From 302e8457c8d34a35d7eabbd474d98ebc16120ed2 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期三, 12 八月 2026 17:23:07 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/fix/hsy/20260812' into dev_pro2.0
---
src/views/system/post/data.ts | 24 ++++
src/views/system/dept/modules/import-form.vue | 104 ++++++++++++++++++++
src/views/system/dept/data.ts | 24 ++++
src/views/system/dept/index.vue | 19 +++
src/views/system/post/index.vue | 19 +++
src/api/system/dept/index.ts | 13 ++
src/views/system/post/modules/import-form.vue | 82 ++++++++++++++++
src/api/system/post/index.ts | 13 ++
8 files changed, 298 insertions(+), 0 deletions(-)
diff --git a/src/api/system/dept/index.ts b/src/api/system/dept/index.ts
index d6403d7..7d20bf2 100644
--- a/src/api/system/dept/index.ts
+++ b/src/api/system/dept/index.ts
@@ -50,3 +50,16 @@
export async function deleteDeptList(ids: number[]) {
return requestClient.delete(`/system/dept/delete-list?ids=${ids.join(',')}`);
}
+
+/** 涓嬭浇閮ㄩ棬瀵煎叆妯℃澘 */
+export function importDeptTemplate() {
+ return requestClient.download('/system/dept/get-import-template');
+}
+
+/** 瀵煎叆閮ㄩ棬 */
+export function importDept(file: File, updateSupport: boolean) {
+ return requestClient.upload('/system/dept/import', {
+ file,
+ updateSupport,
+ });
+}
diff --git a/src/api/system/post/index.ts b/src/api/system/post/index.ts
index 8b32ad2..3032a56 100644
--- a/src/api/system/post/index.ts
+++ b/src/api/system/post/index.ts
@@ -61,3 +61,16 @@
params,
});
}
+
+/** 涓嬭浇宀椾綅瀵煎叆妯℃澘 */
+export function importPostTemplate() {
+ return requestClient.download('/system/post/get-import-template');
+}
+
+/** 瀵煎叆宀椾綅 */
+export function importPost(file: File, updateSupport: boolean) {
+ return requestClient.upload('/system/post/import', {
+ file,
+ updateSupport,
+ });
+}
diff --git a/src/views/system/dept/data.ts b/src/views/system/dept/data.ts
index d111330..9fe39e2 100644
--- a/src/views/system/dept/data.ts
+++ b/src/views/system/dept/data.ts
@@ -114,6 +114,30 @@
];
}
+/** 閮ㄩ棬瀵煎叆鐨勮〃鍗� */
+export function useImportFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'file',
+ label: '閮ㄩ棬鏁版嵁',
+ component: 'Upload',
+ rules: 'required',
+ help: '浠呭厑璁稿鍏� xls銆亁lsx 鏍煎紡鏂囦欢',
+ },
+ {
+ fieldName: 'updateSupport',
+ label: '鏄惁瑕嗙洊',
+ component: 'Switch',
+ componentProps: {
+ checkedChildren: '鏄�',
+ unCheckedChildren: '鍚�',
+ },
+ rules: z.boolean().default(false),
+ help: '鏄惁鏇存柊宸茬粡瀛樺湪鐨勯儴闂ㄦ暟鎹�',
+ },
+ ];
+}
+
/** 鍒楄〃鐨勫瓧娈� */
export function useGridColumns(): VxeTableGridOptions<SystemDeptApi.Dept>['columns'] {
return [
diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue
index 64f998e..1646f7b 100644
--- a/src/views/system/dept/index.vue
+++ b/src/views/system/dept/index.vue
@@ -15,9 +15,15 @@
import { useGridColumns } from './data';
import Form from './modules/form.vue';
+import ImportForm from './modules/import-form.vue';
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
+ destroyOnClose: true,
+});
+
+const [ImportModal, importModalApi] = useVbenModal({
+ connectedComponent: ImportForm,
destroyOnClose: true,
});
@@ -36,6 +42,11 @@
/** 鍒涘缓閮ㄩ棬 */
function handleCreate() {
formModalApi.setData(null).open();
+}
+
+/** 瀵煎叆閮ㄩ棬 */
+function handleImport() {
+ importModalApi.open();
}
/** 娣诲姞涓嬬骇閮ㄩ棬 */
@@ -129,6 +140,7 @@
<template>
<Page auto-content-height>
<FormModal @success="handleRefresh" />
+ <ImportModal @success="handleRefresh" />
<Grid table-title="閮ㄩ棬鍒楄〃">
<template #toolbar-tools>
<TableAction
@@ -141,6 +153,13 @@
onClick: handleCreate,
},
{
+ label: $t('ui.actionTitle.import', ['閮ㄩ棬']),
+ type: 'primary',
+ icon: ACTION_ICON.UPLOAD,
+ auth: ['system:dept:import'],
+ onClick: handleImport,
+ },
+ {
label: isExpanded ? '鏀剁缉' : '灞曞紑',
type: 'primary',
onClick: handleExpand,
diff --git a/src/views/system/dept/modules/import-form.vue b/src/views/system/dept/modules/import-form.vue
new file mode 100644
index 0000000..08eee2b
--- /dev/null
+++ b/src/views/system/dept/modules/import-form.vue
@@ -0,0 +1,104 @@
+<script lang="ts" setup>
+import type { FileType } from 'ant-design-vue/es/upload/interface';
+
+import { h } from 'vue';
+
+import { useVbenModal } from '@vben/common-ui';
+import { downloadFileFromBlobPart } from '@vben/utils';
+
+import { Button, message, notification, Upload } from 'ant-design-vue';
+
+import { useVbenForm } from '#/adapter/form';
+import { importDept, importDeptTemplate } from '#/api/system/dept';
+import { $t } from '#/locales';
+
+import { useImportFormSchema } from '../data';
+
+const emit = defineEmits(['success']);
+
+const [Form, formApi] = useVbenForm({
+ commonConfig: {
+ formItemClass: 'col-span-2',
+ labelWidth: 120,
+ },
+ layout: 'horizontal',
+ schema: useImportFormSchema(),
+ showDefaultActions: false,
+});
+
+const [Modal, modalApi] = useVbenModal({
+ async onConfirm() {
+ const { valid } = await formApi.validate();
+ if (!valid) {
+ return;
+ }
+ modalApi.lock();
+ // 鎻愪氦琛ㄥ崟
+ const data = await formApi.getValues();
+ try {
+ const response = (await importDept(data.file, data.updateSupport)) as any;
+ // 鍏抽棴骞舵彁绀�
+ await modalApi.close();
+ emit('success');
+
+ const resultData = response?.data || response || {};
+ const failureNames = resultData.failureDeptNames || {};
+
+ if (Object.keys(failureNames).length > 0) {
+ const errorNodes = Object.entries(failureNames).map(([name, reason]) => {
+ return h('div', `${name}: ${reason}`);
+ });
+
+ notification.warning({
+ message: '瀵煎叆瀹屾垚锛岄儴鍒嗛儴闂ㄥ鍏ュけ璐�',
+ description: () => h('div', errorNodes),
+ duration: null,
+ });
+ } else {
+ message.success($t('ui.actionMessage.operationSuccess'));
+ }
+ } finally {
+ modalApi.unlock();
+ }
+ },
+});
+
+/** 涓婁紶鍓� */
+function beforeUpload(file: FileType) {
+ formApi.setFieldValue('file', file);
+ return false;
+}
+
+/** 涓嬭浇妯$増 */
+async function handleDownload() {
+ const data = await importDeptTemplate();
+ downloadFileFromBlobPart({ fileName: '閮ㄩ棬瀵煎叆妯℃澘.xls', source: data });
+}
+</script>
+
+<template>
+ <Modal title="瀵煎叆閮ㄩ棬" class="w-1/3">
+ <Form class="mx-4">
+ <template #file>
+ <div class="w-full">
+ <Upload
+ :max-count="1"
+ accept=".xls,.xlsx"
+ :before-upload="beforeUpload"
+ >
+ <Button type="primary"> 閫夋嫨 Excel 鏂囦欢 </Button>
+ </Upload>
+ </div>
+ </template>
+ </Form>
+ <div class="mx-4 mt-2 mb-4 text-gray-500 text-xs">
+ 鎻愮ず锛氭ā鏉块噷鐨勨�滀笂绾ч儴闂ㄢ�濊濉啓鍏ㄨ矾寰勶紙濡�:鎬诲叕鍙�/鍖椾含鍒嗗叕鍙革級
+ <div>涓婄骇閮ㄩ棬绌虹潃鍗充负椤剁骇閮ㄩ棬銆�</div>
+ </div>
+ <template #prepend-footer>
+ <div class="flex flex-auto items-center">
+ <Button @click="handleDownload"> 涓嬭浇瀵煎叆妯℃澘 </Button>
+ </div>
+ </template>
+ </Modal>
+</template>
diff --git a/src/views/system/post/data.ts b/src/views/system/post/data.ts
index 3c66ebc..ca71395 100644
--- a/src/views/system/post/data.ts
+++ b/src/views/system/post/data.ts
@@ -68,6 +68,30 @@
];
}
+/** 宀椾綅瀵煎叆鐨勮〃鍗� */
+export function useImportFormSchema(): VbenFormSchema[] {
+ return [
+ {
+ fieldName: 'file',
+ label: '宀椾綅鏁版嵁',
+ component: 'Upload',
+ rules: 'required',
+ help: '浠呭厑璁稿鍏� xls銆亁lsx 鏍煎紡鏂囦欢',
+ },
+ {
+ fieldName: 'updateSupport',
+ label: '鏄惁瑕嗙洊',
+ component: 'Switch',
+ componentProps: {
+ checkedChildren: '鏄�',
+ unCheckedChildren: '鍚�',
+ },
+ rules: z.boolean().default(false),
+ help: '鏄惁鏇存柊宸茬粡瀛樺湪鐨勫矖浣嶆暟鎹�',
+ },
+ ];
+}
+
/** 鍒楄〃鐨勬悳绱㈣〃鍗� */
export function useGridFormSchema(): VbenFormSchema[] {
return [
diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue
index c59418e..a8039dc 100644
--- a/src/views/system/post/index.vue
+++ b/src/views/system/post/index.vue
@@ -20,9 +20,15 @@
import { useGridColumns, useGridFormSchema } from './data';
import Form from './modules/form.vue';
+import ImportForm from './modules/import-form.vue';
const [FormModal, formModalApi] = useVbenModal({
connectedComponent: Form,
+ destroyOnClose: true,
+});
+
+const [ImportModal, importModalApi] = useVbenModal({
+ connectedComponent: ImportForm,
destroyOnClose: true,
});
@@ -40,6 +46,11 @@
/** 鍒涘缓宀椾綅 */
function handleCreate() {
formModalApi.setData(null).open();
+}
+
+/** 瀵煎叆宀椾綅 */
+function handleImport() {
+ importModalApi.open();
}
/** 缂栬緫宀椾綅 */
@@ -126,6 +137,7 @@
<template>
<Page auto-content-height>
<FormModal @success="handleRefresh" />
+ <ImportModal @success="handleRefresh" />
<Grid table-title="宀椾綅鍒楄〃">
<template #toolbar-tools>
<TableAction
@@ -145,6 +157,13 @@
onClick: handleExport,
},
{
+ label: $t('ui.actionTitle.import'),
+ type: 'primary',
+ icon: ACTION_ICON.UPLOAD,
+ auth: ['system:post:import'],
+ onClick: handleImport,
+ },
+ {
label: $t('ui.actionTitle.deleteBatch'),
type: 'primary',
danger: true,
diff --git a/src/views/system/post/modules/import-form.vue b/src/views/system/post/modules/import-form.vue
new file mode 100644
index 0000000..ba6b9ca
--- /dev/null
+++ b/src/views/system/post/modules/import-form.vue
@@ -0,0 +1,82 @@
+<script lang="ts" setup>
+import type { FileType } from 'ant-design-vue/es/upload/interface';
+
+import { useVbenModal } from '@vben/common-ui';
+import { downloadFileFromBlobPart } from '@vben/utils';
+
+import { Button, message, Upload } from 'ant-design-vue';
+
+import { useVbenForm } from '#/adapter/form';
+import { importPost, importPostTemplate } from '#/api/system/post';
+import { $t } from '#/locales';
+
+import { useImportFormSchema } from '../data';
+
+const emit = defineEmits(['success']);
+
+const [Form, formApi] = useVbenForm({
+ commonConfig: {
+ formItemClass: 'col-span-2',
+ labelWidth: 120,
+ },
+ layout: 'horizontal',
+ schema: useImportFormSchema(),
+ showDefaultActions: false,
+});
+
+const [Modal, modalApi] = useVbenModal({
+ async onConfirm() {
+ const { valid } = await formApi.validate();
+ if (!valid) {
+ return;
+ }
+ modalApi.lock();
+ // 鎻愪氦琛ㄥ崟
+ const data = await formApi.getValues();
+ try {
+ await importPost(data.file, data.updateSupport);
+ // 鍏抽棴骞舵彁绀�
+ await modalApi.close();
+ emit('success');
+ message.success($t('ui.actionMessage.operationSuccess'));
+ } finally {
+ modalApi.unlock();
+ }
+ },
+});
+
+/** 涓婁紶鍓� */
+function beforeUpload(file: FileType) {
+ formApi.setFieldValue('file', file);
+ return false;
+}
+
+/** 涓嬭浇妯$増 */
+async function handleDownload() {
+ const data = await importPostTemplate();
+ downloadFileFromBlobPart({ fileName: '宀椾綅瀵煎叆妯℃澘.xls', source: data });
+}
+</script>
+
+<template>
+ <Modal title="瀵煎叆宀椾綅" class="w-1/3">
+ <Form class="mx-4">
+ <template #file>
+ <div class="w-full">
+ <Upload
+ :max-count="1"
+ accept=".xls,.xlsx"
+ :before-upload="beforeUpload"
+ >
+ <Button type="primary"> 閫夋嫨 Excel 鏂囦欢 </Button>
+ </Upload>
+ </div>
+ </template>
+ </Form>
+ <template #prepend-footer>
+ <div class="flex flex-auto items-center">
+ <Button @click="handleDownload"> 涓嬭浇瀵煎叆妯℃澘 </Button>
+ </div>
+ </template>
+ </Modal>
+</template>
--
Gitblit v1.9.3