表格.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. <template>
  2. <div class="layout-padding">
  3. <div class="layout-padding-auto layout-padding-view">
  4. #if($queryList)
  5. <!-- 查询表单区域 -->
  6. <el-row v-show="showSearch">
  7. <el-form :model="state.queryForm" ref="queryRef" :inline="true" @keyup.enter="getDataList">
  8. #foreach($field in $queryList)
  9. #if($field.queryFormType == 'select')
  10. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">
  11. <el-select v-model="state.queryForm.${field.attrName}" placeholder="请选择#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end">
  12. #if($field.fieldDict)
  13. <el-option
  14. :label="item.label"
  15. :value="item.value"
  16. v-for="(item, index) in ${field.fieldDict}"
  17. :key="index"
  18. />
  19. #else
  20. <el-option label="请选择" value="0" />
  21. #end
  22. </el-select>
  23. </el-form-item>
  24. #elseif($field.queryFormType == 'date')
  25. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">
  26. <el-date-picker
  27. type="date"
  28. placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"
  29. v-model="state.queryForm.${field.attrName}"
  30. :value-format="dateStr"
  31. />
  32. </el-form-item>
  33. #elseif($field.queryFormType == 'datetime')
  34. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">
  35. <el-date-picker
  36. type="datetime"
  37. placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"
  38. v-model="state.queryForm.${field.attrName}"
  39. :value-format="dateTimeStr"
  40. />
  41. </el-form-item>
  42. #elseif($field.queryFormType == 'date-range')
  43. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">
  44. <el-date-picker
  45. type="daterange"
  46. start-placeholder="开始日期"
  47. end-placeholder="结束日期"
  48. v-model="state.queryForm.${field.attrName}Range"
  49. :value-format="dateStr"
  50. range-separator="至"
  51. />
  52. </el-form-item>
  53. #elseif($field.queryFormType == 'datetime-range')
  54. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}Range">
  55. <el-date-picker
  56. type="datetimerange"
  57. start-placeholder="开始时间"
  58. end-placeholder="结束时间"
  59. v-model="state.queryForm.${field.attrName}Range"
  60. :value-format="dateTimeStr"
  61. range-separator="至"
  62. />
  63. </el-form-item>
  64. #elseif($field.formType == 'radio')
  65. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">
  66. <el-radio-group v-model="state.queryForm.${field.attrName}">
  67. #if($field.fieldDict)
  68. <el-radio
  69. :label="item.value"
  70. v-for="(item, index) in ${field.fieldDict}"
  71. border
  72. :key="index"
  73. >
  74. {{ item.label }}
  75. </el-radio>
  76. #else
  77. <el-radio label="${field.fieldComment}" border>
  78. ${field.fieldComment}
  79. </el-radio>
  80. #end
  81. </el-radio-group>
  82. </el-form-item>
  83. #else
  84. <el-form-item label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" prop="${field.attrName}">
  85. <el-input
  86. placeholder="请输入#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"
  87. v-model="state.queryForm.${field.attrName}"
  88. />
  89. </el-form-item>
  90. #end
  91. #end
  92. <el-form-item>
  93. <el-button icon="search" type="primary" @click="getDataList">
  94. 查询
  95. </el-button>
  96. <el-button icon="Refresh" @click="resetQuery">重置</el-button>
  97. </el-form-item>
  98. </el-form>
  99. </el-row>
  100. #end
  101. <!-- 操作按钮区域 -->
  102. <el-row>
  103. <div class="mb8" style="width: 100%">
  104. <el-button
  105. icon="folder-add"
  106. type="primary"
  107. class="ml10"
  108. @click="formDialogRef.openDialog()"
  109. v-auth="'${moduleName}_${functionName}_add'"
  110. >
  111. 新增
  112. </el-button>
  113. <el-button
  114. plain
  115. icon="upload-filled"
  116. type="primary"
  117. class="ml10"
  118. @click="excelUploadRef.show()"
  119. v-auth="'${moduleName}_${functionName}_add'"
  120. >
  121. 导入
  122. </el-button>
  123. <el-button
  124. plain
  125. :disabled="multiple"
  126. icon="Delete"
  127. type="primary"
  128. v-auth="'${moduleName}_${functionName}_del'"
  129. @click="handleDelete(selectObjs)"
  130. >
  131. 删除
  132. </el-button>
  133. <right-toolbar
  134. v-model:showSearch="showSearch"
  135. :export="'${moduleName}_${functionName}_export'"
  136. @exportExcel="exportExcel"
  137. class="ml10 mr20"
  138. style="float: right;"
  139. @queryTable="getDataList"
  140. />
  141. </div>
  142. </el-row>
  143. <!-- 数据表格区域 -->
  144. <el-table
  145. :data="state.dataList"
  146. v-loading="state.loading"
  147. border
  148. :cell-style="tableStyle.cellStyle"
  149. :header-cell-style="tableStyle.headerCellStyle"
  150. @selection-change="selectionChangHandle"
  151. @sort-change="sortChangeHandle"
  152. >
  153. <el-table-column type="selection" width="40" align="center" />
  154. <el-table-column type="index" label="#" width="40" />
  155. #foreach($field in $gridList)
  156. #if($field.fieldDict)
  157. <el-table-column prop="${field.attrName}" label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" show-overflow-tooltip>
  158. <template #default="scope">
  159. <dict-tag :options="$field.fieldDict" :value="scope.row.${field.attrName}" />
  160. </template>
  161. </el-table-column>
  162. #elseif($field.formType == 'upload-img')
  163. <el-table-column prop="${field.attrName}" label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end" width="120">
  164. <template #default="scope">
  165. <el-image
  166. v-if="scope.row.${field.attrName}"
  167. :src="scope.row.${field.attrName}"
  168. :preview-src-list="[scope.row.${field.attrName}]"
  169. fit="cover"
  170. class="w-20 h-20 rounded"
  171. :preview-teleported="true"
  172. />
  173. <span v-else class="text-gray-400">暂无图片</span>
  174. </template>
  175. </el-table-column>
  176. #else
  177. <el-table-column
  178. prop="${field.attrName}"
  179. label="#if(${field.fieldComment})${field.fieldComment}#else${field.attrName}#end"
  180. #if(${field.gridSort} == '1')
  181. sortable="custom"
  182. #end
  183. show-overflow-tooltip
  184. />
  185. #end
  186. #end
  187. <el-table-column label="操作" width="150">
  188. <template #default="scope">
  189. <el-button
  190. icon="edit-pen"
  191. text
  192. type="primary"
  193. v-auth="'${moduleName}_${functionName}_edit'"
  194. @click="formDialogRef.openDialog(scope.row.${pk.attrName})"
  195. >
  196. 编辑
  197. </el-button>
  198. <el-button
  199. icon="delete"
  200. text
  201. type="primary"
  202. v-auth="'${moduleName}_${functionName}_del'"
  203. @click="handleDelete([scope.row.${pk.attrName}])"
  204. >
  205. 删除
  206. </el-button>
  207. </template>
  208. </el-table-column>
  209. </el-table>
  210. <!-- 分页组件 -->
  211. <pagination
  212. @size-change="sizeChangeHandle"
  213. @current-change="currentChangeHandle"
  214. v-bind="state.pagination"
  215. />
  216. </div>
  217. <!-- 编辑、新增弹窗 -->
  218. <form-dialog ref="formDialogRef" @refresh="getDataList(false)" />
  219. <!-- 导入excel弹窗 (需要在 upms-biz/resources/file 下维护模板) -->
  220. <upload-excel
  221. ref="excelUploadRef"
  222. title="导入"
  223. url="/${moduleName}/${functionName}/import"
  224. temp-url="/admin/sys-file/local/file/${functionName}.xlsx"
  225. @refreshDataList="getDataList"
  226. />
  227. </div>
  228. </template>
  229. <script setup lang="ts" name="system${ClassName}">
  230. // ========== 导入声明 ==========
  231. import { BasicTableProps, useTable } from "/@/hooks/table";
  232. import { fetchList, delObjs } from "/@/api/${moduleName}/${functionName}";
  233. import { useMessage, useMessageBox } from "/@/hooks/message";
  234. import { useDict } from '/@/hooks/dict';
  235. // ========== 组件声明 ==========
  236. // 异步加载表单弹窗组件
  237. const FormDialog = defineAsyncComponent(() => import('./form.vue'));
  238. // ========== 字典数据 ==========
  239. #set($fieldDict=[])
  240. #foreach($field in $queryList)
  241. #if($field.fieldDict)
  242. #set($void=$fieldDict.add($field.fieldDict))
  243. #end
  244. #end
  245. #foreach($field in $gridList)
  246. #if($field.fieldDict)
  247. #set($void=$fieldDict.add($field.fieldDict))
  248. #end
  249. #end
  250. #if($fieldDict)
  251. // 加载字典数据
  252. const { $dict.format($fieldDict) } = useDict($dict.quotation($fieldDict));
  253. #end
  254. // ========== 组件引用 ==========
  255. const formDialogRef = ref(); // 表单弹窗引用
  256. const excelUploadRef = ref(); // Excel上传弹窗引用
  257. const queryRef = ref(); // 查询表单引用
  258. // ========== 响应式数据 ==========
  259. const showSearch = ref(true); // 是否显示搜索区域
  260. const selectObjs = ref([]) as any; // 表格多选数据
  261. const multiple = ref(true); // 是否多选
  262. // ========== 表格状态 ==========
  263. const state: BasicTableProps = reactive<BasicTableProps>({
  264. queryForm: {}, // 查询参数
  265. pageList: fetchList // 分页查询方法
  266. });
  267. // ========== Hook引用 ==========
  268. // 表格相关Hook
  269. const {
  270. getDataList,
  271. currentChangeHandle,
  272. sizeChangeHandle,
  273. sortChangeHandle,
  274. downBlobFile,
  275. tableStyle
  276. } = useTable(state);
  277. // ========== 方法定义 ==========
  278. /**
  279. * 重置查询条件
  280. */
  281. const resetQuery = () => {
  282. // 清空搜索条件
  283. queryRef.value?.resetFields();
  284. // 清空多选
  285. selectObjs.value = [];
  286. // 重新查询
  287. getDataList();
  288. };
  289. /**
  290. * 导出Excel文件
  291. */
  292. const exportExcel = () => {
  293. downBlobFile(
  294. '/${moduleName}/${functionName}/export',
  295. Object.assign(state.queryForm, { ids: selectObjs }),
  296. '${functionName}.xlsx'
  297. );
  298. };
  299. /**
  300. * 表格多选事件处理
  301. * @param objs 选中的数据行
  302. */
  303. const selectionChangHandle = (objs: { $pk.attrName: string }[]) => {
  304. selectObjs.value = objs.map(({ $pk.attrName }) => $pk.attrName);
  305. multiple.value = !objs.length;
  306. };
  307. /**
  308. * 删除数据处理
  309. * @param ids 要删除的数据ID数组
  310. */
  311. const handleDelete = async (ids: string[]) => {
  312. try {
  313. await useMessageBox().confirm('此操作将永久删除');
  314. } catch {
  315. return;
  316. }
  317. try {
  318. await delObjs(ids);
  319. getDataList();
  320. useMessage().success('删除成功');
  321. } catch (err: any) {
  322. useMessage().error(err.msg);
  323. }
  324. };
  325. </script>