index.vue 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343
  1. <template>
  2. <div class="system-dict-container layout-padding">
  3. <div class="layout-padding-auto layout-padding-view pd20">
  4. <el-row :gutter="20" class="h100">
  5. <!-- 左侧组织树 -->
  6. <el-col :xs="6" :sm="6" :md="6" :lg="4" :xl="4" class="orgTree">
  7. <el-scrollbar height="100%" class="pr10">
  8. <template v-if="state.dicTypeList.length">
  9. <el-tree
  10. v-loading="state.loading"
  11. :data="state.dicTypeList"
  12. highlight-current
  13. :expand-on-click-node="false"
  14. node-key="id"
  15. :props="{ children: 'children', label: 'dicTypeName' }"
  16. @node-click="handleNodeClick"
  17. :current-node-key="state.dicTypeList[0].id"
  18. ref="treRef"
  19. style="min-width: 100%; display: inline-block"
  20. >
  21. </el-tree>
  22. </template>
  23. <template v-else>
  24. <Empty description="暂无字典类型" />
  25. </template>
  26. </el-scrollbar>
  27. </el-col>
  28. <!-- 右侧表格 -->
  29. <el-col :xs="18" :sm="18" :md="18" :lg="20" :xl="20" class="rightContent">
  30. <el-scrollbar class="pr10">
  31. <div class="flex-column">
  32. <div class="flex-between mb10">
  33. <el-form :model="state.queryParams" ref="ruleFormRef" :inline="true" @submit.native.prevent>
  34. <el-form-item label="关键字" prop="keyword" class="mb0">
  35. <el-input v-model="state.queryParams.keyword" placeholder="字典值名称/字典值" clearable @keyup.enter="handleQuery" />
  36. </el-form-item>
  37. <el-form-item class="mb0">
  38. <el-button type="primary" @click="handleQuery" :loading="state.tableLoading" v-waves>
  39. <SvgIcon name="ele-Search" class="mr5" />查询
  40. </el-button>
  41. <el-button @click="resetQuery(ruleFormRef)" v-waves class="default-button" :loading="state.tableLoading">
  42. <SvgIcon name="ele-Refresh" class="mr5" />重置
  43. </el-button>
  44. </el-form-item>
  45. </el-form>
  46. <div>
  47. <el-button type="primary" @click="expand"
  48. ><SvgIcon
  49. name="ele-ArrowDownBold"
  50. style="transition: transform var(--el-transition-duration)"
  51. :style="state.isExpand ? 'transform: none' : 'transform: rotateZ(180deg)'"
  52. class="mr5"
  53. />
  54. {{ state.isExpand ? '收起' : '展开' }}</el-button
  55. >
  56. <el-button type="primary" @click="onOpenAddUser" v-auth="'system:dict:add'">
  57. <SvgIcon name="ele-Plus" class="mr5" />新增
  58. </el-button>
  59. <!-- <el-button type="primary" @click="onRowDel" v-waves v-auth="'100104'">
  60. <SvgIcon name="ele-Delete" class="mr5" />注销
  61. </el-button> -->
  62. <!-- <el-button type="primary" v-waves @click="onExportTable">
  63. <SvgIcon name="iconfont icon-daochu" class="mr5" />导出
  64. </el-button> -->
  65. </div>
  66. </div>
  67. <!-- 表格 -->
  68. <el-auto-resizer class="table" v-loading="state.tableLoading">
  69. <template #default="{ height, width }">
  70. <el-table-v2
  71. v-model:expanded-row-keys="state.expandedRowKeys"
  72. :columns="state.columns"
  73. :data="state.tableData"
  74. expand-column-key="dicDataName"
  75. fixed
  76. :width="width"
  77. :height="height"
  78. >
  79. <template #empty>
  80. <Empty />
  81. </template>
  82. </el-table-v2>
  83. </template>
  84. </el-auto-resizer>
  85. </div>
  86. </el-scrollbar>
  87. </el-col>
  88. </el-row>
  89. </div>
  90. <dict-add ref="dictAddRef" @updateList="handleQuery" />
  91. <dict-edit ref="dickEditRef" @updateList="handleQuery" />
  92. </div>
  93. </template>
  94. <script lang="ts" setup name="systemDict">
  95. import { defineAsyncComponent, ref, reactive, onMounted, h, watch } from 'vue';
  96. import { ElButton } from 'element-plus';
  97. import type { FormInstance } from 'element-plus';
  98. import { ElMessage } from 'element-plus';
  99. import { formatDate } from '/@/utils/formatTime';
  100. import { auth } from '/@/utils/authFunction';
  101. import other from '/@/utils/other';
  102. import { throttle } from '/@/utils/tools';
  103. import { dicTypeList, getDataByTypeId } from '/@/api/system/dict';
  104. // 引入组件
  105. const DictAdd = defineAsyncComponent(() => import('/@/views/system/config/dict/component/Dict-add.vue'));
  106. const DictEdit = defineAsyncComponent(() => import('/@/views/system/config/dict/component/Dict-edit.vue'));
  107. // 定义变量内容
  108. const state = reactive<any>({
  109. queryParams: {
  110. keyword: '',
  111. typeid: '',
  112. loading: false,
  113. },
  114. tableData: [],
  115. staticArr: [],
  116. total: 0,
  117. loading: false,
  118. tableLoading: false,
  119. dicTypeList: [],
  120. options: [],
  121. columns: [
  122. {
  123. key: 'dicDataName',
  124. dataKey: 'dicDataName',
  125. title: '字典名称',
  126. width: 600,
  127. },
  128. {
  129. key: 'dicDataValue',
  130. dataKey: 'dicDataValue',
  131. title: '字典值',
  132. width: 150,
  133. },
  134. {
  135. key: 'dicTypeCode',
  136. dataKey: 'dicTypeCode',
  137. title: '字典code',
  138. width: 170,
  139. },
  140. {
  141. key: 'creationTime',
  142. dataKey: 'creationTime',
  143. title: '更新时间',
  144. width: 170,
  145. cellRenderer: (data: any) => h('span', {}, { default: () => formatDate(new Date(data.rowData.creationTime), 'YYYY-mm-dd HH-MM') }),
  146. },
  147. {
  148. key: 'handle',
  149. title: '操作',
  150. width: 70,
  151. fixed: 'right',
  152. align: 'center',
  153. cellRenderer: (data: any) => {
  154. if (auth('system:dict:query')) {
  155. // 权限判断
  156. return h(
  157. ElButton,
  158. {
  159. onClick: () => onOpenEditUser(data),
  160. type: 'primary',
  161. link: true,
  162. title: '修改字典信息',
  163. },
  164. { default: () => '修改' }
  165. );
  166. }
  167. },
  168. },
  169. ],
  170. expandedRowKeys: [],
  171. isExpand: false,
  172. });
  173. const dictAddRef = ref<RefType>(); //新增字典
  174. const dickEditRef = ref<RefType>(); //修改字典
  175. const treRef = ref<RefType>();
  176. const ruleFormRef = ref<RefType>();
  177. /** 搜索按钮操作 节流操作 */
  178. const handleQuery = throttle(() => {
  179. if (state.queryParams.keyword) {
  180. state.tableLoading = true;
  181. state.expandedRowKeys = [];
  182. emptyArr = [];
  183. state.tableData = formatTable(other.deepClone(state.staticArr), state.queryParams.keyword);
  184. state.expandedRowKeys = getExpand(state.tableData);
  185. state.tableLoading = false;
  186. } else {
  187. getList();
  188. }
  189. }, 1000);
  190. const expand = () => {
  191. state.isExpand = !state.isExpand;
  192. };
  193. watch(
  194. () => state.isExpand,
  195. (old: Boolean) => {
  196. if (old) getAllIds(state.tableData);
  197. else state.expandedRowKeys = [];
  198. }
  199. );
  200. const getAllIds = (arr: any) => {
  201. if (!arr) return [];
  202. arr.forEach((v: any) => {
  203. if (v.children?.length) {
  204. getAllIds(v.children);
  205. state.expandedRowKeys.push(v.id);
  206. }
  207. });
  208. };
  209. // 获取字典类型列表
  210. const getDictTypeList = () => {
  211. if (!auth('system:dict:type')) ElMessage.error('抱歉,您没有权限获取字典类型!');
  212. else {
  213. state.loading = true;
  214. dicTypeList()
  215. .then((res: any) => {
  216. state.dicTypeList = res?.result ?? [];
  217. state.queryParams.typeid = res?.result[0].id ?? '';
  218. getList();
  219. state.loading = false;
  220. })
  221. .catch(() => {
  222. state.loading = false;
  223. });
  224. }
  225. };
  226. /* 获取字典列表 */
  227. const getList = () => {
  228. if (!auth('system:dict:query')) ElMessage.error('抱歉,您没有权限获取字典列表!');
  229. else {
  230. state.tableLoading = true;
  231. getDataByTypeId(state.queryParams)
  232. .then((response: any) => {
  233. state.tableData = response?.result ?? [];
  234. state.staticArr = response?.result ?? [];
  235. state.tableLoading = false;
  236. })
  237. .catch(() => {
  238. state.loading = false;
  239. });
  240. }
  241. };
  242. // 搜索
  243. const formatTable = (list: any[], keyword: string) => {
  244. if (!list.length || !Array.isArray(list)) return [];
  245. let emptyArr: any[] = [];
  246. list.map((item) => {
  247. if (item.dicDataName.includes(keyword) || item.dicDataValue.includes(keyword)) {
  248. if (item.children && Array.isArray(item.children) && item.children.length > 0) {
  249. item.children = formatTable(item.children, keyword);
  250. }
  251. emptyArr.push(item);
  252. } else if (item.children && Array.isArray(item.children) && item.children.length > 0) {
  253. item.children = formatTable(item.children, keyword);
  254. if (item.children.length) {
  255. emptyArr.push(item);
  256. }
  257. }
  258. });
  259. return emptyArr;
  260. };
  261. let emptyArr: any[] = [];
  262. const getExpand = (list: any[]) => {
  263. if (!list.length || !Array.isArray(list)) return [];
  264. list.map((item) => {
  265. if (item.children && Array.isArray(item.children) && item.children.length > 0) {
  266. getExpand(item.children);
  267. }
  268. emptyArr.push(item.id);
  269. });
  270. return emptyArr;
  271. };
  272. // 点击节点
  273. const handleNodeClick = (data: any) => {
  274. state.queryParams.typeid = data.id;
  275. state.isExpand = false;
  276. state.expandedRowKeys = [];
  277. resetQuery(ruleFormRef.value);
  278. };
  279. // 打开新增字典弹窗
  280. const onOpenAddUser = () => {
  281. dictAddRef.value.openDialog(state.queryParams.typeid);
  282. };
  283. // 打开修改字典弹窗
  284. const onOpenEditUser = (row: any) => {
  285. dickEditRef.value.openDialog(row.rowData, state.tableData);
  286. };
  287. /** 重置按钮操作 */
  288. const resetQuery = throttle((formEl: FormInstance | undefined) => {
  289. if (!formEl) return;
  290. formEl.resetFields();
  291. getList();
  292. state.expandedRowKeys = [];
  293. emptyArr = [];
  294. }, 500);
  295. // 删除字典
  296. // const onRowDel = (row: any) => {
  297. // ElMessageBox.confirm(`此操作将永久删除账户名称:“${row.name}”,是否继续?`, '提示', {
  298. // confirmButtonText: '确认',
  299. // cancelButtonText: '取消',
  300. // draggable: true,
  301. // cancelButtonClass: 'default-button',
  302. // type: 'warning'
  303. // }).then(() => {
  304. // delUser(row.id).then(() => {
  305. // ElMessage.success('删除成功');
  306. // handleQuery();
  307. // });
  308. // }).catch(() => { });
  309. // };
  310. // 导出表格
  311. // const onExportTable = () => {};
  312. onMounted(() => {
  313. getDictTypeList();
  314. });
  315. </script>
  316. <style lang="scss" scoped>
  317. .system-dict-container {
  318. .orgTree {
  319. border-right: 1px solid var(--el-border-color);
  320. height: 100%;
  321. }
  322. .rightContent {
  323. height: 100%;
  324. .flex-column {
  325. display: flex;
  326. flex-direction: column;
  327. height: 100%;
  328. .table {
  329. flex: 1;
  330. }
  331. }
  332. }
  333. :deep(.el-tree-node__content) {
  334. height: 40px;
  335. }
  336. }
  337. </style>