index.vue 15.8 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 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
          <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>
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 101
        <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.奇淼( 已提交
102 103 104 105
          <template #default="scope">
            <el-button
              size="mini"
              type="text"
P
piexlmax 已提交
106
              icon="edit"
Mr.奇淼('s avatar
Mr.奇淼( 已提交
107 108 109 110 111 112 113 114 115 116 117 118 119 120
              @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.奇淼( 已提交
121
            <el-popover :visible="scope.row.visible" placement="top">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
122
              <p>确定删除吗?</p>
123
              <div style="text-align: right; margin-top: 8px;">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
124 125 126 127
                <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 已提交
128
                <el-button size="mini" type="text" icon="delete">删除</el-button>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
129 130 131 132 133 134
              </template>
            </el-popover>
          </template>
        </el-table-column>
      </el-table>
      <!-- 组件列表 -->
Mr.奇淼('s avatar
Mr.奇淼( 已提交
135
      <div class="gva-btn-list justify-content-flex-end auto-btn-list">
Mr.奇淼('s avatar
Mr.奇淼( 已提交
136 137 138
        <el-button size="mini" type="primary" @click="enterForm(true)">预览代码</el-button>
        <el-button size="mini" type="primary" @click="enterForm(false)">生成代码</el-button>
      </div>
139
    </div>
140
    <!-- 组件弹窗 -->
141
    <el-dialog v-model="dialogFlag" title="组件内容">
何秀钢 已提交
142
      <FieldDialog v-if="dialogFlag" ref="fieldDialog" :dialog-middle="dialogMiddle" />
143 144 145 146 147 148
      <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>
149
    </el-dialog>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
150

151
    <el-dialog v-model="previewFlag">
152 153 154 155 156 157 158
      <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>
159
      <PreviewCodeDialog v-if="previewFlag" ref="preview" :preview-code="preViewCode" />
160
      <template #footer>
161
        <div class="dialog-footer" style="padding-top:14px;padding-right:14px">
P
piexlmax 已提交
162
          <el-button size="small" type="primary" @click="previewFlag = false">确 定</el-button>
163 164
        </div>
      </template>
Mr.奇淼('s avatar
Mr.奇淼( 已提交
165
    </el-dialog>
166
  </div>
167
</template>
何秀钢 已提交
168

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

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

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

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