edit.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. <template>
  2. <div class="card-edit">
  3. <a-form :model="dataModel" @finish="onFinish" autocomplete="off">
  4. <a-divider orientation="left">主题定义</a-divider>
  5. <a-row :gutter="24">
  6. <a-col :span="8">
  7. <a-form-item :label-col="{span:6}" label="主题名称" name="subjectName"
  8. :rules="[{ required: true, message: '请填写主题名称!' }]">
  9. <a-input v-model:value="dataModel.subjectName" placeholder="">
  10. </a-input>
  11. </a-form-item>
  12. </a-col>
  13. <a-col :span="8">
  14. <a-form-item :label-col="{span:6}" label="表编码" name="tabCode"
  15. :rules="[{ required: true, message: '请填写表编码!' }]">
  16. <a-input v-model:value="dataModel.tabCode" placeholder="">
  17. </a-input>
  18. </a-form-item>
  19. </a-col>
  20. <a-col :span="8">
  21. <a-form-item :label-col="{span:6}" label="表名称" name="tabName"
  22. :rules="[{ required: true, message: '请填表名称!' }]">
  23. <a-input v-model:value="dataModel.tabName" placeholder="">
  24. </a-input>
  25. </a-form-item>
  26. </a-col>
  27. </a-row>
  28. <a-row :gutter="24">
  29. <a-col :span="8">
  30. <a-form-item :label-col="{span:8}" label="是否有外键字段" name="isReferences"
  31. :rules="[{ required: true, message: '请填写是否有外键字段!' }]">
  32. <a-radio-group v-model:value="dataModel.isReferences">
  33. <a-radio :value="1">是</a-radio>
  34. <a-radio :value="0">否</a-radio>
  35. </a-radio-group>
  36. </a-form-item>
  37. </a-col>
  38. <a-col :span="8">
  39. <a-form-item :label-col="{span:6}" label="描述" name="tabDesc">
  40. <a-input v-model:value="dataModel.tabDesc" placeholder="">
  41. </a-input>
  42. </a-form-item>
  43. </a-col>
  44. </a-row>
  45. <a-divider orientation="left">字段定义</a-divider>
  46. <a-row>
  47. <a-col :span="24" style="margin-right: 20px;">
  48. <div style="float: right;">
  49. <Space>
  50. <BImportExcel :options="importOptions" @success="onImportSuccess"></BImportExcel>
  51. &nbsp;
  52. <a-button @click="add()">
  53. <template #icon>
  54. <plus-circle-outlined/>
  55. </template>
  56. 新增
  57. </a-button>
  58. </Space>
  59. </div>
  60. </a-col>
  61. </a-row>
  62. <a-row>
  63. <a-col style="margin-bottom: 20px;">
  64. <a-table :columns="columns" :data-source="fieldData" :scroll="{ x:'100%', y: 500 }" :pagination="false"
  65. bordered>
  66. <template #bodyCell="{ column ,record,index}">
  67. <template v-if="column.key === 'operation'">
  68. <a-button type="link" size="small" @click="edit(record)">修改</a-button>
  69. <a-popconfirm placement="leftTop"
  70. title="是否删除数据?"
  71. @confirm="onDelete(index)">
  72. <a-button type="link" size="small">删除</a-button>
  73. </a-popconfirm>
  74. </template>
  75. </template>
  76. </a-table>
  77. </a-col>
  78. </a-row>
  79. <a-divider orientation="left">Sql预览</a-divider>
  80. <a-row>
  81. <a-col class="table-bottom-a1">
  82. <a-form-item :label-col="{span:8}" label="" name="remark">
  83. <codemirror
  84. v-model="code"
  85. :style="{ height: '100px',width:'100%' }"
  86. :autofocus="true"
  87. :indent-with-tab="true"
  88. :lang="lang"
  89. disabled="false"
  90. tab-size="2"
  91. :theme="'oneDark'"
  92. />
  93. </a-form-item>
  94. </a-col>
  95. </a-row>
  96. <a-row>
  97. <a-col :span="24" style="text-align: right;margin: 20px;">
  98. <Space>
  99. <a-form-item class="buttom-btns">
  100. <a-button @click="onClose">取消</a-button>
  101. <a-button type="primary" html-type="submit">提交</a-button>
  102. </a-form-item>
  103. </Space>
  104. </a-col>
  105. </a-row>
  106. </a-form>
  107. <FieldEdit ref="modalRef" :onSave="onFieldSave"></FieldEdit>
  108. </div>
  109. </template>
  110. <script lang="ts">
  111. import {defineComponent, reactive, ref, toRefs, watch} from 'vue';
  112. import {useTabsViewStore} from '@/store/modules/tabsView';
  113. import BUploadFile from "@/components/file/uploadFile.vue";
  114. import type {TableColumnsType} from 'ant-design-vue';
  115. import {get, save} from '@/api/common';
  116. import FieldEdit from "@/views/subject/fieldedit.vue";
  117. import {getDictionaryItemList} from "@/api/system/dictionary";
  118. import {Codemirror} from 'vue-codemirror';
  119. import {oneDark} from '@codemirror/theme-one-dark';
  120. import {sql, MySQL} from '@codemirror/lang-sql';
  121. import type {Subjectfield, Subject} from "@/views/subject/model";
  122. import type {ImportProps} from "@/components/basic/excel/importExcel/ImportProps";
  123. import BImportExcel from "@/components/basic/excel/importExcel/importExcel.vue";
  124. import {message} from "ant-design-vue";
  125. interface FormState {
  126. dataModel: Subject;
  127. }
  128. export default defineComponent({
  129. name: 'subjectEditForm',
  130. components: {
  131. BUploadFile, FieldEdit, Codemirror, MySQL, sql, oneDark, BImportExcel
  132. },
  133. setup() {
  134. const subject: Subject = {
  135. subjectName: "",
  136. tabCode: "",
  137. tabName: "",
  138. isReferences: 0,
  139. tabDesc: "",
  140. execSql: ""
  141. }
  142. const formState = reactive<FormState>({dataModel: subject});
  143. const tabsViewStore = useTabsViewStore();
  144. const modalRef = ref();
  145. const fieldData = ref<Subjectfield[]>([]);
  146. const settingTypeList = ref([{name: '', value: ''}]);
  147. const queryTypeList = ref([{name: '', value: ''}]);
  148. const lang = sql();
  149. const code = ref("");
  150. let isEdit = false;
  151. const onFinish = () => {
  152. if (fieldData.value.length == 0) {
  153. message.warn("尚未添加任何字段定义。");
  154. return;
  155. }
  156. save('/subject/saveSubject', {dataModel: formState.dataModel, fieldList: fieldData.value}).then(result => {
  157. if (result) {
  158. onClose(1)
  159. }
  160. });
  161. };
  162. const onClose = (reload: any) => {
  163. tabsViewStore.closeCurrentTabByPath("/views/subjectedit");
  164. tabsViewStore.openTab("/subject/list", {reload: reload});
  165. };
  166. getDictionaryItemList({code: "queryType"}).then(data => {
  167. queryTypeList.value = data;
  168. });
  169. getDictionaryItemList({code: "settingType"}).then(data => {
  170. settingTypeList.value = data;
  171. });
  172. const onFieldSave = async (model: Subjectfield) => {
  173. if (!isEdit) {
  174. fieldData.value.push(model);
  175. }
  176. formState.dataModel.isReferences = fieldData.value.filter((x) => x.isForeignKey == 1).length > 0 ? 1 : 0;
  177. }
  178. const columns: TableColumnsType = [
  179. {
  180. title: '序号', width: 80, dataIndex: 'num', key: 'num', align: "center", customRender: ({index}) => {
  181. return `${index + 1}`;
  182. }
  183. },
  184. {title: '字段编码', dataIndex: 'fieldCode', key: 'fieldCode', align: "center"},
  185. {title: '字段名称', dataIndex: 'fieldName', key: 'fieldName', align: "center"},
  186. {
  187. title: '配置类型', dataIndex: 'settingTypeId', key: 'settingTypeId', align: "center", customRender: ({record}) => {
  188. return settingTypeList.value.filter(x => x.value == record.settingTypeId)[0]?.name;
  189. }
  190. },
  191. {
  192. title: '是否查询字段', dataIndex: 'isSearchField', key: 'isSearchField', align: "center", customRender: ({record}) =>
  193. record.isSearchField == "1" ? "是" : "否"
  194. },
  195. {
  196. title: '查询类型', dataIndex: 'queryTypeId', key: 'queryTypeId', align: "center", customRender: ({record}) =>
  197. queryTypeList.value.filter(x => x.value == record.queryTypeId)[0]?.name
  198. },
  199. {title: '取数字典编码', dataIndex: 'dictionaryCode', key: 'dictionaryCode', align: "center"},
  200. {title: '显示排序', dataIndex: 'disOrder', key: 'disOrder', align: "center"},
  201. {
  202. title: '是否关联字段', dataIndex: 'isForeignKey', key: 'isForeignKey', align: "center", customRender: ({record}) =>
  203. record.isForeignKey == "1" ? "是" : "否"
  204. },
  205. {title: '显示别名', dataIndex: 'fieldAlias', key: 'fieldAlias', align: "center"},
  206. {title: '外键表', dataIndex: 'referencesTab', key: 'referencesTab', align: "center"},
  207. {title: '外键列', dataIndex: 'foreignKey', key: 'foreignKey', align: "center"},
  208. {title: '外键表显示列', dataIndex: 'displayColumn', key: 'displayColumn', align: "center"},
  209. {title: '操作', key: 'operation', fixed: 'right', width: 120, align: "center"},
  210. ];
  211. const importOptions = ref<ImportProps>({
  212. title: "导入",
  213. url: 'subject/importData',
  214. columns: [
  215. {cnName: "字段编码", enName: "fieldCode", width: 100},
  216. {cnName: "字段名称", enName: "fieldName", width: 200},
  217. {cnName: "配置类型", enName: "settingTypeName", width: 200},
  218. {cnName: "字段描述", enName: "fieldDesc", width: 100},
  219. {cnName: "数据类型", enName: "dataType", width: 150},
  220. {cnName: "查询类型", enName: "queryTypeName", width: 100},
  221. {cnName: "取数字典编码", enName: "dictionaryCode", width: 200},
  222. {cnName: "显示排序", enName: "disOrder", width: 200},
  223. {cnName: "是否查询字段", enName: "isSearchFieldText", width: 200},
  224. {cnName: "是否关联字段", enName: "isForeignKeyText", width: 100},
  225. {cnName: "外键表", enName: "referencesTab", width: 150},
  226. {cnName: "外键列", enName: "foreignKey", width: 150},
  227. {cnName: "外键表显示列", enName: "displayColumn", width: 150},
  228. {cnName: "显示别名", enName: "fieldAlias", width: 200},
  229. ],
  230. template: {
  231. tempFileName: "主题字段导入模板.xlsx",
  232. url: '',
  233. params: null
  234. }
  235. });
  236. const onImportSuccess = (data: []) => {
  237. fieldData.value = fieldData.value.concat(data);
  238. formState.dataModel.isReferences = fieldData.value.filter((x) => x.isForeignKey == 1).length > 0 ? 1 : 0;
  239. }
  240. const data = ref([]);
  241. const add = () => {
  242. isEdit = false;
  243. modalRef.value.show(null);
  244. }
  245. const edit = (record) => {
  246. isEdit = true;
  247. modalRef.value.show(record);
  248. }
  249. const onDelete = (record) => {
  250. fieldData.value.splice(record, 1);
  251. }
  252. const loadData = (id) => {
  253. if (id != undefined) {
  254. get('subject/getSubject',
  255. {subjectId: id}).then(data => {
  256. formState.dataModel = data;
  257. })
  258. get('subject/getFieldList',
  259. {subjectId: id}).then(data => {
  260. fieldData.value = data;
  261. })
  262. }
  263. }
  264. watch(
  265. () => [formState.dataModel.tabCode, fieldData],
  266. () => {
  267. code.value = ` select ${formState.dataModel.tabCode}.*`;
  268. fieldData.value.filter(x => x.isForeignKey == 1).forEach(x => {
  269. code.value += `,${x.referencesTab}.${x.displayColumn} as ${x.fieldAlias}`
  270. })
  271. code.value += ` from ${formState.dataModel.tabCode}`;
  272. fieldData.value.filter(x => x.isForeignKey == 1).forEach(x => {
  273. code.value += ` left join ${x.referencesTab} on ${formState.dataModel.tabCode}.${x.fieldCode}=${x.referencesTab}.${x.foreignKey}`
  274. })
  275. }, {deep: true}
  276. );
  277. return {
  278. ...toRefs(formState),
  279. onFinish, onFieldSave, onClose, add, onImportSuccess,
  280. edit, importOptions,
  281. onDelete,
  282. loadData, oneDark,
  283. fieldData, columns,
  284. isEdit, data, lang, code, modalRef,
  285. };
  286. },
  287. created() {
  288. const id = history.state.params?.id;
  289. this.loadData(id);
  290. }
  291. })
  292. </script>