dictionary.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <VerticalFlexLayout>
  3. <template #static>
  4. <Breadcrumb />
  5. </template>
  6. <div class="dictionary-container">
  7. <el-card shadow="never">
  8. <div class="table-operations">
  9. <el-button type="primary" @click="handleAddDialogShow" :icon="Plus">新增字典项</el-button>
  10. </div>
  11. <el-table v-loading="loading" :data="dataSource" style="width: 100%; margin-top: 16px">
  12. <el-table-column prop="dictName" label="字典名称" />
  13. <el-table-column prop="dictCode" label="字典编码" />
  14. <el-table-column prop="description" label="字典描述" show-overflow-tooltip />
  15. <el-table-column prop="dictType" label="分类" width="180">
  16. <template #default="{ row }">
  17. {{ typeLabelMap[row.dictType] || '' }}
  18. </template>
  19. </el-table-column>
  20. <el-table-column prop="status" label="状态" width="180">
  21. <template #default="{ row }">
  22. {{ statusLabelMap[row.status] || '' }}
  23. </template>
  24. </el-table-column>
  25. <el-table-column label="操作" width="200" fixed="right">
  26. <template #default="{ row }">
  27. <el-button type="primary" link @click="handleEdit(row)">编辑</el-button>
  28. <el-button type="primary" link @click="handleDelete(row)">删除</el-button>
  29. </template>
  30. </el-table-column>
  31. </el-table>
  32. <div class="paginationPosition">
  33. <el-pagination
  34. v-model:current-page="currentPage"
  35. v-model:page-size="pageSize"
  36. :page-sizes="[10, 20, 50, 100]"
  37. :total="totalRow"
  38. background
  39. layout="total, prev, pager, next, sizes, jumper"
  40. @size-change="handleSizeChange"
  41. @current-change="handleCurrentChange"
  42. />
  43. </div>
  44. </el-card>
  45. <AddDict
  46. v-if="dialogVisible"
  47. ref="addDictRef"
  48. @close="closeAddDialog"
  49. @submit="handleSubmit"
  50. :dictCode="currentDictCode"
  51. />
  52. </div>
  53. </VerticalFlexLayout>
  54. </template>
  55. <script lang="ts" setup>
  56. import { ref, onMounted, computed } from 'vue';
  57. import { ElMessage, ElMessageBox } from 'element-plus';
  58. import { Plus } from '@element-plus/icons-vue';
  59. import AddDict from './components/AddDict.vue';
  60. import { createDictApi, SaveDictParams, updateDict, deleteDict } from '@/api/dict';
  61. import { useDataSource } from './useDataSource';
  62. import { dictionaryStatusOptions, dictionaryTypeOptions } from './constants';
  63. import Breadcrumb from '@/components/Breadcrumb.vue';
  64. import VerticalFlexLayout from '@/components/VerticalFlexLayout.vue';
  65. // 表格数据
  66. const loading = ref(false);
  67. const { dataSource, getDataSource, pageSize, currentPage, totalRow } = useDataSource();
  68. onMounted(() => {
  69. getDataSource();
  70. });
  71. // 分页相关
  72. function handleSizeChange(val: number) {
  73. pageSize.value = val;
  74. getDataSource();
  75. }
  76. function handleCurrentChange(val: number) {
  77. currentPage.value = val;
  78. getDataSource();
  79. }
  80. // 表单相关
  81. const dialogVisible = ref(false);
  82. const dialogTitle = ref('新增字典');
  83. const addDictRef = ref<InstanceType<typeof AddDict>>();
  84. const currentDictCode = ref('');
  85. // 新增字典
  86. function handleAddDialogShow() {
  87. dialogVisible.value = true;
  88. currentDictCode.value = '';
  89. }
  90. const closeAddDialog = () => {
  91. dialogVisible.value = false;
  92. if (addDictRef.value) {
  93. addDictRef.value.resetForm();
  94. }
  95. };
  96. // 编辑字典
  97. function handleEdit(row: any) {
  98. dialogTitle.value = '编辑字典';
  99. dialogVisible.value = true;
  100. currentDictCode.value = row.dictCode;
  101. }
  102. // 删除字典
  103. async function handleDelete(row: any) {
  104. try {
  105. await ElMessageBox.confirm('确定要删除这条字典记录吗?', '提示', {
  106. type: 'warning',
  107. });
  108. await deleteDictionary(row.dictId);
  109. } catch {
  110. // 用户取消删除
  111. }
  112. }
  113. // 提交表单
  114. async function handleSubmit(formData: SaveDictParams) {
  115. if (!addDictRef.value) return;
  116. if (formData.dictId) {
  117. await updateDictionary(formData);
  118. } else {
  119. await createDictionary(formData);
  120. }
  121. dialogVisible.value = false;
  122. getDataSource();
  123. }
  124. const createDictionary = (formData: SaveDictParams) => {
  125. createDictApi(formData).then(() => {
  126. ElMessage.success('保存成功');
  127. });
  128. };
  129. const updateDictionary = (formData: SaveDictParams) => {
  130. updateDict(formData).then(() => {
  131. ElMessage.success('编辑成功');
  132. });
  133. };
  134. const deleteDictionary = (id: number) => {
  135. deleteDict(id).then(() => {
  136. ElMessage.success('删除成功');
  137. getDataSource();
  138. });
  139. };
  140. const typeLabelMap = computed(() =>
  141. Object.fromEntries(dictionaryTypeOptions.map((item) => [item.value, item.label])),
  142. );
  143. const statusLabelMap = computed(() =>
  144. Object.fromEntries(dictionaryStatusOptions.map((item) => [item.value, item.label])),
  145. );
  146. </script>
  147. <style lang="scss" scoped>
  148. .dictionary-container {
  149. .search-form {
  150. margin-bottom: 16px;
  151. }
  152. .table-operations {
  153. margin-bottom: 16px;
  154. }
  155. }
  156. </style>