mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-11-13 20:53:49 +08:00
fix 修复生成代码 pgsql 菜单权限生成和个别数据类型生成错误,vue 方法导入改为自动导入
This commit is contained in:
@@ -10,14 +10,15 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/hggen/internal/cmd/gendao"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/hggen/internal/cmd/gendao"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
)
|
||||
|
||||
// DoTableColumns 获取指定表生成字段列表
|
||||
@@ -63,11 +64,10 @@ func DoTableColumns(ctx context.Context, in *sysin.GenCodesColumnListInp, config
|
||||
LEFT JOIN pg_constraint pk ON pk.conrelid = c.oid AND pk.contype = 'p' AND a.attnum = ANY(pk.conkey)
|
||||
LEFT JOIN pg_constraint uk ON uk.conrelid = c.oid AND uk.contype = 'u' AND a.attnum = ANY(uk.conkey)
|
||||
WHERE n.nspname = 'public'
|
||||
AND c.relname = '%s'
|
||||
AND c.relname = '` + in.Table + `'
|
||||
AND a.attnum > 0
|
||||
AND NOT a.attisdropped
|
||||
ORDER BY a.attnum`
|
||||
sql = fmt.Sprintf(sql, in.Table)
|
||||
} else {
|
||||
// MySQL: 使用information_schema.COLUMNS
|
||||
sql = fmt.Sprintf("SELECT ORDINAL_POSITION as id, COLUMN_NAME as name, COLUMN_COMMENT as dc, DATA_TYPE as dataType, COLUMN_TYPE as sqlType, CHARACTER_MAXIMUM_LENGTH as length, IS_NULLABLE as isAllowNull, COLUMN_DEFAULT as defaultValue, COLUMN_KEY as `index`, EXTRA as extra FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s' ORDER BY id ASC", conf.Name, in.Table)
|
||||
|
||||
@@ -897,8 +897,14 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
|
||||
"mainComponent": "LAYOUT",
|
||||
}
|
||||
genFile = new(sysin.GenFile)
|
||||
templateName = "source.sql.template"
|
||||
)
|
||||
|
||||
// 根据数据库类型选择不同的模板
|
||||
if config.Type == consts.DBPgsql {
|
||||
templateName = "source_pgsql.sql.template"
|
||||
}
|
||||
|
||||
menus, err := service.AdminMenu().GetFastList(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -993,7 +999,7 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
|
||||
}
|
||||
|
||||
tplData["generatePath"] = genFile.Path
|
||||
genFile.Content, err = in.view.Parse(ctx, name+".template", tplData)
|
||||
genFile.Content, err = in.view.Parse(ctx, templateName, tplData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ func (l *gCurd) generateLogicEdit(ctx context.Context, in *CurdPreviewInput) g.M
|
||||
}
|
||||
|
||||
if field.Unique {
|
||||
uniqueBuffer.WriteString(fmt.Sprintf(LogicEditUnique, field.GoName, in.In.DaoName, in.In.DaoName, field.GoName, field.GoName, field.Dc,in.pk.GoName))
|
||||
uniqueBuffer.WriteString(fmt.Sprintf(LogicEditUnique, field.GoName, in.In.DaoName, in.In.DaoName, field.GoName, field.GoName, field.Dc, in.pk.GoName))
|
||||
}
|
||||
|
||||
// 添加 YAML 格式验证
|
||||
@@ -246,6 +246,8 @@ func (l *gCurd) generateLogicListWhereEach(buffer *bytes.Buffer, in *CurdPreview
|
||||
|
||||
if IsNumberType(field.GoType) {
|
||||
linkMode = `in.` + field.GoName + ` > 0`
|
||||
} else if field.GoType == GoTypeBool {
|
||||
linkMode = `true` // bool 类型始终可以查询
|
||||
} else if field.GoType == GoTypeGTime {
|
||||
linkMode = `in.` + field.GoName + ` != nil`
|
||||
} else if field.GoType == GoTypeJson {
|
||||
@@ -286,12 +288,23 @@ func (l *gCurd) generateLogicListWhereEach(buffer *bytes.Buffer, in *CurdPreview
|
||||
case WhereModeNotBetween:
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "NotBetween(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + "[0], in." + field.GoName + "[1])\n\t}"
|
||||
case WhereModeLike:
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Like(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
|
||||
fieldValue := "in." + field.GoName
|
||||
if field.GoType != GoTypeString && field.GoType != GoTypeBytes {
|
||||
fieldValue = "gconv.String(in." + field.GoName + ")"
|
||||
}
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Like(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", " + fieldValue + ")\n\t}"
|
||||
case WhereModeLikeAll:
|
||||
val := `"%"+in.` + field.GoName + `+"%"`
|
||||
if field.GoType != GoTypeString && field.GoType != GoTypeBytes {
|
||||
val = `"%"+gconv.String(in.` + field.GoName + `)+"%"`
|
||||
}
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Like(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", " + val + ")\n\t}"
|
||||
case WhereModeNotLike:
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "NotLike(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
|
||||
fieldValue := "in." + field.GoName
|
||||
if field.GoType != GoTypeString && field.GoType != GoTypeBytes {
|
||||
fieldValue = "gconv.String(in." + field.GoName + ")"
|
||||
}
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "NotLike(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", " + fieldValue + ")\n\t}"
|
||||
case WhereModeJsonContains:
|
||||
val := tablePrefix + `"JSON_CONTAINS("+dao.` + daoName + `.Columns().` + columnName + `+",?)", in.` + field.GoName
|
||||
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "(" + val + ")\n\t}"
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
@@ -32,7 +33,7 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
|
||||
}
|
||||
|
||||
var (
|
||||
defaultComponent = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input placeholder=\"请输入%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
defaultComponent = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-input\n placeholder=\"请输入%s\"\n v-model:value=\"formValue.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
component string
|
||||
)
|
||||
|
||||
@@ -45,68 +46,69 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
|
||||
component = defaultComponent
|
||||
|
||||
case FormModeInputNumber:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input-number placeholder=\"请输入%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-input-number\n placeholder=\"请输入%s\"\n v-model:value=\"formValue.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
|
||||
case FormModeInputTextarea:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-input type=\"textarea\" placeholder=\"%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-input\n type=\"textarea\"\n placeholder=\"%s\"\n v-model:value=\"formValue.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
|
||||
case FormModeInputEditor:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <Editor style=\"height: 450px\" id=\"%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <Editor style=\"height: 450px\" id=\"%s\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName)
|
||||
|
||||
case FormModeInputYaml:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <YamlEditor ref=\"%sYamlRef\" v-model:value=\"formValue.%s\" :height=\"400\" placeholder=\"请输入%s\" validate-on-blur show-stats prevent-invalid-submit @error=\"handleYamlError\" @valid=\"handleYamlValid\" @validation-change=\"(isValid) => handleYamlValidationChange(isValid, '%s')\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName, field.Dc, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <YamlEditor\n ref=\"%sYamlRef\"\n v-model:value=\"formValue.%s\"\n :height=\"400\"\n placeholder=\"请输入%s\"\n validate-on-blur\n show-stats\n prevent-invalid-submit\n @error=\"handleYamlError\"\n @valid=\"handleYamlValid\"\n @validation-change=\"(isValid) => handleYamlValidationChange(isValid, '%s')\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName, field.Dc, field.TsName)
|
||||
|
||||
case FormModeInputDynamic:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-dynamic-input\n v-model:value=\"formValue.%s\"\n preset=\"pair\"\n key-placeholder=\"键名\"\n value-placeholder=\"键值\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-dynamic-input\n v-model:value=\"formValue.%s\"\n preset=\"pair\"\n key-placeholder=\"键名\"\n value-placeholder=\"键值\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModeDate:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"formValue.%s\" type=\"date\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"formValue.%s\" type=\"date\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
// case FormModeDateRange: // 必须要有两个字段,后面优化下
|
||||
|
||||
case FormModeTime:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"formValue.%s\" type=\"datetime\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <DatePicker v-model:formValue=\"formValue.%s\" type=\"datetime\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
// case FormModeTimeRange: // 必须要有两个字段,后面优化下
|
||||
|
||||
case FormModeRadio:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-radio-group v-model:value=\"formValue.%s\" name=\"%s\">\n <n-radio-button\n v-for=\"%s in dict.getOptionUnRef('%s')\"\n :key=\"%s.value\"\n :value=\"%s.value\"\n :label=\"%s.label\"\n />\n </n-radio-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], field.TsName, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-radio-group v-model:value=\"formValue.%s\" name=\"%s\">\n <n-radio-button\n v-for=\"%s in dict.getOptionUnRef('%s')\"\n :key=\"%s.value\"\n :value=\"%s.value\"\n :label=\"%s.label\"\n />\n </n-radio-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], field.TsName, field.TsName, field.TsName)
|
||||
|
||||
case FormModeCheckbox:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-checkbox-group v-model:value=\"formValue.%s\">\n <n-space>\n <n-checkbox\n v-for=\"item in dict.getOptionUnRef('%s')\"\n :key=\"item.value\"\n :value=\"item.value\"\n :label=\"item.label\"\n />\n </n-space>\n </n-checkbox-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-checkbox-group v-model:value=\"formValue.%s\">\n <n-space>\n <n-checkbox\n v-for=\"item in dict.getOptionUnRef('%s')\"\n :key=\"item.value\"\n :value=\"item.value\"\n :label=\"item.label\"\n />\n </n-space>\n </n-checkbox-group>\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
|
||||
|
||||
case FormModeSelect:
|
||||
if in.options.dictMap[field.TsName] != nil {
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"formValue.%s\" :options=\"dict.getOptionUnRef('%s')\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"formValue.%s\" :options=\"dict.getOptionUnRef('%s')\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
|
||||
} else {
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"formValue.%s\" options=\"\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-select v-model:value=\"formValue.%s\" options=\"\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
}
|
||||
|
||||
case FormModeSelectMultiple:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-select multiple v-model:value=\"formValue.%s\" :options=\"dict.getOptionUnRef('%s')\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-select multiple v-model:value=\"formValue.%s\" :options=\"dict.getOptionUnRef('%s')\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName])
|
||||
|
||||
case FormModeUploadImage:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"1\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"1\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModeUploadImages:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"10\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <UploadImage :maxNumber=\"10\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModeUploadFile:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"1\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"1\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModeUploadFiles:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"10\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <UploadFile :maxNumber=\"10\" v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModeSwitch:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-switch :unchecked-value=\"2\" :checked-value=\"1\" v-model:value=\"formValue.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-switch\n :unchecked-value=\"2\"\n :checked-value=\"1\"\n v-model:value=\"formValue.%s\"\n />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModeRate:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <n-rate allow-half :default-value=\"formValue.%s\" :on-update:value=\"update%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.GoName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <n-rate allow-half :default-value=\"formValue.%s\" :on-update:value=\"update%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName, field.GoName)
|
||||
|
||||
case FormModeCitySelector:
|
||||
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <CitySelector v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf(" <n-form-item label=\"%s\" path=\"%s\">\n <CitySelector v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
|
||||
|
||||
case FormModePidTreeSelect:
|
||||
component = fmt.Sprintf(`<n-form-item label="%v" path="pid">
|
||||
component = fmt.Sprintf(` <n-form-item label="%v" path="pid">
|
||||
<n-tree-select
|
||||
:options="treeOption"
|
||||
v-model:value="formValue.pid"
|
||||
@@ -118,8 +120,9 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
|
||||
show-path
|
||||
/>
|
||||
</n-form-item>`, field.Dc, in.pk.TsName, in.options.Tree.TitleField.TsName)
|
||||
|
||||
case FormModeTreeSelect:
|
||||
component = fmt.Sprintf(`<n-form-item label="%v" path="%v">
|
||||
component = fmt.Sprintf(` <n-form-item label="%v" path="%v">
|
||||
<n-tree-select
|
||||
placeholder="请选择%v"
|
||||
v-model:value="formValue.%v"
|
||||
@@ -129,8 +132,9 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
|
||||
default-expand-all
|
||||
/>
|
||||
</n-form-item>`, field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
|
||||
case FormModeCascader:
|
||||
component = fmt.Sprintf(`<n-form-item label="%v" path="%v">
|
||||
component = fmt.Sprintf(` <n-form-item label="%v" path="%v">
|
||||
<n-cascader
|
||||
placeholder="请选择%v"
|
||||
v-model:value="formValue.%v"
|
||||
@@ -139,11 +143,12 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
|
||||
filterable
|
||||
/>
|
||||
</n-form-item>`, field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
|
||||
default:
|
||||
component = defaultComponent
|
||||
}
|
||||
|
||||
buffer.WriteString(fmt.Sprintf("<n-gi span=\"%v\">%v</n-gi>\n\n", field.FormGridSpan, component))
|
||||
buffer.WriteString(fmt.Sprintf("<n-gi span=\"%v\">\n%v\n </n-gi>\n\n", field.FormGridSpan, component))
|
||||
}
|
||||
return buffer.String()
|
||||
}
|
||||
@@ -156,8 +161,6 @@ func (l *gCurd) generateWebEditScript(ctx context.Context, in *CurdPreviewInput)
|
||||
hasYamlField = false
|
||||
)
|
||||
|
||||
importBuffer.WriteString(" import { ref, computed } from 'vue';\n")
|
||||
|
||||
// 导入字典
|
||||
if in.options.DictOps.Has {
|
||||
importBuffer.WriteString(" import { useDictStore } from '@/store/modules/dict';\n")
|
||||
|
||||
@@ -8,6 +8,7 @@ package views
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
@@ -17,7 +18,7 @@ func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (g.Ma
|
||||
importBuffer = bytes.NewBuffer(nil)
|
||||
importVueMethod = []string{"h", "reactive", "ref", "computed"}
|
||||
importApiMethod = []string{"List"}
|
||||
importModelMethod = []string{"columns", "schemas"}
|
||||
importModelMethod = []string{"columns", "schemas", "State"}
|
||||
importUtilsMethod = []string{"adaTableScrollX"}
|
||||
importIcons []string
|
||||
actionWidth int64 = 72
|
||||
@@ -100,7 +101,6 @@ func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (g.Ma
|
||||
}
|
||||
|
||||
// 导入基础包
|
||||
importBuffer.WriteString(" import " + ImportWebMethod(importVueMethod) + " from 'vue';\n")
|
||||
importBuffer.WriteString(" import { useDialog, useMessage } from 'naive-ui';\n")
|
||||
importBuffer.WriteString(" import { BasicTable, TableAction } from '@/components/Table';\n")
|
||||
importBuffer.WriteString(" import { BasicForm, useForm } from '@/components/Form/index';\n")
|
||||
|
||||
@@ -46,8 +46,6 @@ func (l *gCurd) generateWebModelImport(ctx context.Context, in *CurdPreviewInput
|
||||
importBuffer := bytes.NewBuffer(nil)
|
||||
constBuffer := bytes.NewBuffer(nil)
|
||||
|
||||
importBuffer.WriteString("import { h, ref } from 'vue';\n")
|
||||
|
||||
// 导入基础组件
|
||||
if len(in.options.Step.ImportModel.NaiveUI) > 0 {
|
||||
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.NaiveUI) + " from 'naive-ui';\n")
|
||||
@@ -120,19 +118,25 @@ func (l *gCurd) generateWebModelStateItems(ctx context.Context, in *CurdPreviewI
|
||||
dataType = parts[0]
|
||||
}
|
||||
}
|
||||
|
||||
isStr := isStringType(field.TsType, dataType)
|
||||
isArray := strings.HasPrefix(dataType, "_") || strings.Contains(field.SqlType, "[]")
|
||||
|
||||
var value = field.DefaultValue
|
||||
if value == nil {
|
||||
if isArray {
|
||||
value = "null"
|
||||
}
|
||||
if value == "" {
|
||||
// 修复字符串字段为空时的处理
|
||||
if isStringType(field.TsType, dataType) {
|
||||
value = "" // 模板会自动加引号变成 ''
|
||||
} else if isStr {
|
||||
value = ""
|
||||
} else {
|
||||
value = "null"
|
||||
}
|
||||
} else if valueStr, ok := value.(string); ok && isStringType(field.TsType, dataType) {
|
||||
// 对于字符串类型,直接使用原值,模板会自动加引号
|
||||
}
|
||||
if value == "" {
|
||||
if isArray || !isStr {
|
||||
value = "null"
|
||||
}
|
||||
} else if valueStr, ok := value.(string); ok && isStr {
|
||||
value = valueStr
|
||||
}
|
||||
|
||||
@@ -470,9 +474,14 @@ func isStringType(tsType, dataType string) bool {
|
||||
|
||||
// 根据数据库数据类型判断
|
||||
stringTypes := []string{
|
||||
// mysql
|
||||
"varchar", "char", "text", "longtext", "mediumtext", "tinytext",
|
||||
"nvarchar", "nchar", "ntext",
|
||||
"string", "enum", "set",
|
||||
// pgsql
|
||||
"bpchar", "date", "time", "timetz", "timestamp", "timestamptz", "interval",
|
||||
"uuid", "bytea", "inet", "cidr", "macaddr", "macaddr8", "bit", "varbit", "json", "jsonb",
|
||||
"point", "line", "lseg", "box", "path", "polygon", "circle", "money",
|
||||
}
|
||||
|
||||
for _, t := range stringTypes {
|
||||
@@ -480,6 +489,5 @@ func isStringType(tsType, dataType string) bool {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -9,33 +9,43 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
)
|
||||
|
||||
func (l *gCurd) webViewTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
|
||||
data = make(g.Map)
|
||||
data["item"] = l.generateWebViewItem(ctx, in)
|
||||
item, hasUpload := l.generateWebViewItem(ctx, in)
|
||||
data["item"] = item
|
||||
data["hasUploadFile"] = hasUpload
|
||||
return
|
||||
}
|
||||
|
||||
func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) string {
|
||||
func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) (string, bool) {
|
||||
buffer := bytes.NewBuffer(nil)
|
||||
hasUploadFile := false
|
||||
|
||||
for _, field := range in.masterFields {
|
||||
if !field.IsEdit {
|
||||
continue
|
||||
}
|
||||
|
||||
// 检测是否使用了文件上传相关的组件
|
||||
if field.FormMode == FormModeUploadFile || field.FormMode == FormModeUploadFiles {
|
||||
hasUploadFile = true
|
||||
}
|
||||
|
||||
var (
|
||||
defaultComponent = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n {{ formValue.%s }}\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
defaultComponent = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n {{ formValue.%s }}\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
component string
|
||||
)
|
||||
|
||||
switch field.FormMode {
|
||||
case FormModeInputTextarea, FormModeInputEditor:
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <span v-html=\"formValue.%s\"></span></n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n <span v-html=\"formValue.%s\"></span>\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
case FormModeInputYaml:
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <pre style=\"white-space: pre-wrap; font-family: monospace; background: #f5f5f5; padding: 10px; border-radius: 4px;\">{{ formValue.%s }}</pre></n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n <pre style=\"white-space: pre-wrap; font-family: monospace; background: #f5f5f5; padding: 10px; border-radius: 4px;\">{{ formValue.%s }}</pre>\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
case FormModeInputDynamic:
|
||||
component = defaultComponent
|
||||
@@ -47,28 +57,28 @@ func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) s
|
||||
component = defaultComponent
|
||||
|
||||
case FormModeRadio, FormModeSelect:
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-tag :type=\"dict.getType('%s', formValue.%s)\" size=\"small\" class=\"min-left-space\">{{ dict.getLabel('%s', formValue.%s) }}</n-tag>\n </n-descriptions-item>", field.Dc, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-tag\n :type=\"dict.getType('%s', formValue.%s)\"\n size=\"small\"\n class=\"min-left-space\"\n >\n {{ dict.getLabel('%s', formValue.%s) }}\n </n-tag>\n </n-descriptions-item>", field.Dc, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
|
||||
|
||||
case FormModeCheckbox, FormModeSelectMultiple:
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <template v-for=\"(item, key) in formValue.%s\" :key=\"key\">\n <n-tag :type=\"dict.getType('%s', item)\" size=\"small\" class=\"min-left-space\">{{ dict.getLabel('%s', item) }}</n-tag>\n </template>\n </n-descriptions-item>", field.Dc, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <template v-for=\"(item, key) in formValue.%s\" :key=\"key\">\n <n-tag\n :type=\"dict.getType('%s', item)\"\n size=\"small\"\n class=\"min-left-space\"\n >\n {{ dict.getLabel('%s', item) }}\n </n-tag>\n </template>\n </n-descriptions-item>", field.Dc, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
|
||||
|
||||
case FormModeUploadImage:
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"formValue.%s\"/></n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"formValue.%s\" />\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
case FormModeUploadImages:
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image-group>\n <n-space>\n <span v-for=\"(item, key) in formValue.%s\" :key=\"key\">\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"item\" />\n </span>\n </n-space>\n </n-image-group>\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n <n-image-group>\n <n-space>\n <span v-for=\"(item, key) in formValue.%s\" :key=\"key\">\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"item\" />\n </span>\n </n-space>\n </n-image-group>\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
case FormModeUploadFile:
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div class=\"upload-card\" v-show=\"formValue.%s !== ''\" @click=\"download(formValue.%s)\">\n <div class=\"upload-card-item\" style=\"height: 100px; width: 100px\">\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\">{{ getFileExt(formValue.%s) }}</n-avatar>\n </div>\n </div>\n </div>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName, field.TsName, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n <div class=\"upload-card\" v-show=\"formValue.%s !== ''\" @click=\"download(formValue.%s)\">\n <div class=\"upload-card-item\" style=\"height: 100px; width: 100px\">\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\">{{ getFileExt(formValue.%s) }}</n-avatar>\n </div>\n </div>\n </div>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName, field.TsName, field.TsName)
|
||||
|
||||
case FormModeUploadFiles:
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div class=\"upload-card\">\n <n-space style=\"gap: 0px 0px\">\n <div\n class=\"upload-card-item\"\n style=\"height: 100px; width: 100px\"\n v-for=\"(item, key) in formValue.%s\"\n :key=\"key\"\n >\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\" @click=\"download(item)\">{{\n getFileExt(item)\n }}</n-avatar>\n </div>\n </div>\n </div>\n </n-space>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item>\n <template #label> %s </template>\n <div class=\"upload-card\">\n <n-space style=\"gap: 0px 0px\">\n <div\n class=\"upload-card-item\"\n style=\"height: 100px; width: 100px\"\n v-for=\"(item, key) in formValue.%s\"\n :key=\"key\"\n >\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\" @click=\"download(item)\">\n {{ getFileExt(item) }}\n </n-avatar>\n </div>\n </div>\n </div>\n </n-space>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
case FormModeSwitch:
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-switch v-model:value=\"formValue.%s\" :unchecked-value=\"2\" :checked-value=\"1\" :disabled=\"true\"/></n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-switch\n v-model:value=\"formValue.%s\"\n :unchecked-value=\"2\"\n :checked-value=\"1\"\n :disabled=\"true\"\n />\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
case FormModeRate:
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\"\n ><n-rate readonly :default-value=\"formValue.%s\"\n /></n-descriptions-item>", field.Dc, field.TsName)
|
||||
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-rate readonly :default-value=\"formValue.%s\" />\n </n-descriptions-item>", field.Dc, field.TsName)
|
||||
|
||||
default:
|
||||
component = defaultComponent
|
||||
@@ -76,5 +86,5 @@ func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) s
|
||||
|
||||
buffer.WriteString(" " + component + "\n\n")
|
||||
}
|
||||
return buffer.String()
|
||||
return buffer.String(), hasUploadFile
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ package views
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/util/gutil"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/hggen/views/gohtml"
|
||||
"hotgo/internal/model"
|
||||
@@ -21,10 +20,14 @@ import (
|
||||
"strings"
|
||||
"unicode"
|
||||
|
||||
"github.com/gogf/gf/v2/util/gutil"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gproc"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
@@ -79,8 +82,17 @@ func ImportSql(ctx context.Context, path string) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sqlContent := string(rows)
|
||||
config := g.DB("default").GetConfig()
|
||||
if config.Type == consts.DBPgsql {
|
||||
return importSqlPgsql(ctx, sqlContent)
|
||||
}
|
||||
return importSqlMysql(ctx, sqlContent)
|
||||
}
|
||||
|
||||
sqlArr := strings.Split(string(rows), "\n")
|
||||
// importSqlMysql 导出mysql文件
|
||||
func importSqlMysql(ctx context.Context, sqlContent string) error {
|
||||
sqlArr := strings.Split(sqlContent, "\n")
|
||||
for _, sql := range sqlArr {
|
||||
sql = strings.TrimSpace(sql)
|
||||
if sql == "" || strings.HasPrefix(sql, "--") {
|
||||
@@ -95,6 +107,53 @@ func ImportSql(ctx context.Context, path string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// importSqlPgsql 导出pgsql文件
|
||||
func importSqlPgsql(ctx context.Context, sqlContent string) error {
|
||||
lines := strings.Split(sqlContent, "\n")
|
||||
var currentStmt strings.Builder
|
||||
inDoBlock := false
|
||||
for _, line := range lines {
|
||||
trimmedLine := strings.TrimSpace(line)
|
||||
|
||||
if trimmedLine == "" || strings.HasPrefix(trimmedLine, "--") {
|
||||
continue
|
||||
}
|
||||
|
||||
currentStmt.WriteString(line)
|
||||
currentStmt.WriteString("\n")
|
||||
|
||||
if strings.HasPrefix(trimmedLine, "DO $$") || strings.HasPrefix(trimmedLine, "DO $") {
|
||||
inDoBlock = true
|
||||
continue
|
||||
}
|
||||
|
||||
if inDoBlock && (strings.HasPrefix(trimmedLine, "END $$;") || strings.HasPrefix(trimmedLine, "END $")) {
|
||||
inDoBlock = false
|
||||
stmt := currentStmt.String()
|
||||
exec, err := g.DB().Exec(ctx, stmt)
|
||||
g.Log().Infof(ctx, "importSqlPgsql DO block executed, exec:%+v, err:%+v", exec, err)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "importSqlPgsql error: %v, sql: %s", err, stmt)
|
||||
return err
|
||||
}
|
||||
currentStmt.Reset()
|
||||
continue
|
||||
}
|
||||
|
||||
if !inDoBlock && strings.HasSuffix(trimmedLine, ";") {
|
||||
stmt := currentStmt.String()
|
||||
exec, err := g.DB().Exec(ctx, stmt)
|
||||
g.Log().Infof(ctx, "importSqlPgsql sql executed, exec:%+v, err:%+v", exec, err)
|
||||
if err != nil {
|
||||
g.Log().Errorf(ctx, "importSqlPgsql error: %v, sql: %s", err, stmt)
|
||||
return err
|
||||
}
|
||||
currentStmt.Reset()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkCurdPath(temp *model.GenerateAppCrudTemplate, addonName string) (err error) {
|
||||
if temp == nil {
|
||||
return gerror.New("生成模板配置不能为空")
|
||||
@@ -299,22 +358,182 @@ func FormatGo(ctx context.Context, name, code string) (string, error) {
|
||||
}
|
||||
|
||||
func FormatVue(code string) string {
|
||||
if formatted, ok := tryPrettierFormat(code, "vue"); ok {
|
||||
return formatted
|
||||
}
|
||||
|
||||
endTag := `</template>`
|
||||
vueLen := gstr.PosR(code, endTag)
|
||||
vueCode := code[:vueLen+len(endTag)]
|
||||
tsCode := code[vueLen+len(endTag):]
|
||||
|
||||
vueCode = gohtml.Format(vueCode)
|
||||
vueCode = formatVueTemplate(vueCode)
|
||||
tsCode = FormatTs(tsCode)
|
||||
return vueCode + tsCode
|
||||
}
|
||||
|
||||
func FormatTs(code string) string {
|
||||
if formatted, ok := tryPrettierFormat(code, "typescript"); ok {
|
||||
return formatted
|
||||
}
|
||||
code = replaceEmptyLinesWithSpace(code)
|
||||
code = formatTypeScript(code)
|
||||
return code + "\n"
|
||||
}
|
||||
|
||||
// tryPrettierFormat 尝试使用 Prettier 格式化代码
|
||||
func tryPrettierFormat(code string, parser string) (string, bool) {
|
||||
webDir := gfile.Abs("./web")
|
||||
prettierBin := gfile.Join(webDir, "node_modules", ".bin", "prettier")
|
||||
|
||||
if !gfile.Exists(prettierBin) {
|
||||
return "", false
|
||||
}
|
||||
|
||||
tmpFile := gfile.Temp(gtime.TimestampNanoStr()) + "." + getFileExt(parser)
|
||||
defer gfile.Remove(tmpFile)
|
||||
|
||||
if err := gfile.PutContents(tmpFile, code); err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
cmd := fmt.Sprintf("cd %s && %s --write %s 2>/dev/null", webDir, prettierBin, tmpFile)
|
||||
_, err := gproc.ShellExec(context.Background(), cmd)
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
|
||||
formatted := gfile.GetContents(tmpFile)
|
||||
if formatted == "" {
|
||||
return "", false
|
||||
}
|
||||
return formatted, true
|
||||
}
|
||||
|
||||
// getFileExt 根据 parser 类型返回文件扩展名
|
||||
func getFileExt(parser string) string {
|
||||
switch parser {
|
||||
case "vue":
|
||||
return "vue"
|
||||
case "typescript":
|
||||
return "ts"
|
||||
default:
|
||||
return "txt"
|
||||
}
|
||||
}
|
||||
|
||||
// formatVueTemplate 格式化 Vue 模板代码
|
||||
func formatVueTemplate(code string) string {
|
||||
lines := strings.Split(code, "\n")
|
||||
var result []string
|
||||
lastLineWasOpenTag := false
|
||||
|
||||
for _, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if lastLineWasOpenTag && trimmed == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
if strings.HasPrefix(trimmed, "<") && !strings.HasPrefix(trimmed, "</") &&
|
||||
!strings.HasSuffix(trimmed, "/>") && !strings.HasSuffix(trimmed, ">") &&
|
||||
!strings.HasPrefix(trimmed, "<!--") {
|
||||
lastLineWasOpenTag = true
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
lastLineWasOpenTag = false
|
||||
if trimmed == "/>" {
|
||||
if len(result) > 0 {
|
||||
prevLine := result[len(result)-1]
|
||||
re := regexp.MustCompile(`^(\s*)`)
|
||||
matches := re.FindStringSubmatch(prevLine)
|
||||
if len(matches) > 1 {
|
||||
line = matches[1] + "/>"
|
||||
}
|
||||
}
|
||||
} else if strings.Contains(line, "/>") {
|
||||
re := regexp.MustCompile(`\s*/>`)
|
||||
line = re.ReplaceAllString(line, " />")
|
||||
}
|
||||
|
||||
if strings.HasPrefix(trimmed, "<") && !strings.HasPrefix(trimmed, "</") &&
|
||||
!strings.HasPrefix(trimmed, "<!--") && len(trimmed) > 100 {
|
||||
line = formatLongVueTag(line)
|
||||
}
|
||||
result = append(result, line)
|
||||
}
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
// formatLongVueTag 格式化过长的 Vue 标签
|
||||
func formatLongVueTag(line string) string {
|
||||
re := regexp.MustCompile(`\s+`)
|
||||
parts := strings.SplitN(line, ">", 2)
|
||||
if len(parts) == 2 {
|
||||
tagPart := re.ReplaceAllString(parts[0], " ")
|
||||
tagPart = strings.TrimSpace(tagPart)
|
||||
return tagPart + ">" + parts[1]
|
||||
}
|
||||
return line
|
||||
}
|
||||
|
||||
// formatTypeScript 格式化 TypeScript 代码
|
||||
func formatTypeScript(code string) string {
|
||||
lines := strings.Split(code, "\n")
|
||||
var result []string
|
||||
inClass := false
|
||||
lastWasField := false
|
||||
|
||||
for i, line := range lines {
|
||||
trimmed := strings.TrimSpace(line)
|
||||
if strings.HasPrefix(trimmed, "export class") {
|
||||
inClass = true
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if inClass && (strings.HasPrefix(trimmed, "constructor(") ||
|
||||
strings.HasPrefix(trimmed, "public ") && strings.Contains(trimmed, "(")) {
|
||||
if lastWasField && len(result) > 0 {
|
||||
result = append(result, "")
|
||||
}
|
||||
inClass = false
|
||||
lastWasField = false
|
||||
result = append(result, line)
|
||||
continue
|
||||
}
|
||||
|
||||
if inClass && strings.HasPrefix(trimmed, "public ") && strings.Contains(trimmed, "=") {
|
||||
if lastWasField && len(result) > 0 && strings.TrimSpace(result[len(result)-1]) == "" {
|
||||
result = result[:len(result)-1]
|
||||
}
|
||||
result = append(result, line)
|
||||
lastWasField = true
|
||||
continue
|
||||
}
|
||||
|
||||
if trimmed == "}" && lastWasField {
|
||||
result = append(result, "")
|
||||
lastWasField = false
|
||||
}
|
||||
|
||||
if trimmed == "" {
|
||||
if inClass && lastWasField {
|
||||
continue
|
||||
}
|
||||
if i > 0 && len(result) > 0 && strings.TrimSpace(result[len(result)-1]) == "" {
|
||||
continue
|
||||
}
|
||||
}
|
||||
result = append(result, line)
|
||||
}
|
||||
return strings.Join(result, "\n")
|
||||
}
|
||||
|
||||
func replaceEmptyLinesWithSpace(input string) string {
|
||||
re := regexp.MustCompile(`\n\s*\n`)
|
||||
re := regexp.MustCompile(`\n\s*\n\s*\n+`)
|
||||
result := re.ReplaceAllString(input, "\n\n")
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
-- hotgo自动生成菜单权限SQL 通常情况下只在首次生成代码时自动执行一次
|
||||
-- 如需再次执行请先手动删除生成的菜单权限和SQL文件:@{.generatePath}
|
||||
-- Version: @{.hgVersion}
|
||||
-- Date: @{.nowTime}
|
||||
-- Link https://github.com/bufanyun/hotgo
|
||||
|
||||
--
|
||||
-- 数据库: "@{.dbName}"
|
||||
--
|
||||
|
||||
-- --------------------------------------------------------
|
||||
|
||||
--
|
||||
-- 插入表中的数据 "@{.menuTable}"
|
||||
--
|
||||
|
||||
DO $$
|
||||
DECLARE
|
||||
dir_id bigint;
|
||||
list_id bigint;
|
||||
edit_id bigint;
|
||||
BEGIN
|
||||
-- 菜单目录
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES ('@{.options.Menu.Pid}', '@{.tableComment}', '@{.varName | LcFirst}', '/@{.varName | LcFirst}', '@{.options.Menu.Icon}', '1', '@{.pageRedirect}', '', '', '@{.mainComponent}', '1', '', '0', '0', '', '0', '0', '0', '@{.dirLevel}', '@{.dirTree}', '@{.options.Menu.Sort}', '', '1', now(), now())
|
||||
RETURNING id INTO dir_id;
|
||||
|
||||
-- 菜单页面
|
||||
-- 列表
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (dir_id, '@{.tableComment}列表', '@{.varName | LcFirst}Index', 'index', '', '2', '', '/@{.apiPrefix}/list', '', '/@{.componentPrefix}/index', '1', '@{.varName | LcFirst}', '0', '0', '', '0', '1', '0', '@{.listLevel}', '@{.dirTree}tr_' || dir_id || ' ', '10', '', '1', now(), now())
|
||||
RETURNING id INTO list_id;
|
||||
@{ if or (eq .options.Step.HasView true) (eq .options.Step.HasEdit true) }
|
||||
|
||||
-- 详情
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '@{.tableComment}详情', '@{.varName | LcFirst}View', '', '', '3', '', '/@{.apiPrefix}/view', '', '', '1', '', '0', '0', '', '0', '1', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '10', '', '1', now(), now());
|
||||
@{end}
|
||||
|
||||
-- 菜单按钮
|
||||
@{ if eq .options.Step.HasEdit true }
|
||||
-- 编辑
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '编辑/新增@{.tableComment}', '@{.varName | LcFirst}Edit', '', '', '3', '', '/@{.apiPrefix}/edit', '', '', '1', '', '0', '0', '', '0', '1', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '20', '', '1', now(), now())
|
||||
RETURNING id INTO edit_id;
|
||||
@{end}
|
||||
@{ if and (eq .options.Step.HasEdit true) (eq .options.Step.HasMaxSort true) }
|
||||
|
||||
-- 获取最大排序
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (edit_id, '获取@{.tableComment}最大排序', '@{.varName | LcFirst}MaxSort', '', '', '3', '', '/@{.apiPrefix}/maxSort', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.sortLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' tr_' || edit_id || ' ', '30', '', '1', now(), now());
|
||||
@{end}
|
||||
@{ if eq .options.Step.HasDel true }
|
||||
|
||||
-- 删除
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '删除@{.tableComment}', '@{.varName | LcFirst}Delete', '', '', '3', '', '/@{.apiPrefix}/delete', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '40', '', '1', now(), now());
|
||||
@{end}
|
||||
@{ if eq .options.Step.HasStatus true }
|
||||
|
||||
-- 更新状态
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '修改@{.tableComment}状态', '@{.varName | LcFirst}Status', '', '', '3', '', '/@{.apiPrefix}/status', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '50', '', '1', now(), now());
|
||||
@{end}
|
||||
@{ if eq .options.Step.HasSwitch true }
|
||||
|
||||
-- 操作开关
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '操作@{.tableComment}开关', '@{.varName | LcFirst}Switch', '', '', '3', '', '/@{.apiPrefix}/switch', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '60', '', '1', now(), now());
|
||||
@{end}
|
||||
@{ if eq .options.Step.HasExport true }
|
||||
|
||||
-- 导出
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '导出@{.tableComment}', '@{.varName | LcFirst}Export', '', '', '3', '', '/@{.apiPrefix}/export', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '70', '', '1', now(), now());
|
||||
@{end}
|
||||
@{ if eq .options.Step.IsTreeTable true }
|
||||
|
||||
-- 关系树选项
|
||||
INSERT INTO "@{.menuTable}" ("pid", "title", "name", "path", "icon", "type", "redirect", "permissions", "permission_name", "component", "always_show", "active_menu", "is_root", "is_frame", "frame_src", "keep_alive", "hidden", "affix", "level", "tree", "sort", "remark", "status", "created_at", "updated_at")
|
||||
VALUES (list_id, '获取@{.tableComment}关系树选项', '@{.varName | LcFirst}TreeOption', '', '', '3', '', '/@{.apiPrefix}/treeOption', '', '', '1', '', '0', '0', '', '0', '0', '0', '@{.btnLevel}', '@{.dirTree}tr_' || dir_id || ' tr_' || list_id || ' ', '70', '', '1', now(), now());
|
||||
@{end}
|
||||
END $$;
|
||||
|
||||
@@ -21,7 +21,10 @@
|
||||
:label-width="100"
|
||||
class="py-4"
|
||||
>
|
||||
<n-grid cols="1 s:1 m:@{.options.PresetStep.FormGridCols} l:@{.options.PresetStep.FormGridCols} xl:@{.options.PresetStep.FormGridCols} 2xl:@{.options.PresetStep.FormGridCols}" responsive="screen">
|
||||
<n-grid
|
||||
cols="1 s:1 m:@{.options.PresetStep.FormGridCols} l:@{.options.PresetStep.FormGridCols} xl:@{.options.PresetStep.FormGridCols} 2xl:@{.options.PresetStep.FormGridCols}"
|
||||
responsive="screen"
|
||||
>
|
||||
@{.formItem}
|
||||
</n-grid>
|
||||
</n-form>
|
||||
|
||||
@@ -27,7 +27,13 @@
|
||||
@{end}
|
||||
|
||||
@{ if eq .options.Step.HasEdit true }
|
||||
<n-button v-if="hasPermission(['/@{.apiPrefix}/edit'])" type="info" icon-placement="left" @click="handleEdit(selectedState)" :disabled="selectedState.@{.pk.TsName} < 1">
|
||||
<n-button
|
||||
v-if="hasPermission(['/@{.apiPrefix}/edit'])"
|
||||
type="info"
|
||||
icon-placement="left"
|
||||
@click="handleEdit(selectedState)"
|
||||
:disabled="selectedState.@{.pk.TsName} < 1"
|
||||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center">
|
||||
<n-icon size="14">
|
||||
@@ -40,7 +46,13 @@
|
||||
@{end}
|
||||
|
||||
@{ if eq .options.Step.HasBatchDel true }
|
||||
<n-button v-if="hasPermission(['/@{.apiPrefix}/delete'])" type="error" icon-placement="left" @click="handleDelete(selectedState)" :disabled="selectedState.@{.pk.TsName} < 1">
|
||||
<n-button
|
||||
v-if="hasPermission(['/@{.apiPrefix}/delete'])"
|
||||
type="error"
|
||||
icon-placement="left"
|
||||
@click="handleDelete(selectedState)"
|
||||
:disabled="selectedState.@{.pk.TsName} < 1"
|
||||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center">
|
||||
<n-icon size="14">
|
||||
@@ -78,7 +90,21 @@
|
||||
<n-spin size="medium" />
|
||||
</div>
|
||||
</template>
|
||||
<n-tree v-else show-line block-line cascade virtual-scroll :pattern="pattern" :data="treeOption" :expandedKeys="expandedKeys" style="height: 75vh" key-field="@{.pk.TsName}" label-field="@{.options.Tree.TitleField.TsName}" @update:selected-keys="handleSelected" @update:expanded-keys="handleOnExpandedKeys" />
|
||||
<n-tree
|
||||
v-else
|
||||
show-line
|
||||
block-line
|
||||
cascade
|
||||
virtual-scroll
|
||||
:pattern="pattern"
|
||||
:data="treeOption"
|
||||
:expandedKeys="expandedKeys"
|
||||
style="height: 75vh"
|
||||
key-field="@{.pk.TsName}"
|
||||
label-field="@{.options.Tree.TitleField.TsName}"
|
||||
@update:selected-keys="handleSelected"
|
||||
@update:expanded-keys="handleOnExpandedKeys"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</n-card>
|
||||
@@ -95,7 +121,13 @@
|
||||
</template>
|
||||
<n-result v-show="selectedState.@{.pk.TsName} < 1" status="info" title="提示" description="请先从列表选择一项后,进行编辑">
|
||||
<template #footer>
|
||||
<n-button type="info" icon-placement="left" @{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"@{end} @{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"@{end} v-if="hasPermission(['/@{.apiPrefix}/edit'])">
|
||||
<n-button
|
||||
type="info"
|
||||
icon-placement="left"
|
||||
@{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"
|
||||
@{end}@{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"
|
||||
@{end}v-if="hasPermission(['/@{.apiPrefix}/edit'])"
|
||||
>
|
||||
<template #icon>
|
||||
<div class="flex items-center">
|
||||
<n-icon size="14">
|
||||
@@ -110,18 +142,47 @@
|
||||
@{end}
|
||||
|
||||
@{ if eq .isSearchForm true }
|
||||
<BasicForm @{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"@{end} ref="searchFormRef" @register="register" @submit="reloadTable" @reset="reloadTable" @keyup.enter="reloadTable">
|
||||
<BasicForm
|
||||
@{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"
|
||||
@{end}ref="searchFormRef"
|
||||
@register="register"
|
||||
@submit="reloadTable"
|
||||
@reset="reloadTable"
|
||||
@keyup.enter="reloadTable"
|
||||
>
|
||||
<template #statusSlot="{ model, field }">
|
||||
<n-input v-model:value="model[field]" />
|
||||
</template>
|
||||
</BasicForm>
|
||||
@{end}
|
||||
|
||||
<BasicTable @{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"@{end} ref="actionRef" @{ if eq .options.Step.HasCheck true }openChecked@{end} :columns="columns" :request="loadDataTable" :row-key="(row) => row.@{.pk.TsName}" :actionColumn="actionColumn" :scroll-x="scrollX" :resizeHeightOffset="-10000" @{ if and (eq .options.Step.IsTreeTable true) (eq .options.Step.IsOptionTreeTable false) }:cascade="false" :expanded-row-keys="expandedKeys" @update:expanded-row-keys="updateExpandedKeys"@{end} @{ if eq .options.Step.HasCheck true }:checked-row-keys="checkedIds"@{end} @{ if eq .options.Step.HasCheck true }@update:checked-row-keys="handleOnCheckedRow"@{end}>
|
||||
<BasicTable
|
||||
@{ if eq .options.Step.IsOptionTreeTable true }v-if="selectedState.@{.pk.TsName} > 0"
|
||||
@{end}ref="actionRef"
|
||||
@{ if eq .options.Step.HasCheck true }openChecked
|
||||
@{end}:columns="columns"
|
||||
:request="loadDataTable"
|
||||
:row-key="(row) => row.@{.pk.TsName}"
|
||||
:actionColumn="actionColumn"
|
||||
:scroll-x="scrollX"
|
||||
:resizeHeightOffset="-10000"
|
||||
@{ if and (eq .options.Step.IsTreeTable true) (eq .options.Step.IsOptionTreeTable false) }:cascade="false"
|
||||
:expanded-row-keys="expandedKeys"
|
||||
@update:expanded-row-keys="updateExpandedKeys"
|
||||
@{end}@{ if eq .options.Step.HasCheck true }:checked-row-keys="checkedIds"
|
||||
@{end}@{ if eq .options.Step.HasCheck true }@update:checked-row-keys="handleOnCheckedRow"
|
||||
@{end}
|
||||
>
|
||||
<template #tableTitle>
|
||||
|
||||
@{ if eq .options.Step.HasAdd true }
|
||||
<n-button type="primary" @{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"@{end} @{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"@{end} class="min-left-space" v-if="hasPermission(['/@{.apiPrefix}/edit'])">
|
||||
<n-button
|
||||
type="primary"
|
||||
@{ if eq .options.Step.IsOptionTreeTable true }@click="handleAdd(selectedState)"
|
||||
@{end}@{ if eq .options.Step.IsOptionTreeTable false }@click="addTable"
|
||||
@{end}class="min-left-space"
|
||||
v-if="hasPermission(['/@{.apiPrefix}/edit'])"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<PlusOutlined />
|
||||
@@ -132,7 +193,12 @@
|
||||
@{end}
|
||||
|
||||
@{ if eq .options.Step.HasBatchDel true }
|
||||
<n-button type="error" @click="handleBatchDelete" class="min-left-space" v-if="hasPermission(['/@{.apiPrefix}/delete'])">
|
||||
<n-button
|
||||
type="error"
|
||||
@click="handleBatchDelete"
|
||||
class="min-left-space"
|
||||
v-if="hasPermission(['/@{.apiPrefix}/delete'])"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<DeleteOutlined />
|
||||
@@ -143,7 +209,12 @@
|
||||
@{end}
|
||||
|
||||
@{ if eq .options.Step.HasExport true }
|
||||
<n-button type="primary" @click="handleExport" class="min-left-space" v-if="hasPermission(['/@{.apiPrefix}/export'])">
|
||||
<n-button
|
||||
type="primary"
|
||||
@click="handleExport"
|
||||
class="min-left-space"
|
||||
v-if="hasPermission(['/@{.apiPrefix}/export'])"
|
||||
>
|
||||
<template #icon>
|
||||
<n-icon>
|
||||
<ExportOutlined />
|
||||
|
||||
@@ -3,16 +3,8 @@
|
||||
@{.const}
|
||||
|
||||
export class State {
|
||||
@{range .stateItems}
|
||||
public @{.Name} = @{if and .DataType (or
|
||||
(eq .DataType "varchar")
|
||||
(eq .DataType "char")
|
||||
(eq .DataType "text")
|
||||
(eq .DataType "json")
|
||||
(eq .DataType "date")
|
||||
(eq .DataType "datetime")
|
||||
(eq .DataType "TIMESTAMP")
|
||||
)}'@{.DefaultValue}'@{else}@{.DefaultValue}@{end};//@{.Dc}@{end}
|
||||
@{range .stateItems} public @{.Name} = @{if and .DataType (or (eq .DataType "varchar") (eq .DataType "char") (eq .DataType "bpchar") (eq .DataType "text") (eq .DataType "json") (eq .DataType "jsonb") (eq .DataType "date") (eq .DataType "time") (eq .DataType "timetz") (eq .DataType "datetime") (eq .DataType "timestamp") (eq .DataType "timestamptz") (eq .DataType "TIMESTAMP") (eq .DataType "interval") (eq .DataType "uuid") (eq .DataType "bytea") (eq .DataType "inet") (eq .DataType "cidr") (eq .DataType "macaddr") (eq .DataType "macaddr8") (eq .DataType "bit") (eq .DataType "varbit") (eq .DataType "point") (eq .DataType "line") (eq .DataType "lseg") (eq .DataType "box") (eq .DataType "path") (eq .DataType "polygon") (eq .DataType "circle") (eq .DataType "money")) (ne .DefaultValue "null")}'@{.DefaultValue}'@{else}@{.DefaultValue}@{end}; // @{.Dc}
|
||||
@{end}
|
||||
constructor(state?: Partial<State>) {
|
||||
if (state) {
|
||||
Object.assign(this, state);
|
||||
|
||||
@@ -13,13 +13,12 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { useMessage } from 'naive-ui';
|
||||
import { View } from '@{.importWebApi}';
|
||||
import { State, newState } from './model';
|
||||
import { adaModalWidth } from '@/utils/hotgo';
|
||||
import { getFileExt } from '@/utils/urlUtils';
|
||||
@{ if eq .options.DictOps.Has true }import { useDictStore } from '@/store/modules/dict';@{end}
|
||||
@{ if eq .hasUploadFile true }import { getFileExt } from '@/utils/urlUtils';
|
||||
@{end}@{ if eq .options.DictOps.Has true }import { useDictStore } from '@/store/modules/dict';@{end}
|
||||
|
||||
const message = useMessage();
|
||||
@{ if eq .options.DictOps.Has true }const dict = useDictStore();@{end}
|
||||
@@ -29,7 +28,7 @@
|
||||
const dialogWidth = computed(() => {
|
||||
return adaModalWidth(580);
|
||||
});
|
||||
const fileAvatarCSS = computed(() => {
|
||||
@{ if eq .hasUploadFile true }const fileAvatarCSS = computed(() => {
|
||||
return {
|
||||
'--n-merged-size': `var(--n-avatar-size-override, 80px)`,
|
||||
'--n-font-size': `18px`,
|
||||
@@ -40,6 +39,7 @@
|
||||
function download(url: string) {
|
||||
window.open(url);
|
||||
}
|
||||
@{end}
|
||||
|
||||
// 打开模态框
|
||||
function openModal(state: State) {
|
||||
|
||||
Reference in New Issue
Block a user