index.vue 15.7 KB
Newer Older
1
<template>
2
  <div>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
3
    <!-- 从数据库直接获取字段 -->
Mr.奇淼('s avatar
Mr.奇淼( 已提交
4 5 6 7 8 9 10
    <div class="gva-search-box">
      <el-collapse v-model="activeNames" style="margin-bottom:12px">
        <el-collapse-item name="1">
          <template #title>
            <div :style="{fontSize:'16px',paddingLeft:'20px'}">
              点这里从现有数据库创建代码
              <i class="header-icon el-icon-thumb" />
11
            </div>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
          </template>
          <el-form ref="getTableForm" style="margin-top:24px" :inline="true" :model="dbform" label-width="120px">
            <el-form-item label="数据库名" prop="structName">
              <el-select v-model="dbform.dbName" filterable placeholder="请选择数据库" @change="getTable">
                <el-option
                  v-for="item in dbOptions"
                  :key="item.database"
                  :label="item.database"
                  :value="item.database"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="表名" prop="structName">
              <el-select
                v-model="dbform.tableName"
                :disabled="!dbform.dbName"
                filterable
                placeholder="请选择表"
              >
                <el-option
                  v-for="item in tableOptions"
                  :key="item.tableName"
                  :label="item.tableName"
                  :value="item.tableName"
                />
              </el-select>
            </el-form-item>
            <el-form-item>
              <el-button size="mini" type="primary" @click="getColumn">使用此表创建</el-button>
            </el-form-item>
          </el-form>
        </el-collapse-item>
      </el-collapse>
45 46
    </div>
    <div class="gva-search-box">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
47 48 49 50 51
      <!-- 初始版本自动化代码工具 -->
      <el-form ref="autoCodeForm" :rules="rules" :model="form" label-width="120px" :inline="true">
        <el-form-item label="Struct名称" prop="structName">
          <el-input v-model="form.structName" placeholder="首字母自动转换大写" />
        </el-form-item>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
52
        <el-form-item label="TableName" prop="tableName">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
          <el-input v-model="form.tableName" placeholder="指定表名(非必填)" />
        </el-form-item>
        <el-form-item label="Struct简称" prop="abbreviation">
          <el-input v-model="form.abbreviation" placeholder="简称会作为入参对象名和路由group" />
        </el-form-item>
        <el-form-item label="Struct中文名称" prop="description">
          <el-input v-model="form.description" placeholder="中文描述作为自动api描述" />
        </el-form-item>
        <el-form-item label="文件名称" prop="packageName">
          <el-input v-model="form.packageName" placeholder="生成文件的默认名称(建议为驼峰格式,首字母小写,如sysXxxXxxx)" />
        </el-form-item>
        <el-form-item>
          <template #label>
            <el-tooltip content="注:把自动生成的API注册进数据库" placement="bottom" effect="light">
              <div> 自动创建API </div>
            </el-tooltip>
          </template>
          <el-checkbox v-model="form.autoCreateApiToSql" />
        </el-form-item>
        <el-form-item>
          <template #label>
            <el-tooltip content="注:自动迁移生成的文件到ymal配置的对应位置" placement="bottom" effect="light">
              <div> 自动移动文件 </div>
            </el-tooltip>
          </template>
          <el-checkbox v-model="form.autoMoveFile" />
        </el-form-item>
      </el-form>
    </div>
82
    <!-- 组件列表 -->
Mr.奇淼('s avatar
Mr.奇淼( 已提交
83 84 85 86 87
    <div class="gva-table-box">
      <div class="gva-btn-list">
        <el-button size="mini" type="primary" @click="editAndAddField()">新增Field</el-button>
      </div>
      <el-table :data="form.fields">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
88 89 90 91 92 93 94 95 96 97 98 99
        <el-table-column align="left" type="index" label="序列" width="100" />
        <el-table-column align="left" prop="fieldName" label="Field名" />
        <el-table-column align="left" prop="fieldDesc" label="中文名" />
        <el-table-column align="left" prop="fieldJson" label="FieldJson" />
        <el-table-column align="left" prop="fieldType" label="Field数据类型" width="130" />
        <el-table-column align="left" prop="dataType" label="数据库字段类型" width="130" />
        <el-table-column align="left" prop="dataTypeLong" label="数据库字段长度" width="130" />
        <el-table-column align="left" prop="columnName" label="数据库字段" width="130" />
        <el-table-column align="left" prop="comment" label="数据库字段描述" width="130" />
        <el-table-column align="left" prop="fieldSearchType" label="搜索条件" width="130" />
        <el-table-column align="left" prop="dictType" label="字典" width="130" />
        <el-table-column align="left" label="操作" width="300">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
          <template #default="scope">
            <el-button
              size="mini"
              type="text"
              icon="el-icon-edit"
              @click="editAndAddField(scope.row)"
            >编辑</el-button>
            <el-button
              size="mini"
              type="text"
              :disabled="scope.$index === 0"
              @click="moveUpField(scope.$index)"
            >上移</el-button>
            <el-button
              size="mini"
              type="text"
              :disabled="(scope.$index + 1) === form.fields.length"
              @click="moveDownField(scope.$index)"
            >下移</el-button>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
119
            <el-popover :visible="scope.row.visible" placement="top">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
120
              <p>确定删除吗?</p>
121
              <div style="text-align: right; margin-top: 8px;">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
                <el-button size="mini" type="text" @click="scope.row.visible = false">取消</el-button>
                <el-button type="primary" size="mini" @click="deleteField(scope.$index)">确定</el-button>
              </div>
              <template #reference>
                <el-button size="mini" type="text" icon="el-icon-delete">删除</el-button>
              </template>
            </el-popover>
          </template>
        </el-table-column>
      </el-table>
      <el-tag type="danger" style="margin:12px 0;">id , created_at , updated_at , deleted_at 会自动生成请勿重复创建</el-tag>
      <!-- 组件列表 -->
      <div class="gva-btn-list justify-content-flex-end">
        <el-button size="mini" type="primary" @click="enterForm(true)">预览代码</el-button>
        <el-button size="mini" type="primary" @click="enterForm(false)">生成代码</el-button>
      </div>
138
    </div>
139
    <!-- 组件弹窗 -->
140
    <el-dialog v-model="dialogFlag" title="组件内容">
何秀钢 已提交
141
      <FieldDialog v-if="dialogFlag" ref="fieldDialog" :dialog-middle="dialogMiddle" />
142 143 144 145 146 147
      <template #footer>
        <div class="dialog-footer">
          <el-button size="mini" @click="closeDialog">取 消</el-button>
          <el-button size="mini" type="primary" @click="enterDialog">确 定</el-button>
        </div>
      </template>
148
    </el-dialog>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
149

150
    <el-dialog v-model="previewFlag">
151 152 153 154 155 156 157
      <template #title>
        <div class="previewCodeTool">
          <p>操作栏:</p>
          <el-button size="mini" type="primary" @click="selectText">全选</el-button>
          <el-button size="mini" type="primary" @click="copy">复制</el-button>
        </div>
      </template>
-芈Autumn-'s avatar
-芈Autumn- 已提交
158
      <PreviewCodeDialog v-if="previewFlag" :preview-code="preViewCode" />
159
      <template #footer>
160
        <div class="dialog-footer" style="padding-top:14px;padding-right:14px">
P
piexlmax 已提交
161
          <el-button size="small" type="primary" @click="previewFlag = false">确 定</el-button>
162 163
        </div>
      </template>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
164
    </el-dialog>
165
  </div>
166
</template>
何秀钢 已提交
167

168
<script>
169
const fieldTemplate = {
何秀钢 已提交
170 171 172 173 174 175 176 177 178 179 180
  fieldName: '',
  fieldDesc: '',
  fieldType: '',
  dataType: '',
  fieldJson: '',
  columnName: '',
  dataTypeLong: '',
  comment: '',
  fieldSearchType: '',
  dictType: ''
}
Mr.奇淼('s avatar
Mr.奇淼( 已提交
181

何秀钢 已提交
182
import FieldDialog from '@/view/systemTools/autoCode/component/fieldDialog.vue'
-芈Autumn-'s avatar
-芈Autumn- 已提交
183
import PreviewCodeDialog from '@/view/systemTools/autoCode/component/previewCodeDialg.vue'
184
import { toUpperCase, toHump, toSQLLine } from '@/utils/stringFun'
Mr.奇淼('s avatar
Mr.奇淼( 已提交
185
import { createTemp, getDB, getTable, getColumn, preview, getMeta } from '@/api/autoCode'
何秀钢 已提交
186
import { getDict } from '@/utils/dictionary'
187 188

export default {
何秀钢 已提交
189 190 191
  name: 'AutoCode',
  components: {
    FieldDialog,
-芈Autumn-'s avatar
-芈Autumn- 已提交
192
    PreviewCodeDialog
何秀钢 已提交
193
  },
194 195
  data() {
    return {
何秀钢 已提交
196 197
      activeNames: [''],
      preViewCode: {},
Mr.奇淼('s avatar
Mr.奇淼( 已提交
198
      dbform: {
何秀钢 已提交
199 200
        dbName: '',
        tableName: ''
Mr.奇淼('s avatar
Mr.奇淼( 已提交
201 202 203
      },
      dbOptions: [],
      tableOptions: [],
何秀钢 已提交
204
      addFlag: '',
Mr.奇淼('s avatar
Mr.奇淼( 已提交
205
      fdMap: {},
206
      form: {
何秀钢 已提交
207 208 209 210 211
        structName: '',
        tableName: '',
        packageName: '',
        abbreviation: '',
        description: '',
212
        autoCreateApiToSql: false,
m0_50812349's avatar
m0_50812349 已提交
213
        autoMoveFile: false,
Mr.奇淼('s avatar
Mr.奇淼( 已提交
214
        fields: []
215 216
      },
      rules: {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
217
        structName: [
何秀钢 已提交
218
          { required: true, message: '请输入结构体名称', trigger: 'blur' }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
219 220
        ],
        abbreviation: [
何秀钢 已提交
221
          { required: true, message: '请输入结构体简称', trigger: 'blur' }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
222 223
        ],
        description: [
何秀钢 已提交
224
          { required: true, message: '请输入结构体描述', trigger: 'blur' }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
225 226 227 228
        ],
        packageName: [
          {
            required: true,
229
            message: '文件名称:sysXxxxXxxx',
何秀钢 已提交
230
            trigger: 'blur'
Mr.奇淼('s avatar
Mr.奇淼( 已提交
231 232
          }
        ]
233 234 235
      },
      dialogMiddle: {},
      bk: {},
Mr.奇淼('s avatar
Mr.奇淼( 已提交
236
      dialogFlag: false,
何秀钢 已提交
237 238
      previewFlag: false
    }
239
  },
何秀钢 已提交
240 241 242
  created() {
    this.getDb()
    this.setFdMap()
Mr.奇淼('s avatar
Mr.奇淼( 已提交
243 244 245 246
    const id = this.$route.params.id
    if (id) {
      this.getAutoCodeJson(id)
    }
247 248 249
  },
  methods: {
    editAndAddField(item) {
何秀钢 已提交
250
      this.dialogFlag = true
251
      if (item) {
何秀钢 已提交
252 253 254
        this.addFlag = 'edit'
        this.bk = JSON.parse(JSON.stringify(item))
        this.dialogMiddle = item
255
      } else {
何秀钢 已提交
256 257
        this.addFlag = 'add'
        this.dialogMiddle = JSON.parse(JSON.stringify(fieldTemplate))
258 259 260
      }
    },
    moveUpField(index) {
何秀钢 已提交
261 262
      if (index === 0) {
        return
263
      }
何秀钢 已提交
264 265 266
      const oldUpField = this.form.fields[index - 1]
      this.form.fields.splice(index - 1, 1)
      this.form.fields.splice(index, 0, oldUpField)
267 268
    },
    moveDownField(index) {
何秀钢 已提交
269 270 271
      const fCount = this.form.fields.length
      if (index === fCount - 1) {
        return
272
      }
何秀钢 已提交
273 274 275
      const oldDownField = this.form.fields[index + 1]
      this.form.fields.splice(index + 1, 1)
      this.form.fields.splice(index, 0, oldDownField)
276 277
    },
    enterDialog() {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
278
      this.$refs.fieldDialog.$refs.fieldDialogFrom.validate(valid => {
279
        if (valid) {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
280 281
          this.dialogMiddle.fieldName = toUpperCase(
            this.dialogMiddle.fieldName
何秀钢 已提交
282 283 284
          )
          if (this.addFlag === 'add') {
            this.form.fields.push(this.dialogMiddle)
285
          }
何秀钢 已提交
286
          this.dialogFlag = false
287
        } else {
何秀钢 已提交
288
          return false
289
        }
何秀钢 已提交
290
      })
291
    },
292
    closeDialog() {
何秀钢 已提交
293 294
      if (this.addFlag === 'edit') {
        this.dialogMiddle = this.bk
295
      }
何秀钢 已提交
296
      this.dialogFlag = false
297
    },
298
    deleteField(index) {
何秀钢 已提交
299
      this.form.fields.splice(index, 1)
300
    },
Mr.奇淼('s avatar
Mr.奇淼( 已提交
301
    async enterForm(isPreview) {
302 303
      if (this.form.fields.length <= 0) {
        this.$message({
何秀钢 已提交
304 305 306 307
          type: 'error',
          message: '请填写至少一个field'
        })
        return false
308
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
309
      if (
何秀钢 已提交
310
        this.form.fields.some(item => item.fieldName === this.form.structName)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
311
      ) {
312
        this.$message({
何秀钢 已提交
313 314 315 316
          type: 'error',
          message: '存在与结构体同名的字段'
        })
        return false
317
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
318
      this.$refs.autoCodeForm.validate(async valid => {
319
        if (valid) {
何秀钢 已提交
320
          this.form.structName = toUpperCase(this.form.structName)
-芈Autumn-'s avatar
-芈Autumn- 已提交
321
          if (this.form.tableName) { this.form.tableName = this.form.tableName.replace(' ', '') }
何秀钢 已提交
322
          if (this.form.structName === this.form.abbreviation) {
323
            this.$message({
何秀钢 已提交
324 325 326 327
              type: 'error',
              message: 'structName和struct简称不能相同'
            })
            return false
328
          }
329
          this.form.humpPackageName = toSQLLine(this.form.packageName)
何秀钢 已提交
330 331
          if (isPreview) {
            const data = await preview(this.form)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
332 333
            this.preViewCode = data.data.autoCode
            this.previewFlag = true
何秀钢 已提交
334 335 336 337
          } else {
            const data = await createTemp(this.form)
            if (data.headers?.success === 'false') {
              return
Mr.奇淼('s avatar
Mr.奇淼( 已提交
338
            } else {
339 340 341 342 343 344 345
              if (this.form.autoMoveFile) {
                this.$message({
                  type: 'success',
                  message: '自动化代码创建成功,自动移动成功'
                })
                return
              }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
346
              this.$message({
何秀钢 已提交
347 348 349
                type: 'success',
                message: '自动化代码创建成功,正在下载'
              })
Mr.奇淼('s avatar
Mr.奇淼( 已提交
350
            }
何秀钢 已提交
351 352 353
            const blob = new Blob([data])
            const fileName = 'ginvueadmin.zip'
            if ('download' in document.createElement('a')) {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
354
              // 不是IE浏览器
何秀钢 已提交
355 356 357 358 359 360 361 362 363
              const url = window.URL.createObjectURL(blob)
              const link = document.createElement('a')
              link.style.display = 'none'
              link.href = url
              link.setAttribute('download', fileName)
              document.body.appendChild(link)
              link.click()
              document.body.removeChild(link) // 下载完成移除元素
              window.URL.revokeObjectURL(url) // 释放掉blob对象
Mr.奇淼('s avatar
Mr.奇淼( 已提交
364 365
            } else {
              // IE 10+
何秀钢 已提交
366
              window.navigator.msSaveBlob(blob, fileName)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
367
            }
368
          }
369
        } else {
何秀钢 已提交
370
          return false
371
        }
何秀钢 已提交
372
      })
Mr.奇淼('s avatar
Mr.奇淼( 已提交
373 374
    },
    async getDb() {
何秀钢 已提交
375 376 377
      const res = await getDB()
      if (res.code === 0) {
        this.dbOptions = res.data.dbs
Mr.奇淼('s avatar
Mr.奇淼( 已提交
378
      }
379
    },
Mr.奇淼('s avatar
Mr.奇淼( 已提交
380
    async getTable() {
何秀钢 已提交
381 382 383
      const res = await getTable({ dbName: this.dbform.dbName })
      if (res.code === 0) {
        this.tableOptions = res.data.tables
Mr.奇淼('s avatar
Mr.奇淼( 已提交
384
      }
何秀钢 已提交
385
      this.dbform.tableName = ''
Mr.奇淼('s avatar
Mr.奇淼( 已提交
386
    },
387
    async getColumn() {
何秀钢 已提交
388 389 390 391 392 393 394 395 396 397 398
      const gormModelList = ['id', 'created_at', 'updated_at', 'deleted_at']
      const res = await getColumn(this.dbform)
      if (res.code === 0) {
        const tbHump = toHump(this.dbform.tableName)
        this.form.structName = toUpperCase(tbHump)
        this.form.tableName = this.dbform.tableName
        this.form.packageName = tbHump
        this.form.abbreviation = tbHump
        this.form.description = tbHump + ''
        this.form.autoCreateApiToSql = true
        this.form.fields = []
399
        res.data.columns &&
Mr.奇淼('s avatar
Mr.奇淼( 已提交
400
          res.data.columns.forEach(item => {
何秀钢 已提交
401 402
            if (!gormModelList.some(gormfd => gormfd === item.columnName)) {
              const fbHump = toHump(item.columnName)
403 404
              this.form.fields.push({
                fieldName: toUpperCase(fbHump),
何秀钢 已提交
405
                fieldDesc: item.columnComment || fbHump + '字段',
406 407 408 409
                fieldType: this.fdMap[item.dataType],
                dataType: item.dataType,
                fieldJson: fbHump,
                dataTypeLong: item.dataTypeLong,
410 411
                columnName: item.columnName,
                comment: item.columnComment,
何秀钢 已提交
412 413 414
                fieldSearchType: '',
                dictType: ''
              })
415
            }
何秀钢 已提交
416
          })
417
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
418 419
    },
    async setFdMap() {
何秀钢 已提交
420
      const fdTypes = ['string', 'int', 'bool', 'float64', 'time.Time']
Mr.奇淼('s avatar
Mr.奇淼( 已提交
421
      fdTypes.forEach(async fdtype => {
何秀钢 已提交
422
        const res = await getDict(fdtype)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
423
        res && res.forEach(item => {
何秀钢 已提交
424 425 426
          this.fdMap[item.label] = fdtype
        })
      })
Mr.奇淼('s avatar
Mr.奇淼( 已提交
427 428 429 430 431 432
    },
    async getAutoCodeJson(id) {
      const res = await getMeta({ id: Number(id) })
      if (res.code === 0) {
        this.form = JSON.parse(res.data.meta)
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
433 434
    }
  }
何秀钢 已提交
435
}
436
</script>
何秀钢 已提交
437 438

<style scoped lang="scss">
439 440 441 442 443
  .previewCodeTool {
    display: flex;
    align-items: center;
    padding: 5px 0;
  }
444 445 446
.button-box {
  padding: 10px 20px;
  .el-button {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
447
    margin-right: 20px;
448 449 450
    float: right;
  }
}
451
</style>