| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624 |
- package com_model_service
- import (
- "encoding/json"
- "gfast/app/model/admin/model_fields"
- "gfast/app/model/admin/model_info"
- "gfast/app/model/admin/sys_dict_type"
- "gfast/library/utils"
- "github.com/gogf/gf/container/garray"
- "github.com/gogf/gf/database/gdb"
- "github.com/gogf/gf/encoding/gjson"
- "github.com/gogf/gf/errors/gerror"
- "github.com/gogf/gf/frame/g"
- "github.com/gogf/gf/net/ghttp"
- "github.com/gogf/gf/os/gtime"
- "github.com/gogf/gf/text/gstr"
- "github.com/gogf/gf/util/gconv"
- )
- //通过模型ID获取模型字段规则
- func GetModelRuleByModelId(r *ghttp.Request, modelId int64, masterId int64) (rules []*model_fields.FieldRule, err error) {
- //1.获取模型信息
- modelInfo, err := model_info.GetByID(modelId)
- if err != nil {
- return
- }
- //获取模型字段信息
- args := &model_fields.SelectPageReq{
- ModelId: modelId,
- }
- //2.字段信息
- modelFields, err := model_fields.SelectListAll(args)
- if err != nil {
- return
- }
- //3.获取字段数据
- //表前缀
- dbPrefix := g.DB().GetPrefix()
- var fieldData gdb.Record
- if masterId != 0 {
- fieldData, err = g.DB().Table(dbPrefix+modelInfo.ModelName).Where(modelInfo.ModelPk, masterId).FindOne()
- if err != nil {
- g.Log().Error(err)
- err = gerror.New("获取模型字段数据失败")
- return
- }
- }
- //获取可编辑字段
- fieldEdit := garray.NewStrArrayFrom(gstr.Split(modelInfo.ModelEdit, ","))
- for _, field := range modelFields {
- rule := &model_fields.FieldRule{
- FOptions: g.List{},
- FAttr: g.Map{},
- FProps: g.Map{},
- FValidate: make([]model_fields.Validate, 0),
- }
- fAttr := g.Map{}
- //主键跳过不在表单显示
- if field.FieldName == modelInfo.ModelPk {
- continue
- }
- //过滤不可编辑字段
- if !fieldEditAble(field.FieldName, fieldEdit) {
- continue
- }
- //字段规则
- fieldRules := garray.NewStrArrayFrom(gstr.Split(field.FieldRules, ","))
- //隐藏字段处理
- if fieldRules.Contains("hidden") {
- continue
- }
- rule.FField = field.FieldName
- rule.FTitle = field.FieldTitle
- rule.FValue = field.FieldDefault
- //必填验证
- if fieldRules.Contains("required") {
- validate := model_fields.Validate{
- VType: "string",
- VRequired: true,
- VMessage: rule.FTitle + "不能为空",
- VTrigger: "blur",
- }
- rule.FValidate = append(rule.FValidate, validate)
- }
- //只读规则
- if fieldRules.Contains("fAttr") {
- fAttr["readonly"] = true
- }
- switch field.FieldType {
- case "baidu_map":
- case "text":
- rule.FType = "input"
- if fieldData != nil {
- rule.FValue = fieldData[field.FieldName]
- }
- case "number", "large_number", "currency":
- rule.FType = "inputNumber"
- //非负
- if fieldRules.Contains("unsigned") {
- validate := model_fields.Validate{
- VType: "number",
- VRequired: true,
- VMin: 0,
- VMessage: rule.FTitle + "不能为负数",
- }
- rule.FValidate = append(rule.FValidate, validate)
- }
- if fieldData != nil {
- rule.FValue = fieldData[field.FieldName]
- }
- case "datetime":
- rule.FType = "DatePicker"
- rule.FProps = g.Map{
- "type": "datetime",
- "format": "yyyy-MM-dd HH:mm:ss",
- "placeholder": "请选择" + field.FieldTitle,
- }
- if fieldData != nil {
- rule.FValue = utils.TimeStampToDateTime(gconv.Int64(fieldData[field.FieldName]))
- } else if field.FieldDefault == "" {
- rule.FValue = gtime.Now().Format("Y-m-d H:i:s")
- }
- case "date":
- rule.FType = "DatePicker"
- rule.FProps = g.Map{
- "format": "yyyy-MM-dd",
- "placeholder": "请选择" + field.FieldTitle,
- }
- if fieldData != nil {
- rule.FValue = utils.TimeStampToDate(gconv.Int64(fieldData[field.FieldName]))
- } else if field.FieldDefault == "" {
- rule.FValue = gtime.Now().Format("Y-m-d")
- }
- case "switch":
- rule.FType = "switch"
- rule.FProps = g.Map{
- "activeValue": "1",
- "inactiveValue": "0",
- }
- if fieldData != nil {
- rule.FValue = fieldData[field.FieldName]
- }
- case "bigtext":
- rule.FType = "input"
- rule.FProps = g.Map{
- "type": "textarea",
- "placeholder": "请输入" + field.FieldTitle,
- "rows": 5,
- }
- if fieldData != nil {
- rule.FValue = fieldData[field.FieldName]
- }
- case "richtext":
- rule.FType = "Editor"
- if fieldData != nil {
- rule.FValue = fieldData[field.FieldName]
- }
- case "selectnumber", "selecttext":
- rule.FType = "select"
- rule.FOptions, err = fieldOptionConv(field.FieldData)
- if err != nil {
- return
- }
- for k, _ := range rule.FValidate {
- rule.FValidate[k].VTrigger = "change"
- }
- if fieldData != nil {
- rule.FValue = gconv.String(fieldData[field.FieldName])
- }
- case "checkbox":
- rule.FType = "checkbox"
- if fieldData != nil {
- rule.FValue = gstr.Split(gconv.String(fieldData[field.FieldName]), ",")
- } else {
- if field.FieldDefault != "" {
- rule.FValue = gstr.Split(field.FieldDefault, ",")
- } else {
- rule.FValue = g.Slice{}
- }
- }
- rule.FOptions, err = fieldOptionConv(field.FieldData)
- if err != nil {
- return
- }
- for k, _ := range rule.FValidate {
- rule.FValidate[k].VType = "array"
- rule.FValidate[k].VTrigger = "change"
- }
- case "file", "files":
- rule.FType = "upFile"
- if fieldData != nil {
- type fileMap map[string]interface{}
- var filesSlice []fileMap
- filesByte := gconv.Bytes(fieldData[field.FieldName])
- if len(filesByte) > 0 {
- err = json.Unmarshal(filesByte, &filesSlice)
- if err != nil {
- g.Log().Error(err)
- err = gerror.New("获取附件信息失败")
- return
- }
- }
- for k, fm := range filesSlice {
- filesSlice[k]["url"], err = utils.GetRealFilesUrl(r, gconv.String(fm["url"]))
- if err != nil {
- return
- }
- }
- rule.FValue = filesSlice
- } else {
- if field.FieldDefault != "" {
- rule.FValue = gjson.New(field.FieldDefault)
- } else {
- rule.FValue = g.Slice{}
- }
- }
- limit := 1
- multiple := false
- if field.FieldType == "files" {
- limit = 6
- multiple = true
- }
- rule.FProps = g.Map{
- "type": "select",
- "uploadType": "file",
- "action": "/system/upload/upFile",
- "name": "file",
- "multiple": multiple,
- "limit": limit,
- }
- case "imagefile", "images":
- rule.FType = "upload"
- limit := 1
- multiple := false
- if field.FieldType == "images" {
- limit = 6
- multiple = true
- if fieldData != nil {
- imgStr := gconv.String(fieldData[field.FieldName])
- if imgStr != "" {
- imgs := gstr.Split(imgStr, ",")
- for k, img := range imgs {
- imgs[k], err = utils.GetRealFilesUrl(r, img)
- if err != nil {
- return
- }
- }
- rule.FValue = imgs
- } else {
- rule.FValue = g.Slice{}
- }
- } else {
- if field.FieldDefault != "" {
- rule.FValue = gstr.Split(field.FieldDefault, ",")
- } else {
- rule.FValue = g.Slice{}
- }
- }
- } else {
- if fieldData != nil {
- imgStr := gconv.String(fieldData[field.FieldName])
- if imgStr != "" {
- rule.FValue, err = utils.GetRealFilesUrl(r, imgStr)
- if err != nil {
- return
- }
- } else {
- rule.FValue = ""
- }
- } else {
- if field.FieldDefault != "" {
- rule.FValue = field.FieldDefault
- } else {
- rule.FValue = ""
- }
- }
- }
- rule.FProps = g.Map{
- "type": "select",
- "uploadType": "image",
- "action": "/system/upload/upImg",
- "name": "file",
- "multiple": multiple,
- "accept": "image/*",
- "limit": limit,
- }
- case "DepartmentSelector":
- rule.FType = "DepartmentSelector"
- if fieldData != nil {
- rule.FValue = gstr.Split(gconv.String(fieldData[field.FieldName]), ",")
- } else {
- if field.FieldDefault != "" {
- rule.FValue = gstr.Split(field.FieldDefault, ",")
- } else {
- rule.FValue = g.Slice{}
- }
- }
- rule.FProps = g.Map{
- "dataListApi": "/api/v1/govWork/options/getDepartmentSelector",
- }
- default:
- err = gerror.New("未知字段" + field.FieldName + ",类型:" + field.FieldType)
- return
- }
- rule.FAttr = fAttr
- rules = append(rules, rule)
- }
- return
- }
- //保存模型字段数据
- //modelId 模型ID
- //data 字段数据
- //masterId 主表主键ID
- func HandlePostData(modelId int64, data g.Map, masterId int64, tx *gdb.TX, isUpdate bool) (err error) {
- //表前缀
- dbPrefix := g.DB().GetPrefix()
- //1.获取模型信息
- modelInfo, err := model_info.GetByID(modelId)
- if err != nil {
- return
- }
- //获取模型字段信息
- //字段信息
- args := &model_fields.SelectPageReq{
- ModelId: modelId,
- }
- modelFields, err := model_fields.SelectListAll(args)
- if err != nil {
- return
- }
- //获取可编辑字段
- fieldEdit := garray.NewStrArrayFrom(gstr.Split(modelInfo.ModelEdit, ","))
- insertData := g.Map{}
- for _, field := range modelFields {
- //主键
- if field.FieldName == modelInfo.ModelPk {
- insertData[field.FieldName] = masterId
- }
- //过滤不可编辑字段
- if !fieldEditAble(field.FieldName, fieldEdit) {
- continue
- }
- //字段规则
- fieldRules := garray.NewStrArrayFrom(gstr.Split(field.FieldRules, ","))
- switch field.FieldType {
- case "images":
- //图片上传
- picArr := gconv.SliceStr(data[field.FieldName])
- for k, a := range picArr {
- picArr[k], err = utils.GetFilesPath(a)
- g.Log().Error(picArr)
- if err != nil {
- return
- }
- }
- insertData[field.FieldName] = gstr.Join(picArr, ",")
- case "files", "file":
- //文件上传
- fileArr := gconv.SliceMap(data[field.FieldName])
- for k, fa := range fileArr {
- fileArr[k]["url"], err = utils.GetFilesPath(gconv.String(fa["url"]))
- if err != nil {
- return
- }
- }
- insertData[field.FieldName] = gconv.String(fileArr)
- case "imagefile":
- //单图上传
- if _, ok := data[field.FieldName].(string); !ok {
- err = gerror.New("单图片上传字段必须是一个字符串")
- return
- }
- imgStr := gconv.String(data[field.FieldName])
- if imgStr != "" {
- imgStr, err = utils.GetFilesPath(imgStr)
- if err != nil {
- return
- }
- }
- insertData[field.FieldName] = imgStr
- case "baidu_map", "text", "bigtext", "switch", "richtext":
- insertData[field.FieldName] = data[field.FieldName]
- case "number", "large_number":
- insertData[field.FieldName] = gconv.Int64(data[field.FieldName])
- case "currency":
- insertData[field.FieldName] = currencyLong(data[field.FieldName])
- case "datetime", "date":
- insertData[field.FieldName] = utils.StrToTimestamp(gconv.String(data[field.FieldName]))
- case "selectnumber":
- insertData[field.FieldName] = gconv.Int64(data[field.FieldName])
- var b bool
- //验证字段数据
- b, err = fieldOptionValid(field.FieldData, insertData[field.FieldName])
- if err != nil {
- return
- }
- if fieldRules.Contains("required") && !b {
- err = gerror.New(field.FieldTitle + "数据无效")
- return
- }
- case "selecttext":
- insertData[field.FieldName] = gstr.Trim(gconv.String(data[field.FieldName]))
- var b bool
- //验证字段数据
- b, err = fieldOptionValid(field.FieldData, insertData[field.FieldName])
- if err != nil {
- return
- }
- if fieldRules.Contains("required") && !b {
- err = gerror.New(field.FieldTitle + "数据无效")
- return
- }
- case "checkbox":
- checkboxData := data[field.FieldName]
- var b bool
- //验证字段数据
- b, err = fieldOptionValid(field.FieldData, checkboxData)
- if err != nil {
- return
- }
- if fieldRules.Contains("required") && !b {
- err = gerror.New(field.FieldTitle + "数据无效")
- return
- }
- sliceData := gconv.SliceAny(checkboxData)
- dataArr := garray.NewFrom(sliceData)
- insertData[field.FieldName] = dataArr.Join(",")
- case "DepartmentSelector":
- data := gconv.SliceStr(data[field.FieldName])
- insertData[field.FieldName] = gstr.Join(data, ",")
- default:
- err = gerror.New("未知字段:" + field.FieldTitle + field.FieldType)
- return
- }
- //处理特殊规则-必须
- if fieldRules.Contains("required") {
- if val, ok := insertData[field.FieldName].(string); ok && val == "" {
- err = gerror.New(field.FieldTitle + "不能为空")
- return
- }
- }
- //唯一验证
- if fieldRules.Contains("unique") {
- var one gdb.Record
- one, err = g.DB().Table(dbPrefix+modelInfo.ModelName).Where(field.FieldName, insertData[field.FieldName]).FindOne()
- if err != nil {
- g.Log().Error(one)
- err = gerror.New("判断字段" + field.FieldTitle + "唯一性失败")
- return
- }
- if one != nil {
- if !isUpdate || (isUpdate && gconv.Int64(one[modelInfo.ModelPk]) != gconv.Int64(insertData[modelInfo.ModelPk])) {
- err = gerror.New(field.FieldTitle + "已存在")
- return
- }
- }
- }
- }
- //保存模型字段数据
- _, err = tx.Table(dbPrefix + modelInfo.ModelName).Replace(insertData)
- if err != nil {
- g.Log().Error(err)
- err = gerror.New("报错模型数据失败")
- return
- }
- return nil
- }
- //删除模型字段数据
- func DeleteModelFieldData(modelId int64, masterId int64, tx *gdb.TX) (err error) {
- //表前缀
- dbPrefix := g.DB().GetPrefix()
- //1.获取模型信息
- modelInfo, err := model_info.GetByID(modelId)
- if err != nil {
- return
- }
- //删除操作
- _, err = g.DB().Table(dbPrefix+modelInfo.ModelName).TX(tx).Where(modelInfo.ModelPk, masterId).Delete()
- if err != nil {
- g.Log().Error(err)
- err = gerror.New("删除模型数据失败")
- return
- }
- return
- }
- //字段选项数据解析
- func fieldOptionConv(fieldData string) (data g.List, err error) {
- //直接查库操作
- if gstr.Pos(fieldData, "|") > -1 {
- dataInfo := garray.NewStrArrayFrom(gstr.Split(fieldData, "|"))
- var (
- table, fieldK, fieldV, sort, where string
- )
- var has bool = true
- if has {
- table, has = dataInfo.Get(0)
- }
- if has {
- fieldK, has = dataInfo.Get(1)
- }
- if has {
- fieldV, has = dataInfo.Get(2)
- }
- if !has {
- err = gerror.New("数据规则格式不正确,请检查模型字段设置")
- }
- model := g.DB().Table(table).Fields(fieldK + "," + fieldV)
- sort, has = dataInfo.Get(3)
- if has {
- model = model.Order(sort)
- }
- where, has = dataInfo.Get(4)
- if has {
- model = model.Where(where)
- }
- var res gdb.Result
- res, err = model.FindAll()
- if err != nil {
- g.Log().Error(err)
- err = gerror.New("获取模型数据选项失败")
- return
- }
- for _, r := range res {
- data = append(data, g.Map{
- "value": r[fieldK],
- "label": r[fieldV],
- "disable": false,
- })
- }
- } else if gstr.Pos(fieldData, ":") == 0 { //从字典库查询
- dictType := gstr.SubStr(fieldData, 1)
- var dict g.Map
- dict, err = sys_dict_type.GetDictWithDataByType(dictType, "", "")
- if err != nil {
- return
- }
- values := gconv.SliceMap(dict["values"])
- for _, val := range values {
- data = append(data, g.Map{
- "value": val["key"],
- "label": val["value"],
- "disable": false,
- })
- }
- } else { //硬编码
- dataSlice := gstr.Split(fieldData, ",")
- for _, val := range dataSlice {
- keyVal := gstr.Split(val, ":")
- if len(keyVal) != 2 {
- err = gerror.New("数据规则格式不正确,请检查模型字段设置")
- return
- }
- data = append(data, g.Map{
- "value": keyVal[0],
- "label": keyVal[1],
- "disable": false,
- })
- }
- }
- return
- }
- //判断字段是否可编辑
- func fieldEditAble(fieldName string, fieldEdits *garray.StrArray) bool {
- if fieldEdits.Len() == 0 {
- return false
- }
- return fieldEdits.ContainsI(fieldName)
- }
- //货币转化为分
- func currencyLong(currency interface{}) int64 {
- strArr := gstr.Split(gconv.String(currency), ".")
- switch len(strArr) {
- case 1:
- return gconv.Int64(strArr[0]) * 100
- case 2:
- if len(strArr[1]) == 1 {
- strArr[1] += "0"
- } else if len(strArr[1]) > 2 {
- strArr[1] = gstr.SubStr(strArr[1], 0, 2)
- }
- return gconv.Int64(strArr[0])*100 + gconv.Int64(strArr[1])
- }
- return 0
- }
- //检测字段选项是否有效
- func fieldOptionValid(fieldData string, value interface{}) (bool, error) {
- data, err := fieldOptionConv(fieldData)
- if err != nil {
- return false, err
- }
- valueArr := garray.New()
- switch value.(type) {
- case g.Slice:
- valueArr = garray.NewFrom(value.(g.Slice))
- default:
- valueArr.Append(value)
- }
- //去重
- valueArr = valueArr.Unique()
- if valueArr.Len() != 0 {
- r := false //检查提交数据是否在选项数据中
- valueArr.Iterator(func(k int, v interface{}) bool {
- r = false
- for _, d := range data {
- if gstr.Equal(gconv.String(v), gconv.String(d["value"])) {
- r = true
- continue
- }
- }
- return r
- })
- return r, nil
- }
- return true, nil
- }
|