mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-11-14 05:03: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)
|
||||
|
||||
@@ -896,9 +896,15 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
|
||||
"menuTable": config.Prefix + "admin_menu",
|
||||
"mainComponent": "LAYOUT",
|
||||
}
|
||||
genFile = new(sysin.GenFile)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -99,10 +99,10 @@ func (l *gCurd) generateLogicSwitchFields(ctx context.Context, in *CurdPreviewIn
|
||||
|
||||
func (l *gCurd) generateLogicEdit(ctx context.Context, in *CurdPreviewInput) g.Map {
|
||||
var (
|
||||
data = make(g.Map)
|
||||
updateBuffer = bytes.NewBuffer(nil)
|
||||
insertBuffer = bytes.NewBuffer(nil)
|
||||
uniqueBuffer = bytes.NewBuffer(nil)
|
||||
data = make(g.Map)
|
||||
updateBuffer = bytes.NewBuffer(nil)
|
||||
insertBuffer = bytes.NewBuffer(nil)
|
||||
uniqueBuffer = bytes.NewBuffer(nil)
|
||||
validationBuffer = bytes.NewBuffer(nil)
|
||||
)
|
||||
|
||||
@@ -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,105 +46,109 @@ 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">
|
||||
<n-tree-select
|
||||
:options="treeOption"
|
||||
v-model:value="formValue.pid"
|
||||
key-field="%v"
|
||||
label-field="%v"
|
||||
clearable
|
||||
filterable
|
||||
default-expand-all
|
||||
show-path
|
||||
/>
|
||||
</n-form-item>`, field.Dc, in.pk.TsName, in.options.Tree.TitleField.TsName)
|
||||
component = fmt.Sprintf(` <n-form-item label="%v" path="pid">
|
||||
<n-tree-select
|
||||
:options="treeOption"
|
||||
v-model:value="formValue.pid"
|
||||
key-field="%v"
|
||||
label-field="%v"
|
||||
clearable
|
||||
filterable
|
||||
default-expand-all
|
||||
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">
|
||||
<n-tree-select
|
||||
placeholder="请选择%v"
|
||||
v-model:value="formValue.%v"
|
||||
:options="[{ label: 'AA', key: 1, children: [{ label: 'BB', key: 2 }] }]"
|
||||
clearable
|
||||
filterable
|
||||
default-expand-all
|
||||
/>
|
||||
</n-form-item>`, field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
component = fmt.Sprintf(` <n-form-item label="%v" path="%v">
|
||||
<n-tree-select
|
||||
placeholder="请选择%v"
|
||||
v-model:value="formValue.%v"
|
||||
:options="[{ label: 'AA', key: 1, children: [{ label: 'BB', key: 2 }] }]"
|
||||
clearable
|
||||
filterable
|
||||
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">
|
||||
<n-cascader
|
||||
placeholder="请选择%v"
|
||||
v-model:value="formValue.%v"
|
||||
:options="[{ label: 'AA', value: 1, children: [{ label: 'BB', value: 2 }] }]"
|
||||
clearable
|
||||
filterable
|
||||
/>
|
||||
</n-form-item>`, field.Dc, field.TsName, field.Dc, field.TsName)
|
||||
component = fmt.Sprintf(` <n-form-item label="%v" path="%v">
|
||||
<n-cascader
|
||||
placeholder="请选择%v"
|
||||
v-model:value="formValue.%v"
|
||||
:options="[{ label: 'AA', value: 1, children: [{ label: 'BB', value: 2 }] }]"
|
||||
clearable
|
||||
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 {
|
||||
value = "null"
|
||||
}
|
||||
if value == "" {
|
||||
// 修复字符串字段为空时的处理
|
||||
if isStringType(field.TsType, dataType) {
|
||||
value = "" // 模板会自动加引号变成 ''
|
||||
if isArray {
|
||||
value = "null"
|
||||
} 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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user