index.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. <template>
  2. <div class="table-box">
  3. <ProTable ref="proTable" :columns="columns" :request-api="getTableList" :data-callback="dataCallback">
  4. <template #tableHeader>
  5. <el-button type="primary" :icon="CirclePlus" :disabled="!isAdmin" @click="handleCreate"> 新增律所 </el-button>
  6. <el-button type="primary" :icon="Upload" :disabled="!isAdmin" @click="handleImport"> 导入 </el-button>
  7. <!-- <el-button
  8. type="primary"
  9. :icon="Download"
  10. :loading="exportLoading"
  11. :disabled="!hasExportableData || !isAdmin"
  12. @click="handleExport"
  13. >
  14. 导出
  15. </el-button> -->
  16. <el-button
  17. type="primary"
  18. :icon="Download"
  19. :loading="exportAllLoading"
  20. :disabled="!hasExportableData || !isAdmin"
  21. @click="handleExportAll"
  22. >
  23. 全部导出
  24. </el-button>
  25. </template>
  26. <template #paymentAccount="scope">
  27. <div class="payment-tags">
  28. <el-tag v-for="card in splitPayment(scope.row.paymentAccount)" :key="card">
  29. {{ formatCard(card) }}
  30. </el-tag>
  31. </div>
  32. </template>
  33. <template #operation="scope">
  34. <el-button type="primary" link :icon="EditPen" :disabled="!isAdmin" @click="handleEdit(scope.row)"> 编辑 </el-button>
  35. <el-button type="danger" link :icon="Delete" :disabled="!isAdmin" @click="handleDelete(scope.row)"> 删除 </el-button>
  36. </template>
  37. </ProTable>
  38. <LawFirmDialog ref="lawFirmDialogRef" @success="refreshTable" />
  39. <ImportDialog
  40. v-model="importVisible"
  41. title="导入律所"
  42. :download-handler="handleDownloadTemplate"
  43. :import-handler="handleImportSubmit"
  44. @success="handleImportSuccess"
  45. />
  46. </div>
  47. </template>
  48. <script setup lang="ts">
  49. import { ref, reactive, onActivated, computed } from "vue";
  50. import { ElMessage, ElMessageBox } from "element-plus";
  51. import ProTable from "@/components/ProTable/index.vue";
  52. import type { ProTableInstance, ColumnProps } from "@/components/ProTable/interface";
  53. import {
  54. getLawFirmPage,
  55. addLawFirm,
  56. deleteLawFirm,
  57. editLawFirm,
  58. importData,
  59. downloadLawFirmTemplate,
  60. exportLawFirm
  61. } from "@/api/modules/lawyer";
  62. import { useDownload } from "@/hooks/useDownload";
  63. import { CirclePlus, Delete, EditPen, Upload, Download } from "@element-plus/icons-vue";
  64. import LawFirmDialog from "./components/LawFirmDialog.vue";
  65. import ImportDialog from "./components/ImportDialog.vue";
  66. import { useUserStore } from "@/stores/modules/user";
  67. const userStore = useUserStore();
  68. const isAdmin = computed(() => userStore.userInfo?.name === "admin");
  69. const loginFirmId = computed(() => userStore.userInfo?.roleId || "");
  70. const ensureAdmin = () => {
  71. if (isAdmin.value) return true;
  72. ElMessage.warning("仅管理员可使用该功能");
  73. return false;
  74. };
  75. const proTable = ref<ProTableInstance>();
  76. const lawFirmDialogRef = ref<InstanceType<typeof LawFirmDialog>>();
  77. const importVisible = ref(false);
  78. const exportLoading = ref(false);
  79. const exportAllLoading = ref(false);
  80. const tableTotal = ref(0);
  81. const hasExportableData = computed(() => tableTotal.value > 0);
  82. const columns = reactive<ColumnProps<any>[]>([
  83. { label: "序号", type: "index", width: 60, align: "center" },
  84. { label: "律所名称", prop: "firmName", search: { el: "input", props: { placeholder: "请输入律所名称" } } },
  85. {
  86. label: "负责人姓名",
  87. prop: "directorName",
  88. width: 160,
  89. search: { el: "input", props: { placeholder: "请输入负责人姓名" } }
  90. },
  91. { label: "位置", prop: "address" },
  92. { label: "统一社会信用代码", prop: "creditCode", width: 220 },
  93. {
  94. label: "电话号码",
  95. prop: "phone",
  96. width: 160,
  97. align: "center"
  98. },
  99. { label: "收款账号", prop: "paymentAccount", align: "center" },
  100. { label: "操作", prop: "operation", width: 200, fixed: "right" }
  101. ]);
  102. const getTableList = async (params: any) => {
  103. const newParams: Record<string, any> = { ...params, page: params.pageNum, size: params.pageSize };
  104. delete newParams.pageNum;
  105. delete newParams.pageSize;
  106. // 如果登录的不是管理员,则只查询当前登录的律所
  107. if (!isAdmin.value && loginFirmId.value) {
  108. newParams.firmId = loginFirmId.value;
  109. }
  110. return getLawFirmPage(newParams);
  111. };
  112. const dataCallback = (data: any) => {
  113. const total = Number(data.total) || 0;
  114. tableTotal.value = total;
  115. return {
  116. list: data.records,
  117. total
  118. };
  119. };
  120. const refreshTable = () => {
  121. proTable.value?.getTableList();
  122. };
  123. const splitPayment = (value: string) => {
  124. if (!value) return [];
  125. return value
  126. .split(",")
  127. .map(card => card.trim())
  128. .filter(Boolean);
  129. };
  130. const formatCard = (card: string) => {
  131. return card
  132. .replace(/\s+/g, "")
  133. .replace(/(.{4})/g, "$1 ")
  134. .trim();
  135. };
  136. const handleCreate = () => {
  137. if (!ensureAdmin()) return;
  138. lawFirmDialogRef.value?.open({
  139. title: "新增律所",
  140. onSubmit: async payload => {
  141. // 防止的修改的参数混入
  142. let params = {
  143. creditCode: payload.creditCode,
  144. directorName: payload.directorName,
  145. firmName: payload.firmName,
  146. phone: payload.phone,
  147. paymentList: [
  148. {
  149. address: payload.address,
  150. paymentAccount: payload.paymentAccount
  151. }
  152. ]
  153. };
  154. await addLawFirm(params);
  155. ElMessage.success("新增成功");
  156. }
  157. });
  158. };
  159. const handleImport = () => {
  160. if (!ensureAdmin()) return;
  161. importVisible.value = true;
  162. };
  163. const handleEdit = (row: any) => {
  164. if (!ensureAdmin()) return;
  165. lawFirmDialogRef.value?.open({
  166. title: "编辑律所",
  167. row,
  168. onSubmit: async payload => {
  169. let params = {
  170. id: row.firmId,
  171. creditCode: payload.creditCode,
  172. directorName: payload.directorName,
  173. firmName: payload.firmName,
  174. phone: payload.phone,
  175. paymentList: [
  176. {
  177. id: row.id,
  178. address: payload.address,
  179. paymentAccount: payload.paymentAccount
  180. }
  181. ]
  182. };
  183. await editLawFirm(params);
  184. ElMessage.success("编辑成功");
  185. }
  186. });
  187. };
  188. const handleDelete = (row: any) => {
  189. if (!ensureAdmin()) return;
  190. ElMessageBox.confirm(`确定删除律所【${row.firmName}】吗?`, "提示", {
  191. type: "warning"
  192. })
  193. .then(async () => {
  194. await deleteLawFirm({ id: row.id });
  195. ElMessage.success("删除成功");
  196. refreshTable();
  197. })
  198. .catch(() => {});
  199. };
  200. const handleDownloadTemplate = () => useDownload(downloadLawFirmTemplate, "律所导入模板");
  201. const handleImportSubmit = (formData: FormData) => importData(formData);
  202. const handleImportSuccess = () => {
  203. refreshTable();
  204. };
  205. const buildExportParams = (override: Record<string, any> = {}) => {
  206. const searchParam = proTable.value?.searchParam ? { ...proTable.value.searchParam } : {};
  207. const pageable = proTable.value?.pageable
  208. ? { page: proTable.value.pageable.pageNum, size: proTable.value.pageable.pageSize }
  209. : { page: 1, size: 10 };
  210. const params: Record<string, any> = {
  211. ...searchParam,
  212. ...pageable,
  213. ...override
  214. };
  215. if (!isAdmin.value && loginFirmId.value) {
  216. params.firmId = loginFirmId.value;
  217. }
  218. return params;
  219. };
  220. const handleExport = async () => {
  221. if (!ensureAdmin()) {
  222. return;
  223. }
  224. if (!hasExportableData.value) {
  225. ElMessage.warning("暂无可导出的数据");
  226. return;
  227. }
  228. exportLoading.value = true;
  229. try {
  230. const params = buildExportParams();
  231. await useDownload(exportLawFirm, "律所列表", params);
  232. } finally {
  233. exportLoading.value = false;
  234. }
  235. };
  236. const handleExportAll = async () => {
  237. if (!ensureAdmin()) {
  238. return;
  239. }
  240. if (!hasExportableData.value) {
  241. ElMessage.warning("暂无可导出的数据");
  242. return;
  243. }
  244. exportAllLoading.value = true;
  245. try {
  246. const params = buildExportParams({
  247. page: 1,
  248. size: Math.max(tableTotal.value, 1)
  249. });
  250. await useDownload(exportLawFirm, "律所列表-全部", params);
  251. } finally {
  252. exportAllLoading.value = false;
  253. }
  254. };
  255. onActivated(() => {
  256. refreshTable();
  257. });
  258. </script>
  259. <style scoped lang="scss">
  260. .payment-tags {
  261. display: flex;
  262. flex-wrap: wrap;
  263. gap: 16px;
  264. justify-content: center;
  265. width: 100%;
  266. }
  267. </style>