index.vue 16.0 KB
Newer Older
1
<template>
2
  <div>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
3
    <!-- 从数据库直接获取字段 -->
Mr.奇淼('s avatar
Mr.奇淼( 已提交
4 5 6 7 8 9
    <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'}">
              点这里从现有数据库创建代码
P
piexlmax 已提交
10 11 12
              <el-icon class="header-icon ">
                <pointer />
              </el-icon>
13
            </div>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
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 45 46
          </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>
47 48
    </div>
    <div class="gva-search-box">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
49 50 51 52 53
      <!-- 初始版本自动化代码工具 -->
      <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.奇淼( 已提交
54
        <el-form-item label="TableName" prop="tableName">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
55 56 57 58 59 60 61 62 63
          <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">
64
          <el-input v-model="form.packageName" placeholder="生成文件的默认名称(建议为驼峰格式,首字母小写,如sysXxxXxxx)" @blur="toLowerCase(form,'packageName')" />
Mr.奇淼('s avatar
Mr.奇淼( 已提交
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
        </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>
84
    <!-- 组件列表 -->
Mr.奇淼('s avatar
Mr.奇淼( 已提交
85 86 87 88 89
    <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.奇淼( 已提交
90 91 92 93 94 95 96 97 98 99 100
        <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="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.奇淼( 已提交
101 102 103 104
          <template #default="scope">
            <el-button
              size="mini"
              type="text"
P
piexlmax 已提交
105
              icon="edit"
Mr.奇淼('s avatar
Mr.奇淼( 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119
              @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.奇淼( 已提交
120
            <el-popover :visible="scope.row.visible" placement="top">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
121
              <p>确定删除吗?</p>
122
              <div style="text-align: right; margin-top: 8px;">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
123 124 125 126
                <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>
P
piexlmax 已提交
127
                <el-button size="mini" type="text" icon="delete">删除</el-button>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
128 129 130 131 132 133
              </template>
            </el-popover>
          </template>
        </el-table-column>
      </el-table>
      <!-- 组件列表 -->
Mr.奇淼('s avatar
Mr.奇淼( 已提交
134
      <div class="gva-btn-list justify-content-flex-end auto-btn-list">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
135 136 137
        <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>
158
      <PreviewCodeDialog v-if="previewFlag" ref="preview" :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, toLowerCase } 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
  },
  methods: {
249 250 251
    toLowerCase(form, key) {
      form[key] = toLowerCase(form[key])
    },
252 253 254 255 256 257
    selectText() {
      this.$refs.preview.selectText()
    },
    copy() {
      this.$refs.preview.copy()
    },
258
    editAndAddField(item) {
何秀钢 已提交
259
      this.dialogFlag = true
260
      if (item) {
何秀钢 已提交
261 262 263
        this.addFlag = 'edit'
        this.bk = JSON.parse(JSON.stringify(item))
        this.dialogMiddle = item
264
      } else {
何秀钢 已提交
265 266
        this.addFlag = 'add'
        this.dialogMiddle = JSON.parse(JSON.stringify(fieldTemplate))
267 268 269
      }
    },
    moveUpField(index) {
何秀钢 已提交
270 271
      if (index === 0) {
        return
272
      }
何秀钢 已提交
273 274 275
      const oldUpField = this.form.fields[index - 1]
      this.form.fields.splice(index - 1, 1)
      this.form.fields.splice(index, 0, oldUpField)
276 277
    },
    moveDownField(index) {
何秀钢 已提交
278 279 280
      const fCount = this.form.fields.length
      if (index === fCount - 1) {
        return
281
      }
何秀钢 已提交
282 283 284
      const oldDownField = this.form.fields[index + 1]
      this.form.fields.splice(index + 1, 1)
      this.form.fields.splice(index, 0, oldDownField)
285 286
    },
    enterDialog() {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
287
      this.$refs.fieldDialog.$refs.fieldDialogFrom.validate(valid => {
288
        if (valid) {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
289 290
          this.dialogMiddle.fieldName = toUpperCase(
            this.dialogMiddle.fieldName
何秀钢 已提交
291 292 293
          )
          if (this.addFlag === 'add') {
            this.form.fields.push(this.dialogMiddle)
294
          }
何秀钢 已提交
295
          this.dialogFlag = false
296
        } else {
何秀钢 已提交
297
          return false
298
        }
何秀钢 已提交
299
      })
300
    },
301
    closeDialog() {
何秀钢 已提交
302 303
      if (this.addFlag === 'edit') {
        this.dialogMiddle = this.bk
304
      }
何秀钢 已提交
305
      this.dialogFlag = false
306
    },
307
    deleteField(index) {
何秀钢 已提交
308
      this.form.fields.splice(index, 1)
309
    },
Mr.奇淼('s avatar
Mr.奇淼( 已提交
310
    async enterForm(isPreview) {
311 312
      if (this.form.fields.length <= 0) {
        this.$message({
何秀钢 已提交
313 314 315 316
          type: 'error',
          message: '请填写至少一个field'
        })
        return false
317
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
318
      if (
何秀钢 已提交
319
        this.form.fields.some(item => item.fieldName === this.form.structName)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
320
      ) {
321
        this.$message({
何秀钢 已提交
322 323 324 325
          type: 'error',
          message: '存在与结构体同名的字段'
        })
        return false
326
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
327
      this.$refs.autoCodeForm.validate(async valid => {
328
        if (valid) {
329 330 331 332 333
          for (const key in this.form) {
            if (typeof this.form[key] === 'string') {
              this.form[key] = this.form[key].trim()
            }
          }
何秀钢 已提交
334
          this.form.structName = toUpperCase(this.form.structName)
-芈Autumn-'s avatar
-芈Autumn- 已提交
335
          if (this.form.tableName) { this.form.tableName = this.form.tableName.replace(' ', '') }
何秀钢 已提交
336
          if (this.form.structName === this.form.abbreviation) {
337
            this.$message({
何秀钢 已提交
338 339 340 341
              type: 'error',
              message: 'structName和struct简称不能相同'
            })
            return false
342
          }
343
          this.form.humpPackageName = toSQLLine(this.form.packageName)
何秀钢 已提交
344 345
          if (isPreview) {
            const data = await preview(this.form)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
346 347
            this.preViewCode = data.data.autoCode
            this.previewFlag = true
何秀钢 已提交
348 349 350 351
          } else {
            const data = await createTemp(this.form)
            if (data.headers?.success === 'false') {
              return
Mr.奇淼('s avatar
Mr.奇淼( 已提交
352
            } else {
353 354 355 356 357 358 359
              if (this.form.autoMoveFile) {
                this.$message({
                  type: 'success',
                  message: '自动化代码创建成功,自动移动成功'
                })
                return
              }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
360
              this.$message({
何秀钢 已提交
361 362 363
                type: 'success',
                message: '自动化代码创建成功,正在下载'
              })
Mr.奇淼('s avatar
Mr.奇淼( 已提交
364
            }
何秀钢 已提交
365 366 367
            const blob = new Blob([data])
            const fileName = 'ginvueadmin.zip'
            if ('download' in document.createElement('a')) {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
368
              // 不是IE浏览器
何秀钢 已提交
369 370 371 372 373 374 375 376 377
              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.奇淼( 已提交
378 379
            } else {
              // IE 10+
何秀钢 已提交
380
              window.navigator.msSaveBlob(blob, fileName)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
381
            }
382
          }
383
        } else {
何秀钢 已提交
384
          return false
385
        }
何秀钢 已提交
386
      })
Mr.奇淼('s avatar
Mr.奇淼( 已提交
387 388
    },
    async getDb() {
何秀钢 已提交
389 390 391
      const res = await getDB()
      if (res.code === 0) {
        this.dbOptions = res.data.dbs
Mr.奇淼('s avatar
Mr.奇淼( 已提交
392
      }
393
    },
Mr.奇淼('s avatar
Mr.奇淼( 已提交
394
    async getTable() {
何秀钢 已提交
395 396 397
      const res = await getTable({ dbName: this.dbform.dbName })
      if (res.code === 0) {
        this.tableOptions = res.data.tables
Mr.奇淼('s avatar
Mr.奇淼( 已提交
398
      }
何秀钢 已提交
399
      this.dbform.tableName = ''
Mr.奇淼('s avatar
Mr.奇淼( 已提交
400
    },
401
    async getColumn() {
何秀钢 已提交
402 403 404 405 406 407 408 409 410 411 412
      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 = []
413
        res.data.columns &&
Mr.奇淼('s avatar
Mr.奇淼( 已提交
414
          res.data.columns.forEach(item => {
何秀钢 已提交
415 416
            if (!gormModelList.some(gormfd => gormfd === item.columnName)) {
              const fbHump = toHump(item.columnName)
417 418
              this.form.fields.push({
                fieldName: toUpperCase(fbHump),
何秀钢 已提交
419
                fieldDesc: item.columnComment || fbHump + '字段',
420 421 422
                fieldType: this.fdMap[item.dataType],
                dataType: item.dataType,
                fieldJson: fbHump,
423
                dataTypeLong: item.dataTypeLong && item.dataTypeLong.split(',')[0],
424 425
                columnName: item.columnName,
                comment: item.columnComment,
何秀钢 已提交
426 427 428
                fieldSearchType: '',
                dictType: ''
              })
429
            }
何秀钢 已提交
430
          })
431
      }
Mr.奇淼('s avatar
Mr.奇淼( 已提交
432 433
    },
    async setFdMap() {
何秀钢 已提交
434
      const fdTypes = ['string', 'int', 'bool', 'float64', 'time.Time']
Mr.奇淼('s avatar
Mr.奇淼( 已提交
435
      fdTypes.forEach(async fdtype => {
何秀钢 已提交
436
        const res = await getDict(fdtype)
Mr.奇淼('s avatar
Mr.奇淼( 已提交
437
        res && res.forEach(item => {
何秀钢 已提交
438 439 440
          this.fdMap[item.label] = fdtype
        })
      })
Mr.奇淼('s avatar
Mr.奇淼( 已提交
441 442 443 444 445 446
    },
    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.奇淼( 已提交
447 448
    }
  }
何秀钢 已提交
449
}
450
</script>
何秀钢 已提交
451 452

<style scoped lang="scss">
453 454 455 456 457
  .previewCodeTool {
    display: flex;
    align-items: center;
    padding: 5px 0;
  }
458 459 460
.button-box {
  padding: 10px 20px;
  .el-button {
Mr.奇淼('s avatar
Mr.奇淼( 已提交
461
    margin-right: 20px;
462 463 464
    float: right;
  }
}
Mr.奇淼('s avatar
Mr.奇淼( 已提交
465 466 467
.auto-btn-list{
  margin-top: 16px;
}
468
</style>