wangzhibo
2026-07-16 b57020623cf0c946706573bf102e548c3a544423
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<template>
    <cl-upload
        type="file"
        :show-file-list="false"
        :auto-upload="false"
        :disabled="loading"
        @upload="onUpload"
    >
        <el-button type="success" :loading="loading">
            <cl-svg name="import" class="mr-[5px]" />
            {{ $t('导入') }}
        </el-button>
    </cl-upload>
 
    <cl-form ref="Form">
        <template #slot-tips>
            <el-alert type="warning">
                {{ $t('如遇到问题无法导入菜单,请检查文件并尝试重新导入。') }}
            </el-alert>
        </template>
    </cl-form>
</template>
 
<script lang="ts" setup>
defineOptions({
    name: 'menu-imp'
});
 
import { ElMessage } from 'element-plus';
import { useCool } from '/@/cool';
import { useCrud, useForm } from '@cool-vue/crud';
import { orderBy } from 'lodash-es';
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
 
const { t } = useI18n();
const { service } = useCool();
const Form = useForm();
const Crud = useCrud();
 
const loading = ref(false);
 
function onUpload(_: any, file: File) {
    // 加载状态
    loading.value = true;
 
    const reader = new FileReader();
 
    // 加载完成
    reader.onload = (e: ProgressEvent<FileReader>) => {
        loading.value = false;
 
        try {
            // 解析数据
            const data = JSON.parse(e.target?.result as string);
 
            // 打开表单
            Form.value?.open({
                title: t('菜单导入'),
                height: '400px',
                width: '600px',
                props: {
                    labelWidth: '0px'
                },
                op: {
                    saveButtonText: t('添加')
                },
                items: [
                    {
                        component: {
                            name: 'slot-tips'
                        }
                    },
                    {
                        component: {
                            name: 'el-tree',
                            props: {
                                data: orderBy(data, 'orderNum', 'asc'),
                                nodeKey: 'name',
                                props: {
                                    label: 'name',
                                    children: 'childMenus'
                                },
                                renderContent(_: any, { data }: any) {
                                    return data.name;
                                }
                            },
                            style: {
                                padding: '5px',
                                borderRadius: 'var(--el-border-radius-base)',
                                border: '1px solid var(--el-border-color)'
                            }
                        }
                    }
                ],
                on: {
                    submit(_, { close, done }) {
                        service.base.sys.menu
                            .import({
                                menus: data
                            })
                            .then(() => {
                                ElMessage.success(t('导入成功'));
                                Crud.value?.refresh();
                                close();
                            })
                            .catch(err => {
                                ElMessage.error(err.message);
                                done();
                            });
                    }
                }
            });
        } catch (error) {
            ElMessage.error(t('{file}文件格式错误:{error}', { file: file.name, error }));
        }
    };
 
    // 读取文件
    reader.readAsText(file);
}
</script>