index.vue 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951
  1. <template>
  2. <div class="app-container">
  3. <el-card style="margin-bottom: 15px">
  4. <el-form ref="form" :model="form" label-width="100px" :rules="rules">
  5. <!-- <el-form-item label="数据库名称" prop="dataBaseName">
  6. <el-input v-model="form.dataBaseName" style="width: 600px;"></el-input>
  7. </el-form-item> -->
  8. <el-form-item label="数据表名称" prop="tableName">
  9. <el-input
  10. v-model="form.tableName"
  11. :disabled="isEdited"
  12. style="width: 600px"
  13. ></el-input>
  14. </el-form-item>
  15. <el-form-item label="表描述">
  16. <el-input v-model="form.tableComment" style="width: 600px"></el-input>
  17. </el-form-item>
  18. </el-form>
  19. </el-card>
  20. <el-card>
  21. <div class="titleitem">
  22. <span>数据表字段</span>
  23. </div>
  24. <el-form ref="tableform" :rules="tableform" :model="experienceDataForm">
  25. <el-table
  26. ref="dragTable"
  27. :data="experienceData"
  28. stripe
  29. row-key="tag"
  30. style="width: 100%"
  31. >
  32. <el-table-column
  33. type="index"
  34. label="序号"
  35. width="50"
  36. class-name="allowDrag"
  37. />
  38. <el-table-column prop="fieldName" label="字段名称" width="200">
  39. <template slot-scope="scope">
  40. <el-form-item
  41. :prop="'fieldName' + scope.$index"
  42. :name="'fieldName' + scope.$index"
  43. style="margin: 0px; padding: 0px"
  44. >
  45. <el-input
  46. v-model="scope.row.fieldName"
  47. :disabled="scope.$index == 0"
  48. @blur="fieldNameChange(scope.row)"
  49. ></el-input>
  50. </el-form-item>
  51. </template>
  52. </el-table-column>
  53. <el-table-column prop="fieldType" label="字段类型" width="200">
  54. <template slot-scope="scope">
  55. <el-form-item
  56. :prop="'fieldType' + scope.$index"
  57. :name="'fieldType' + scope.$index"
  58. style="margin: 0px; padding: 0px"
  59. >
  60. <el-select
  61. :disabled="scope.$index == 0"
  62. v-model="scope.row.fieldType"
  63. filterable
  64. @blur="selectBlur(scope)"
  65. @change="
  66. handleSelected(
  67. dataType.find(
  68. (item) => item.label === scope.row.fieldType
  69. ),
  70. scope,
  71. scope.$index,
  72. scope.row
  73. )
  74. "
  75. >
  76. <!-- <el-option v-for="item in list" :key="item" :label="item" :value="item">
  77. </el-option> -->
  78. <!--
  79. <el-option v-for="item in dict.type.mysql_data_type" :label="item.dictLabel" :value="item.dictValue">
  80. </el-option> -->
  81. <el-option
  82. v-for="item in dataType"
  83. :key="item.value"
  84. :label="item.label"
  85. :value="item.value"
  86. />
  87. </el-select>
  88. </el-form-item>
  89. </template>
  90. </el-table-column>
  91. <el-table-column prop="fieldLength" label="长度" width="200">
  92. <template slot-scope="scope">
  93. <el-form-item
  94. :prop="'fieldLength' + scope.$index"
  95. :name="'fieldLength' + scope.$index"
  96. style="margin: 0px; padding: 0px"
  97. >
  98. <!-- <el-input v-model="scope.row.fieldLength"-->
  99. <!-- :disabled="handleSelected(dict.type.mysql_data_type.find(item => item.label === scope.row.fieldType), scope)"></el-input>-->
  100. <el-input
  101. v-model="scope.row.fieldLength"
  102. @blur="fieldLengthChange(scope.$index, scope.row)"
  103. :disabled="changduclick(scope.$index) || scope.$index == 0"
  104. @input="
  105. scope.row.fieldLength = scope.row.fieldLength.replace(
  106. /^(0+)|[^\d]+/g,
  107. ''
  108. )
  109. "
  110. ></el-input>
  111. </el-form-item>
  112. </template>
  113. </el-table-column>
  114. <el-table-column prop="isNull" label="不是null" width="100">
  115. <template slot-scope="scope">
  116. <el-checkbox
  117. :disabled="scope.$index == 0"
  118. @change="isNullChange(scope.row)"
  119. v-model="scope.row.isNull"
  120. ></el-checkbox>
  121. </template>
  122. </el-table-column>
  123. <el-table-column prop="isPrimary" label="主键" width="100">
  124. <template slot-scope="scope">
  125. <el-checkbox
  126. :disabled="scope.$index == 0"
  127. v-model="scope.row.isPrimary"
  128. @change="hanleCheckbox(scope.$index, scope.row)"
  129. ></el-checkbox>
  130. </template>
  131. </el-table-column>
  132. <el-table-column prop="isAuto" label="自增" width="100">
  133. <template slot-scope="scope">
  134. <el-checkbox
  135. :disabled="scope.$index == 0"
  136. @change="isAutoChange(scope.row)"
  137. v-model="scope.row.isAuto"
  138. ></el-checkbox>
  139. </template>
  140. </el-table-column>
  141. <el-table-column prop="fieldDescription" label="字段描述" width="200">
  142. <template slot-scope="scope">
  143. <el-input
  144. :disabled="scope.$index == 0"
  145. @change="fieldDescriptionChange(scope.row)"
  146. v-model="scope.row.fieldDescription"
  147. ></el-input>
  148. </template>
  149. </el-table-column>
  150. <el-table-column prop="operate" label="操作">
  151. <template slot-scope="scope">
  152. <!-- <el-button size="mini" type="success" icon="el-icon-save"
  153. @click="handlesaveExperience(scope.$index, scope.row)">保存
  154. </el-button> -->
  155. <el-button
  156. size="mini"
  157. type="danger"
  158. icon="el-icon-delete"
  159. :disabled="scope.$index == 0"
  160. @click="handleDeleteExperience(scope.$index, scope.row)"
  161. >删除
  162. </el-button>
  163. </template>
  164. </el-table-column>
  165. </el-table>
  166. </el-form>
  167. <div>
  168. <el-button
  169. type="primary"
  170. icon="el-icon-plus"
  171. size="mini"
  172. @click="handleAddExperienceline"
  173. >新增字段
  174. </el-button>
  175. </div>
  176. </el-card>
  177. <div style="margin-top: 15px">
  178. <el-button v-if="!isEdited" @click="add" type="primary">添加</el-button>
  179. <el-button v-else @click="edit" type="primary">修改</el-button>
  180. </div>
  181. </div>
  182. </template>
  183. <script>
  184. import { createDatabase } from "@/api/datasheet/index";
  185. import { tableInfo, editTable } from "@/api/dataEngine/index";
  186. import { mapState } from "vuex";
  187. import { getDicts } from "@/api/system/dict/data";
  188. import Sortable from "sortablejs";
  189. import { v4 as uuidv4 } from "uuid";
  190. export default {
  191. name: "Datasheet",
  192. // dicts: [
  193. // "dm_data_type",
  194. // "mysql_data_type",
  195. // "sqlserver_data_type",
  196. // "oracle_data_type",
  197. // ],
  198. data() {
  199. return {
  200. sqlStringList: [],
  201. isEdited: false,
  202. testzidian: null,
  203. form: {
  204. dataBaseName: "",
  205. tableName: "",
  206. tableComment: "",
  207. },
  208. experienceDataForm: {},
  209. experienceData: [
  210. {
  211. fieldName: "id",
  212. fieldType: "bigint",
  213. fieldLength: undefined,
  214. isNull: true,
  215. isPrimary: true,
  216. fieldDescription: "主键",
  217. isAuto: true,
  218. },
  219. ],
  220. rules: {
  221. dataBaseName: {
  222. validator: this.checkDataBaseName,
  223. trigger: "blur",
  224. },
  225. tableName: {
  226. validator: this.checkTableName,
  227. trigger: "blur",
  228. },
  229. },
  230. tableform: {
  231. // fieldName0: { required: true, message: '请输入字段名称', trigger: 'blur' },
  232. // fieldType0: { required: true, message: '请选择', trigger: 'change' },
  233. // fieldLength0: { required: true, message: '请输入', trigger: 'blur' },
  234. },
  235. list: ["int", "varchar"],
  236. dataType: [], //数据类型字典
  237. Inoputdisabled: [],
  238. // 需要指定长度
  239. mysqlAllowLength: ["char", "varchar", "numeric", "decimal"],
  240. modifySQLString: {
  241. modify: {},
  242. delete: {},
  243. addNew: {},
  244. },
  245. };
  246. },
  247. async created() {
  248. await this.getDict();
  249. if (this.$route.query.tableName) {
  250. this.isEdited = true;
  251. this.info();
  252. } else {
  253. Object.keys(this.form).forEach((item) => {
  254. this.form[item] = "";
  255. });
  256. // this.experienceData = [];
  257. }
  258. },
  259. mounted() {
  260. this.initDragTable();
  261. },
  262. computed: {
  263. ...mapState({
  264. databaseName: (state) => state.user.dataSource.databaseName,
  265. databaseType: (state) => state.user.dataSource.databaseType,
  266. }),
  267. },
  268. watch: {
  269. experienceData: {
  270. handler(n, o) {
  271. // do something
  272. // this.experienceDataForm = {};
  273. let rulesAdd = {};
  274. this.experienceData.forEach((item, index) => {
  275. this.$set(
  276. this.experienceDataForm,
  277. "fieldName" + index,
  278. item.fieldName
  279. );
  280. this.$set(
  281. this.experienceDataForm,
  282. "fieldType" + index,
  283. item.fieldType
  284. );
  285. this.$set(
  286. this.experienceDataForm,
  287. "fieldLength" + index,
  288. item.fieldLength
  289. );
  290. // rulesAdd['' + index] = item.fieldName
  291. // rulesAdd['fieldType' + index] = item.fieldType
  292. // rulesAdd['fieldLength' + index] = item.fieldLength
  293. // this.experienceDataForm = {...rulesAdd}
  294. });
  295. },
  296. deep: true, // 深度监听父组件传过来对象变化
  297. immediate: true,
  298. },
  299. },
  300. methods: {
  301. /* 修改记录回调start */
  302. // 字段名称修改回调
  303. fieldNameChange(row) {
  304. if (!row.fieldName) return;
  305. if (this.databaseType == "mysql") {
  306. if (row.oldVal) {
  307. if (!this.modifySQLString.modify[row.oldVal.fieldName]) {
  308. this.modifySQLString.modify[row.oldVal.fieldName] = {};
  309. }
  310. //更改
  311. this.modifySQLString.modify[row.oldVal.fieldName].fieldName =
  312. this.mysqlMotifySQLString("fieldName", row);
  313. this.sqlStringList.push(this.mysqlMotifySQLString("fieldName", row));
  314. } else if (row.fieldType) {
  315. //新增
  316. this.modifySQLString.addNew[row.fieldName] =
  317. this.mysqlMotifySQLString("addNew", row);
  318. this.sqlStringList.push(this.mysqlMotifySQLString("addNew", row));
  319. }
  320. }
  321. },
  322. // 字段类型改变回调
  323. fieldTypeChange(index, row) {
  324. if (!row.fieldType) return;
  325. if (this.databaseType == "mysql") {
  326. if (!this.modifySQLString.modify[row.fieldName]) {
  327. this.modifySQLString.modify[row.fieldName] = {};
  328. }
  329. if (row.oldVal) {
  330. this.modifySQLString.modify[row.fieldName].fieldType =
  331. this.mysqlMotifySQLString("fieldType", row);
  332. this.sqlStringList.push(this.mysqlMotifySQLString("fieldType", row));
  333. } else if (row.fieldName) {
  334. //新增
  335. this.modifySQLString.addNew[row.fieldName] =
  336. this.mysqlMotifySQLString("addNew", row);
  337. this.sqlStringList.push(this.mysqlMotifySQLString("addNew", row));
  338. }
  339. }
  340. },
  341. // 字段长度改变回调
  342. fieldLengthChange(idnex, row) {
  343. if (!row.fieldLength) return;
  344. if (this.databaseType == "mysql") {
  345. if (!this.modifySQLString.modify[row.fieldName]) {
  346. this.modifySQLString.modify[row.fieldName] = {};
  347. }
  348. if (row.oldVal) {
  349. this.modifySQLString.modify[row.fieldName].fieldLength =
  350. this.mysqlMotifySQLString("fieldLength", row);
  351. this.sqlStringList.push(
  352. this.mysqlMotifySQLString("fieldLength", row)
  353. );
  354. }
  355. }
  356. },
  357. //处理非空选框问题
  358. isNullChange(row) {
  359. if (!row.isNull) {
  360. row.isPrimary = false;
  361. }
  362. if (this.databaseType == "mysql") {
  363. if (row.oldVal) {
  364. if (!this.modifySQLString.modify[row.fieldName]) {
  365. this.modifySQLString.modify[row.fieldName] = {};
  366. }
  367. this.modifySQLString.modify[row.fieldName].isNull = row.isNull
  368. ? this.mysqlMotifySQLString("NOT NULL", row)
  369. : this.mysqlMotifySQLString("NULL", row);
  370. this.sqlStringList.push(
  371. row.isNull
  372. ? this.mysqlMotifySQLString("NOT NULL", row)
  373. : this.mysqlMotifySQLString("NULL", row)
  374. );
  375. }
  376. }
  377. },
  378. // 处理主键选框问题
  379. hanleCheckbox(ind, row) {
  380. if (!this.modifySQLString.modify[row.fieldName]) {
  381. this.modifySQLString.modify[row.fieldName] = {};
  382. }
  383. if (row.isPrimary && (!row.oldVal || !row.oldVal.isPrimary)) {
  384. //添加新的主键
  385. this.modifySQLString.modify[row.fieldName].addPrimary =
  386. this.mysqlMotifySQLString("primary", row);
  387. this.sqlStringList.push(this.mysqlMotifySQLString("primary", row));
  388. }
  389. this.experienceData.forEach((item, index) => {
  390. if (index != ind) {
  391. if (item.oldVal?.isPrimary) {
  392. if (!this.modifySQLString.delete[item.fieldName]) {
  393. this.modifySQLString.delete[item.fieldName] = {};
  394. }
  395. //去掉原来的主键
  396. this.modifySQLString.delete[item.fieldName].dropPrimary =
  397. this.mysqlMotifySQLString("drop primary", item);
  398. this.sqlStringList.push(
  399. this.mysqlMotifySQLString("drop primary", item)
  400. );
  401. }
  402. item.isPrimary = false;
  403. }
  404. if (index == ind && item.isPrimary == true) {
  405. item.isNull = true;
  406. item.isAuto = true;
  407. }
  408. });
  409. },
  410. // 是否自增改变
  411. isAutoChange(row) {
  412. let sqlString = "";
  413. if (!this.modifySQLString.modify[row.fieldName]) {
  414. this.modifySQLString.modify[row.fieldName] = {};
  415. }
  416. if (row.oldVal) {
  417. if (row.oldVal.isAuto != row.isAuto) {
  418. this.modifySQLString.modify[row.fieldName].increment = row.isAuto
  419. ? this.mysqlMotifySQLString("increment", row)
  420. : this.mysqlMotifySQLString("no increment", row);
  421. sqlString = row.isAuto
  422. ? this.mysqlMotifySQLString("increment", row)
  423. : this.mysqlMotifySQLString("no increment", row);
  424. }
  425. } else {
  426. this.modifySQLString.modify[row.fieldName].increment = row.isAuto
  427. ? this.mysqlMotifySQLString("increment", row)
  428. : this.mysqlMotifySQLString("no increment", row);
  429. sqlString = row.isAuto
  430. ? this.mysqlMotifySQLString("increment", row)
  431. : this.mysqlMotifySQLString("no increment", row);
  432. }
  433. if (sqlString) {
  434. this.sqlStringList.push(sqlString);
  435. }
  436. },
  437. // 字段描述改变
  438. fieldDescriptionChange(row) {
  439. let sqlString = "";
  440. if (!this.modifySQLString.modify[row.fieldName]) {
  441. this.modifySQLString.modify[row.fieldName] = {};
  442. }
  443. if (row.oldVal) {
  444. if (row.oldVal.fieldDescription != row.fieldDescription) {
  445. this.modifySQLString.modify[row.fieldName].fieldDescription =
  446. this.mysqlMotifySQLString("describe", row);
  447. sqlString = this.mysqlMotifySQLString("describe", row);
  448. }
  449. } else {
  450. this.modifySQLString.modify[row.fieldName].fieldDescription =
  451. this.mysqlMotifySQLString("describe", row);
  452. sqlString = this.mysqlMotifySQLString("describe", row);
  453. }
  454. if (sqlString) {
  455. this.sqlStringList.push(sqlString);
  456. }
  457. },
  458. // 删除字段回调
  459. deleteField(row) {
  460. let sqlString = "";
  461. if (row.oldVal) {
  462. this.modifySQLString.delete[row.fieldName] = this.mysqlMotifySQLString(
  463. "deleteField",
  464. row
  465. );
  466. sqlString = this.mysqlMotifySQLString("deleteField", row);
  467. }
  468. delete this.modifySQLString.modify[row.fieldName];
  469. delete this.modifySQLString.addNew[row.fieldName];
  470. // delete this.modifySQLString.delete[row.fieldName];
  471. if (sqlString) {
  472. this.sqlStringList.push(sqlString);
  473. }
  474. },
  475. // 拼接mysql的修改语句
  476. mysqlMotifySQLString(type, row) {
  477. let table_name = this.form.tableName,
  478. res = "ALTER TABLE";
  479. switch (type) {
  480. case "fieldName": //改字段
  481. res += ` ${table_name} CHANGE ${row.oldVal.fieldName} ${row.fieldName} ${row.fieldType};`;
  482. break;
  483. case "fieldLength": //改长度
  484. res += ` ${table_name} MODIFY ${row.fieldName} ${row.fieldType}(${row.fieldLength});`;
  485. break;
  486. case "fieldType": //改类型
  487. res += ` ${table_name} MODIFY ${row.fieldName} ${row.fieldType};`;
  488. break;
  489. case "NULL": //改允许为NULL
  490. res += ` ${table_name} MODIFY ${row.fieldName} ${row.fieldType} NULL;`;
  491. break;
  492. case "NOT NULL": //改不允许为NULL
  493. res += ` ${table_name} MODIFY ${row.fieldName} ${row.fieldType} NOT NULL;`;
  494. break;
  495. case "primary": //设为主键
  496. res += ` ${table_name} ADD PRIMARY KEY (${row.fieldName});`;
  497. break;
  498. case "drop primary": //删除主键
  499. res += ` ${table_name} DROP PRIMARY KEY;`;
  500. break;
  501. case "increment": //添加自增
  502. res += ` ${table_name} MODIFY ${row.fieldName} INT AUTO_INCREMENT;`;
  503. break;
  504. case "no increment": //删除自增属性
  505. res += ` ${table_name} MODIFY ${row.fieldName} INT;`;
  506. break;
  507. case "describe": //修改字段描述
  508. res += ` ${table_name} MODIFY ${row.fieldName} ${row.fieldType}${
  509. row.fieldLength ? "" : "(" + row.fieldLength + ")"
  510. } comment '${row.fieldDescription}';`;
  511. break;
  512. case "deleteField":
  513. res += ` ${table_name} DROP ${row.fieldName};`;
  514. break;
  515. case "addNew": //新增列
  516. res += ` ${table_name} ADD ${row.fieldName} ${row.fieldType};`;
  517. break;
  518. default:
  519. break;
  520. }
  521. return res;
  522. },
  523. // 获取sql列表
  524. getSQLStringList() {
  525. let res = [];
  526. console.log(this.modifySQLString);
  527. let deleteList = Object.values(this.modifySQLString.delete);
  528. if (deleteList.length) {
  529. for (const value of deleteList) {
  530. res.push(Object.values(value)[0]);
  531. }
  532. }
  533. let addNewList = Object.values(this.modifySQLString.addNew);
  534. if (addNewList.length) {
  535. res = [...res, ...addNewList];
  536. }
  537. let modifyList = Object.values(this.modifySQLString.modify);
  538. if (modifyList.length) {
  539. for (const value of modifyList) {
  540. res.push(Object.values(value)[0]);
  541. }
  542. }
  543. console.log(res);
  544. return res;
  545. },
  546. /* 修改记录回调start */
  547. // 加载数据字典
  548. async getDict() {
  549. let res = await this.getDicts(this.databaseType + "_data_type");
  550. if (res.code == 200) {
  551. this.dataType = res.data.map((item) => {
  552. return {
  553. raw: item,
  554. value: item.dictValue,
  555. label: item.dictLabel,
  556. };
  557. });
  558. } else {
  559. console.log(res.msg);
  560. }
  561. },
  562. // 初始化表格数据
  563. info() {
  564. const tableName = this.$route.query.tableName;
  565. const tableComment = this.$route.query.tableComment;
  566. this.form.tableName = tableName;
  567. this.form.tableComment = tableComment;
  568. let data = {
  569. tableName,
  570. databaseType: this.databaseType,
  571. databaseName: this.databaseName,
  572. };
  573. tableInfo(data).then((response) => {
  574. this.experienceData = [];
  575. response.data.forEach((item, index) => {
  576. item.oldVal = JSON.parse(JSON.stringify(item)); // 保留原始数据
  577. // item.sort = index;
  578. item.tag = uuidv4();
  579. this.experienceData.push(item);
  580. this.handleRules("add");
  581. });
  582. // 初始化校验规则
  583. this.initInputEditable();
  584. });
  585. },
  586. // 初始化长度框是否禁用
  587. initInputEditable() {
  588. this.experienceData.map((val, index) => {
  589. let temp = JSON.parse(JSON.stringify(this.dataType));
  590. let targetDictItem = temp.find((item) => {
  591. return item.label === val.fieldType;
  592. });
  593. this.handleSelected(targetDictItem, { $index: index, row: val });
  594. });
  595. },
  596. // 处理长度框是否可输入
  597. changduclick(inputIndex) {
  598. return this.Inoputdisabled[inputIndex];
  599. },
  600. // 下拉选中事件 // 处理选中类型后长度输入框是否禁用
  601. handleSelected(tem, scope, index, val) {
  602. console.log(val);
  603. if (val) {
  604. //判断是否是由change事件触发的函数
  605. this.fieldTypeChange(index, val);
  606. }
  607. if (tem == undefined) return;
  608. if (!this.tableform["fieldLength" + scope.$index]) {
  609. this.tableform["fieldLength" + scope.$index] = {};
  610. }
  611. if (tem.raw.listClass === "success") {
  612. this.Inoputdisabled[scope.$index] = true; // 禁用长度输入框
  613. scope.row.fieldLength = "";
  614. this.tableform["fieldLength" + scope.$index].required = false; // 禁用长度输入框的校验
  615. return this.$set(
  616. this.experienceDataForm,
  617. "fieldType" + scope.$index,
  618. scope.row.fieldType
  619. );
  620. }
  621. this.Inoputdisabled[scope.$index] = false; // 解除禁用
  622. this.tableform["fieldLength" + scope.$index].required = true; // 启用长度输入框的校验
  623. return this.$set(
  624. this.experienceDataForm,
  625. "fieldType" + scope.$index,
  626. scope.row.fieldType
  627. );
  628. },
  629. // 下拉选中事件
  630. selectBlur(aa) {
  631. if (aa.row.fieldType == "") {
  632. aa.row.fieldType = undefined;
  633. }
  634. },
  635. //判断一个字符串是否只包含数字、下划线和小写字母
  636. isValidString(str) {
  637. const regex = /^[a-z0-9_]+$/;
  638. return regex.test(str);
  639. },
  640. // 字段名规则校验
  641. checkFieldName(rule, value, callback) {
  642. let msg = "";
  643. if (!value.trim().length) {
  644. msg = "请输入字段名称";
  645. this.$message.error(msg);
  646. callback(new Error(msg));
  647. } else if (value[0] == "_") {
  648. msg = "请不要以下划线开头";
  649. this.$message.error(msg);
  650. callback(new Error(msg));
  651. } else if (!isNaN(value[0])) {
  652. msg = "请不要以数字开头";
  653. this.$message.error(msg);
  654. callback(new Error(msg));
  655. } else if (!this.isValidString(value)) {
  656. msg = "字段名应该只有下划线,数字和小写字母";
  657. this.$message.error(msg);
  658. callback(new Error(msg));
  659. } else {
  660. //字段名去重校验
  661. if (
  662. this.experienceData.filter((item) => item.fieldName == value)
  663. .length == 1
  664. ) {
  665. callback();
  666. } else {
  667. callback(new Error("字段名称不能重复"));
  668. }
  669. }
  670. },
  671. // 校验数据表名称
  672. checkTableName(rule, value, callback) {
  673. let msg = "";
  674. if (!value.trim().length) {
  675. msg = "请输入数据表名称";
  676. this.$message.error(msg);
  677. callback(new Error(msg));
  678. } else if (value[0] == "_") {
  679. msg = "数据表名,请不要以下划线开头";
  680. this.$message.error(msg);
  681. callback(new Error(msg));
  682. } else if (!isNaN(value[0])) {
  683. msg = "数据表名,请不要以数字开头";
  684. this.$message.error(msg);
  685. callback(new Error(msg));
  686. } else if (!this.isValidString(value)) {
  687. msg = "数据表名,字段名应该只有下划线,数字和小写字母";
  688. this.$message.error(msg);
  689. callback(new Error(msg));
  690. } else {
  691. callback();
  692. }
  693. },
  694. //
  695. // 处理非空校验问题
  696. handleRules(type, delindex, addindex) {
  697. if (type == "add") {
  698. let rulesAdd = {};
  699. // 得到添加一行的下标
  700. let index = this.experienceData.length - 1;
  701. rulesAdd["fieldName" + index] = [
  702. {
  703. required: true,
  704. message: "请输入字段名称",
  705. trigger: "blur",
  706. },
  707. {
  708. validator: this.checkFieldName,
  709. trigger: "blur",
  710. },
  711. ];
  712. rulesAdd["fieldType" + index] = {
  713. required: true,
  714. message: "请选择",
  715. trigger: "change",
  716. };
  717. rulesAdd["fieldLength" + index] = {
  718. required: true,
  719. message: "请输入",
  720. trigger: "blur",
  721. };
  722. // 序列化当前校验规则对象
  723. this.tableform = {
  724. ...this.tableform,
  725. ...rulesAdd,
  726. };
  727. } else if (type == "del") {
  728. // 删除校验规则对象中的元素
  729. this.$delete(this.tableform, "fieldName" + delindex);
  730. this.$delete(this.tableform, "fieldType" + delindex);
  731. this.$delete(this.tableform, "fieldLength" + delindex);
  732. }
  733. },
  734. // 校验表格数据完整性
  735. validateTableData() {
  736. return this.experienceData.every((item) => {
  737. return item.fieldName && item.fieldType;
  738. });
  739. },
  740. //增加经验行
  741. handleAddExperienceline() {
  742. let flag = this.validateTableData();
  743. if (!flag) {
  744. this.$message.error("请完善表单信息");
  745. return;
  746. }
  747. if (this.experienceData == undefined) {
  748. this.experienceData = new Array();
  749. }
  750. let obj = {
  751. sort: this.experienceData.length + 1,
  752. tag: uuidv4(),
  753. fieldName: "",
  754. fieldType: "",
  755. fieldLength: undefined,
  756. isDisableFieldLength: true,
  757. isNull: false,
  758. isPrimary: false,
  759. fieldDescription: "",
  760. isAuto: false,
  761. };
  762. this.experienceData.push(obj);
  763. this.handleRules("add");
  764. this.Inoputdisabled.push(false);
  765. },
  766. //保存经验行
  767. handlesaveExperience(a, b) {
  768. // console.log(a + b);
  769. // console.log(b);
  770. },
  771. //删除经验行
  772. handleDeleteExperience(index, row) {
  773. this.experienceData.splice(index, 1);
  774. this.handleRules("del", index);
  775. this.deleteField(row);
  776. this.initInputEditable();
  777. },
  778. add() {
  779. const rule1 = new Promise((resolve, reject) => {
  780. this.$refs["form"].validate((valid) => {
  781. if (valid) {
  782. resolve();
  783. } else {
  784. return false;
  785. }
  786. });
  787. });
  788. const rule2 = new Promise((resolve, reject) => {
  789. this.$refs["tableform"].validate((valid) => {
  790. if (valid) {
  791. resolve();
  792. } else {
  793. return false;
  794. }
  795. });
  796. });
  797. Promise.all([rule1, rule2]).then(() => {
  798. if (this.experienceData.length == 0) {
  799. this.$modal.msgWarning("字段不可为空!");
  800. return;
  801. }
  802. this.experienceData.forEach((field) => {
  803. if (field.fieldLength) {
  804. field.fieldType = `${field.fieldType}(${field.fieldLength})`;
  805. }
  806. });
  807. let query = {
  808. databaseType: this.$store.state.user.dataSource.databaseType,
  809. databaseName: this.$store.state.user.dataSource.databaseName,
  810. tableName: this.form.tableName,
  811. tableComment: this.form.tableComment,
  812. field: this.experienceData,
  813. };
  814. createDatabase(query)
  815. .then((res) => {
  816. this.$modal.msgSuccess(res.msg);
  817. if (res.code === 200) {
  818. this.visible = false;
  819. this.$emit("ok");
  820. Object.keys(this.form).forEach((key) => (this.form[key] = ""));
  821. this.experienceData = [];
  822. this.$tab.closePage().then(() => {
  823. this.$router.push({
  824. path: "/data/datamodeling",
  825. });
  826. });
  827. // 新增成功之后关闭当前页面
  828. // this.$router.replace({
  829. // path: "/data/datamodeling",
  830. // });
  831. }
  832. })
  833. .catch((err) => {
  834. console.log(err);
  835. });
  836. });
  837. },
  838. edit() {
  839. const rule1 = new Promise((resolve, reject) => {
  840. this.$refs["form"].validate((valid) => {
  841. if (valid) {
  842. resolve();
  843. } else {
  844. return false;
  845. }
  846. });
  847. });
  848. const rule2 = new Promise((resolve, reject) => {
  849. this.$refs["tableform"].validate((valid) => {
  850. if (valid) {
  851. resolve();
  852. } else {
  853. return false;
  854. }
  855. });
  856. });
  857. Promise.all([rule1, rule2]).then(() => {
  858. if (this.experienceData.length == 0) {
  859. this.$modal.msgWarning("字段不可为空!");
  860. return;
  861. }
  862. this.experienceData = this.experienceData.filter((item) => {
  863. return item.fieldName && item.fieldType;
  864. });
  865. this.experienceData.forEach((field) => {
  866. if (field.fieldLength) {
  867. field.fieldType = `${field.fieldType}(${field.fieldLength})`;
  868. }
  869. });
  870. // console.log(this.sqlStringList);
  871. // return;
  872. let query = {
  873. databaseType: this.$store.state.user.dataSource.databaseType,
  874. databaseName: this.$store.state.user.dataSource.databaseName,
  875. tableName: this.form.tableName,
  876. tableComment: this.form.tableComment,
  877. field: this.experienceData,
  878. };
  879. editTable(query)
  880. .then((res) => {
  881. this.$modal.msgSuccess(res.msg);
  882. if (res.code === 200) {
  883. this.visible = false;
  884. this.$emit("ok");
  885. Object.keys(this.form).forEach((key) => (this.form[key] = ""));
  886. this.experienceData = [];
  887. this.$tab.closePage().then(() => {
  888. this.$router.push({
  889. path: "/data/datamodeling",
  890. });
  891. });
  892. }
  893. })
  894. .catch((err) => {
  895. console.log(err);
  896. });
  897. // 关闭当前页面
  898. this.$tab.closePage();
  899. });
  900. },
  901. //处理表格行拖拽
  902. initDragTable() {
  903. const el = this.$refs.dragTable.$el.querySelectorAll(
  904. ".el-table__body-wrapper > table > tbody"
  905. )[0];
  906. const sortable = Sortable.create(el, {
  907. handle: ".allowDrag",
  908. onEnd: (evt) => {
  909. const targetRow = this.experienceData.splice(evt.oldIndex, 1)[0];
  910. this.experienceData.splice(evt.newIndex, 0, targetRow);
  911. for (let index in this.experienceData) {
  912. this.experienceData[index].sort = parseInt(index) + 1;
  913. }
  914. // 初始化校验规则
  915. this.experienceData.map((val, index) => {
  916. let temp = JSON.parse(JSON.stringify(this.dataType));
  917. let targetDictItem = temp.find((item) => {
  918. return item.label === val.fieldType;
  919. });
  920. this.handleSelected(targetDictItem, { $index: index, row: val });
  921. });
  922. this.$nextTick(() => {
  923. this.$refs.dragTable.doLayout();
  924. });
  925. },
  926. });
  927. },
  928. },
  929. };
  930. </script>
  931. <style scoped lang="scss"></style>