zant-admin 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.en.md +36 -0
- package/README.md +248 -0
- package/SCAFFOLD_README.md +215 -0
- package/bin/cli.js +99 -0
- package/bin/generator.js +503 -0
- package/bin/prompts.js +159 -0
- package/bin/utils.js +134 -0
- package/package.json +74 -0
- package/public/logo.png +0 -0
- package/src/App.vue +16 -0
- package/src/api/methods/logError.js +8 -0
- package/src/api/methods/logOperation.js +8 -0
- package/src/api/methods/login.js +6 -0
- package/src/api/methods/quartz.js +36 -0
- package/src/api/methods/region.js +16 -0
- package/src/api/methods/sysAccount.js +30 -0
- package/src/api/methods/sysDict.js +29 -0
- package/src/api/methods/sysDictItem.js +26 -0
- package/src/api/methods/sysMenu.js +42 -0
- package/src/api/methods/sysRole.js +35 -0
- package/src/api/methods/sysUser.js +25 -0
- package/src/api/methods/system.js +16 -0
- package/src/api/request.js +225 -0
- package/src/assets/css/style.css +70 -0
- package/src/assets/css/zcui.css +340 -0
- package/src/assets/imgs/loginbackground.svg +69 -0
- package/src/assets/imgs/logo.png +0 -0
- package/src/assets/imgs/md/1.png +0 -0
- package/src/assets/imgs/md/10.png +0 -0
- package/src/assets/imgs/md/11.png +0 -0
- package/src/assets/imgs/md/2.png +0 -0
- package/src/assets/imgs/md/3.png +0 -0
- package/src/assets/imgs/md/4.png +0 -0
- package/src/assets/imgs/md/5.png +0 -0
- package/src/assets/imgs/md/6.png +0 -0
- package/src/assets/imgs/md/7.png +0 -0
- package/src/assets/imgs/md/8.png +0 -0
- package/src/assets/imgs/md/9.png +0 -0
- package/src/components/FormTable.vue +875 -0
- package/src/components/IconPicker.vue +344 -0
- package/src/components/MainPage.vue +957 -0
- package/src/components/details/logErrorDetails.vue +58 -0
- package/src/components/details/logOperationDetails.vue +76 -0
- package/src/components/edit/QuartzEdit.vue +221 -0
- package/src/components/edit/SysAccountEdit.vue +178 -0
- package/src/components/edit/SysDictEdit.vue +114 -0
- package/src/components/edit/SysDictItemEdit.vue +134 -0
- package/src/components/edit/SysRoleEdit.vue +109 -0
- package/src/components/edit/sysMenuEdit.vue +305 -0
- package/src/config/index.js +74 -0
- package/src/directives/permission.js +45 -0
- package/src/main.js +38 -0
- package/src/router/index.js +270 -0
- package/src/stores/config.js +37 -0
- package/src/stores/dict.js +33 -0
- package/src/stores/menu.js +57 -0
- package/src/stores/user.js +21 -0
- package/src/utils/baseEcharts.js +661 -0
- package/src/utils/dictTemplate.js +26 -0
- package/src/utils/regionUtils.js +169 -0
- package/src/utils/useFormCRUD.js +60 -0
- package/src/views/baiscstatis/center.vue +463 -0
- package/src/views/baiscstatis/iframePage.vue +31 -0
- package/src/views/baiscstatis/notFound.vue +192 -0
- package/src/views/console.vue +771 -0
- package/src/views/demo/importexport.vue +123 -0
- package/src/views/demo/region.vue +240 -0
- package/src/views/demo/statistics.vue +195 -0
- package/src/views/home.vue +7 -0
- package/src/views/login.vue +272 -0
- package/src/views/operations/log/logError.vue +78 -0
- package/src/views/operations/log/logLogin.vue +66 -0
- package/src/views/operations/log/logOperation.vue +103 -0
- package/src/views/operations/log/logQuartz.vue +57 -0
- package/src/views/operations/quartz.vue +181 -0
- package/src/views/operations/serviceMonitoring.vue +134 -0
- package/src/views/system/sysAccount.vue +123 -0
- package/src/views/system/sysDict.vue +156 -0
- package/src/views/system/sysDictItem.vue +118 -0
- package/src/views/system/sysMenu.vue +223 -0
- package/src/views/system/sysRole.vue +184 -0
- package/templates/env.production +2 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a-drawer
|
|
3
|
+
:title="editTitle"
|
|
4
|
+
:width="540"
|
|
5
|
+
:open="open"
|
|
6
|
+
:body-style="{ paddingBottom: '80px' }"
|
|
7
|
+
:footer-style="{ textAlign: 'right' }"
|
|
8
|
+
@close="onClose"
|
|
9
|
+
:destroyOnClose="true"
|
|
10
|
+
>
|
|
11
|
+
<a-form :model="formInfo" ref="formRef" layout="vertical">
|
|
12
|
+
<a-form-item
|
|
13
|
+
label="字典标签"
|
|
14
|
+
name="label"
|
|
15
|
+
:rules="[{ required: true, message: '字典标签不能为空' }]"
|
|
16
|
+
>
|
|
17
|
+
<a-input
|
|
18
|
+
:class="formInfo.colorClass"
|
|
19
|
+
v-model:value="formInfo.label"
|
|
20
|
+
placeholder="请输入"
|
|
21
|
+
/>
|
|
22
|
+
</a-form-item>
|
|
23
|
+
<a-form-item label="字典值" name="value">
|
|
24
|
+
<a-input-number v-model:value="formInfo.value" placeholder="请输入" />
|
|
25
|
+
</a-form-item>
|
|
26
|
+
<a-form-item label="颜色样式" name="colorClass">
|
|
27
|
+
<a-select v-model:value="formInfo.colorClass" @change="selectColor">
|
|
28
|
+
<a-select-option value="default">default</a-select-option>
|
|
29
|
+
<a-select-option value="text-color-primary">primary</a-select-option>
|
|
30
|
+
<a-select-option value="text-color-success">success</a-select-option>
|
|
31
|
+
<a-select-option value="text-color-warning">warning</a-select-option>
|
|
32
|
+
<a-select-option value="text-color-error">error</a-select-option>
|
|
33
|
+
<a-select-option value="text-color-gray">gray</a-select-option>
|
|
34
|
+
<a-select-option value="text-color-textgray"
|
|
35
|
+
>textgray</a-select-option
|
|
36
|
+
>
|
|
37
|
+
</a-select>
|
|
38
|
+
</a-form-item>
|
|
39
|
+
<a-form-item label="排序" name="sort">
|
|
40
|
+
<a-input-number v-model:value="formInfo.sort" placeholder="请输入" />
|
|
41
|
+
</a-form-item>
|
|
42
|
+
<a-form-item label="是否启用" name="isEnable">
|
|
43
|
+
<a-switch v-model:checked="formInfo.isEnable" />
|
|
44
|
+
</a-form-item>
|
|
45
|
+
<a-form-item label="备注" name="remark">
|
|
46
|
+
<a-textarea v-model:value="formInfo.remark" />
|
|
47
|
+
</a-form-item>
|
|
48
|
+
</a-form>
|
|
49
|
+
<template #extra>
|
|
50
|
+
<a-space>
|
|
51
|
+
<a-button type="primary" @click="onSave" :loading="loading">保存</a-button>
|
|
52
|
+
<a-button @click="resetForm">重置</a-button>
|
|
53
|
+
</a-space>
|
|
54
|
+
</template>
|
|
55
|
+
</a-drawer>
|
|
56
|
+
</template>
|
|
57
|
+
<script setup>
|
|
58
|
+
import { defineProps, defineEmits, ref, reactive } from 'vue'
|
|
59
|
+
import { message } from 'ant-design-vue'
|
|
60
|
+
import sysDictItem from '@/api/methods/sysDictItem'
|
|
61
|
+
import useFormCRUD from '@/utils/useFormCRUD'
|
|
62
|
+
const props = defineProps({
|
|
63
|
+
open: {
|
|
64
|
+
type: Boolean,
|
|
65
|
+
required: true,
|
|
66
|
+
},
|
|
67
|
+
recordwhere: {
|
|
68
|
+
type: Object,
|
|
69
|
+
default: {},
|
|
70
|
+
},
|
|
71
|
+
})
|
|
72
|
+
const defaultformInfo = {
|
|
73
|
+
id: null,
|
|
74
|
+
dictId: props.recordwhere.dictId,
|
|
75
|
+
label: '',
|
|
76
|
+
colorClass: 'default',
|
|
77
|
+
value: 0,
|
|
78
|
+
sort: 0,
|
|
79
|
+
isEnable: true,
|
|
80
|
+
remark: '',
|
|
81
|
+
}
|
|
82
|
+
// 使用 reactive 定义表单状态
|
|
83
|
+
const formInfo = reactive({ ...defaultformInfo })
|
|
84
|
+
const editTitle = ref('新增')
|
|
85
|
+
const formRef = ref(null)
|
|
86
|
+
// 定义 emits,用于触发关闭事件
|
|
87
|
+
const emit = defineEmits(['close', 'updateData'])
|
|
88
|
+
/**
|
|
89
|
+
* 重置表单到默认值
|
|
90
|
+
*/
|
|
91
|
+
const resetForm = () => {
|
|
92
|
+
Object.assign(formInfo, defaultformInfo)
|
|
93
|
+
formRef.value?.resetFields()
|
|
94
|
+
}
|
|
95
|
+
const { loading, save } = useFormCRUD(sysDictItem)
|
|
96
|
+
|
|
97
|
+
const init = async id => {
|
|
98
|
+
const isEdit = !!id
|
|
99
|
+
editTitle.value = isEdit ? '修改' : '新增'
|
|
100
|
+
if (isEdit) {
|
|
101
|
+
try {
|
|
102
|
+
const res = await sysDictItem.get({ id })
|
|
103
|
+
Object.assign(formInfo, res.data)
|
|
104
|
+
} catch (error) {
|
|
105
|
+
message.error('获取信息失败,请重试')
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
console.log("ss"+props.recordwhere)
|
|
109
|
+
resetForm()
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const onSave = async() => {
|
|
114
|
+
await save(formRef.value, formInfo, {
|
|
115
|
+
onSuccess: () => {
|
|
116
|
+
emit('updateData')
|
|
117
|
+
onClose()
|
|
118
|
+
}
|
|
119
|
+
})
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const selectColor = e => {
|
|
123
|
+
console.log(e)
|
|
124
|
+
formInfo.colorClass = e
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const onClose = () => {
|
|
128
|
+
emit('close')
|
|
129
|
+
}
|
|
130
|
+
// 使用 defineExpose 暴露方法
|
|
131
|
+
defineExpose({
|
|
132
|
+
init,
|
|
133
|
+
})
|
|
134
|
+
</script>
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a-drawer
|
|
3
|
+
:title="editTitle"
|
|
4
|
+
:width="540"
|
|
5
|
+
:open="open"
|
|
6
|
+
:body-style="{ paddingBottom: '80px' }"
|
|
7
|
+
:footer-style="{ textAlign: 'right' }"
|
|
8
|
+
@close="onClose"
|
|
9
|
+
:destroyOnClose="true"
|
|
10
|
+
>
|
|
11
|
+
<a-form :model="formInfo" ref="formRef" layout="vertical">
|
|
12
|
+
<a-form-item
|
|
13
|
+
label="角色名称"
|
|
14
|
+
name="name"
|
|
15
|
+
:rules="[{ required: true, message: '角色名称不能为空' }]"
|
|
16
|
+
>
|
|
17
|
+
<a-input v-model:value="formInfo.name" placeholder="请输入" />
|
|
18
|
+
</a-form-item>
|
|
19
|
+
<a-form-item label="是否启用" name="isEnable">
|
|
20
|
+
<a-switch v-model:checked="formInfo.isEnable" />
|
|
21
|
+
</a-form-item>
|
|
22
|
+
<a-form-item label="备注" name="remark">
|
|
23
|
+
<a-textarea v-model:value="formInfo.remark" />
|
|
24
|
+
</a-form-item>
|
|
25
|
+
</a-form>
|
|
26
|
+
<template #extra>
|
|
27
|
+
<a-space>
|
|
28
|
+
<a-button type="primary" @click="onSave" :loading="loading">保存</a-button>
|
|
29
|
+
<a-button @click="resetForm">重置</a-button>
|
|
30
|
+
</a-space>
|
|
31
|
+
</template>
|
|
32
|
+
</a-drawer>
|
|
33
|
+
</template>
|
|
34
|
+
<script setup>
|
|
35
|
+
import { defineProps, defineEmits, ref, reactive } from 'vue'
|
|
36
|
+
import { message } from 'ant-design-vue'
|
|
37
|
+
import sysRole from '@/api/methods/sysRole'
|
|
38
|
+
import useFormCRUD from '@/utils/useFormCRUD'
|
|
39
|
+
const props = defineProps({
|
|
40
|
+
open: {
|
|
41
|
+
type: Boolean,
|
|
42
|
+
required: true,
|
|
43
|
+
},
|
|
44
|
+
})
|
|
45
|
+
// 表单字段的默认值
|
|
46
|
+
const defaultformInfo = {
|
|
47
|
+
id: null,
|
|
48
|
+
name: '',
|
|
49
|
+
isEnable: true,
|
|
50
|
+
remark: '',
|
|
51
|
+
}
|
|
52
|
+
// 响应式数据
|
|
53
|
+
const formInfo = reactive({ ...defaultformInfo })
|
|
54
|
+
const editTitle = ref('新增')
|
|
55
|
+
const formRef = ref(null)
|
|
56
|
+
// 定义 emits,用于触发关闭事件
|
|
57
|
+
const emit = defineEmits(['close', 'updateData'])
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* 重置表单到默认值
|
|
61
|
+
*/
|
|
62
|
+
const resetForm = () => {
|
|
63
|
+
Object.assign(formInfo, defaultformInfo)
|
|
64
|
+
formRef.value?.resetFields()
|
|
65
|
+
}
|
|
66
|
+
const { loading, save } = useFormCRUD(sysRole)
|
|
67
|
+
/**
|
|
68
|
+
* 初始化角色编辑表单
|
|
69
|
+
* @param {number} id - 角色ID,如果为0或空则表示新增角色
|
|
70
|
+
*/
|
|
71
|
+
const init = async id => {
|
|
72
|
+
const isEdit = !!id
|
|
73
|
+
editTitle.value = isEdit ? '修改' : '新增'
|
|
74
|
+
|
|
75
|
+
if (isEdit) {
|
|
76
|
+
try {
|
|
77
|
+
const res = await sysRole.get({ id })
|
|
78
|
+
Object.assign(formInfo, res.data)
|
|
79
|
+
} catch (error) {
|
|
80
|
+
message.error('获取信息失败,请重试')
|
|
81
|
+
}
|
|
82
|
+
} else {
|
|
83
|
+
resetForm()
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* 保存角色信息
|
|
89
|
+
* 处理表单验证和角色新增/修改操作
|
|
90
|
+
*/
|
|
91
|
+
const onSave = async () => {
|
|
92
|
+
await save(formRef.value, formInfo, {
|
|
93
|
+
onSuccess: () => {
|
|
94
|
+
emit('updateData')
|
|
95
|
+
onClose()
|
|
96
|
+
}
|
|
97
|
+
})
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* 关闭抽屉组件
|
|
101
|
+
* 触发关闭事件并通知父组件
|
|
102
|
+
*/
|
|
103
|
+
const onClose = () => {
|
|
104
|
+
resetForm()
|
|
105
|
+
emit('close')
|
|
106
|
+
}
|
|
107
|
+
// 使用 defineExpose 暴露方法
|
|
108
|
+
defineExpose({ init })
|
|
109
|
+
</script>
|
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<a-drawer
|
|
3
|
+
:title="editTitle"
|
|
4
|
+
:width="640"
|
|
5
|
+
:open="open"
|
|
6
|
+
:body-style="{ paddingBottom: '80px' }"
|
|
7
|
+
:footer-style="{ textAlign: 'right' }"
|
|
8
|
+
@close="onClose"
|
|
9
|
+
:destroyOnClose="true"
|
|
10
|
+
>
|
|
11
|
+
<a-skeleton :loading="initloading" active>
|
|
12
|
+
<a-form :model="formInfo" ref="formRef" layout="vertical">
|
|
13
|
+
<a-row :gutter="16">
|
|
14
|
+
<a-col :span="12">
|
|
15
|
+
<a-form-item label="菜单名称" name="title">
|
|
16
|
+
<a-input v-model:value="formInfo.title" placeholder="请输入" />
|
|
17
|
+
</a-form-item>
|
|
18
|
+
</a-col>
|
|
19
|
+
<a-col :span="12">
|
|
20
|
+
<a-form-item label="类型">
|
|
21
|
+
<a-radio-group v-model:value="formInfo.type">
|
|
22
|
+
<a-radio :value="1">目录</a-radio>
|
|
23
|
+
<a-radio :value="2">菜单</a-radio>
|
|
24
|
+
<a-radio :value="3">链接</a-radio>
|
|
25
|
+
<a-radio :value="4">按钮</a-radio>
|
|
26
|
+
</a-radio-group>
|
|
27
|
+
</a-form-item>
|
|
28
|
+
</a-col>
|
|
29
|
+
</a-row>
|
|
30
|
+
|
|
31
|
+
<a-row :gutter="16">
|
|
32
|
+
<a-col :span="12">
|
|
33
|
+
<a-form-item label="上级目录" name="parentId">
|
|
34
|
+
<a-tree-select
|
|
35
|
+
v-model:value="formInfo.parentId"
|
|
36
|
+
show-search
|
|
37
|
+
style="width: 100%"
|
|
38
|
+
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
|
|
39
|
+
placeholder="请选择"
|
|
40
|
+
allow-clear
|
|
41
|
+
tree-default-expand-all
|
|
42
|
+
:tree-data="menuList"
|
|
43
|
+
tree-node-filter-prop="label"
|
|
44
|
+
@change="selecthandleChange"
|
|
45
|
+
>
|
|
46
|
+
</a-tree-select>
|
|
47
|
+
</a-form-item>
|
|
48
|
+
</a-col>
|
|
49
|
+
<a-col :span="12">
|
|
50
|
+
<a-form-item
|
|
51
|
+
label="命名路由"
|
|
52
|
+
name="path"
|
|
53
|
+
>
|
|
54
|
+
<a-input v-model:value="formInfo.path" placeholder="请输入" />
|
|
55
|
+
</a-form-item>
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
</a-col>
|
|
59
|
+
</a-row>
|
|
60
|
+
<a-row :gutter="16" v-if="formInfo.type == 3" >
|
|
61
|
+
<a-col :span="12">
|
|
62
|
+
<a-form-item label="是否外链" name="cache">
|
|
63
|
+
<a-switch v-model:checked="formInfo.isExternalLink" />
|
|
64
|
+
</a-form-item>
|
|
65
|
+
</a-col>
|
|
66
|
+
<a-col :span="12">
|
|
67
|
+
<a-form-item label="链接" name="url">
|
|
68
|
+
<a-input v-model:value="formInfo.url" placeholder="请输入" />
|
|
69
|
+
</a-form-item>
|
|
70
|
+
</a-col>
|
|
71
|
+
</a-row>
|
|
72
|
+
<a-row :gutter="16">
|
|
73
|
+
<a-col :span="12">
|
|
74
|
+
<a-form-item label="权限标识" name="perms">
|
|
75
|
+
<a-input v-model:value="formInfo.perms" placeholder="请输入" />
|
|
76
|
+
</a-form-item>
|
|
77
|
+
</a-col>
|
|
78
|
+
<a-col :span="12">
|
|
79
|
+
|
|
80
|
+
<a-form-item label="排序" name="Sort">
|
|
81
|
+
<a-input-number
|
|
82
|
+
v-model:value="formInfo.sort"
|
|
83
|
+
style="width: 100%"
|
|
84
|
+
placeholder="请输入"
|
|
85
|
+
/>
|
|
86
|
+
</a-form-item>
|
|
87
|
+
</a-col>
|
|
88
|
+
</a-row>
|
|
89
|
+
<a-row :gutter="16">
|
|
90
|
+
<a-col :span="12">
|
|
91
|
+
<a-form-item label="图标" name="icon">
|
|
92
|
+
<IconPicker v-model:value="formInfo.icon" />
|
|
93
|
+
</a-form-item>
|
|
94
|
+
</a-col>
|
|
95
|
+
</a-row>
|
|
96
|
+
<a-row :gutter="16" v-if="formInfo.type == 2">
|
|
97
|
+
<a-col :span="24">
|
|
98
|
+
<a-form-item label="预置按钮">
|
|
99
|
+
<a-checkbox-group
|
|
100
|
+
v-model:value="formInfo.btnoptions"
|
|
101
|
+
name="checkboxgroup"
|
|
102
|
+
:options="btnoptions"
|
|
103
|
+
/>
|
|
104
|
+
</a-form-item>
|
|
105
|
+
</a-col>
|
|
106
|
+
</a-row>
|
|
107
|
+
<a-row :gutter="16">
|
|
108
|
+
<a-col :span="12">
|
|
109
|
+
<a-form-item label="是否启用" name="isEnable">
|
|
110
|
+
<a-switch v-model:checked="formInfo.isEnable" />
|
|
111
|
+
</a-form-item>
|
|
112
|
+
</a-col>
|
|
113
|
+
<a-col :span="12">
|
|
114
|
+
<a-form-item
|
|
115
|
+
label="是否开启缓存"
|
|
116
|
+
name="cache"
|
|
117
|
+
|
|
118
|
+
>
|
|
119
|
+
<a-switch v-model:checked="formInfo.cache" />
|
|
120
|
+
</a-form-item>
|
|
121
|
+
</a-col>
|
|
122
|
+
<a-col :span="12">
|
|
123
|
+
<a-form-item
|
|
124
|
+
label="显示系统菜单栏"
|
|
125
|
+
name="isShowMenu"
|
|
126
|
+
|
|
127
|
+
>
|
|
128
|
+
<a-switch v-model:checked="formInfo.isShowMenu" />
|
|
129
|
+
</a-form-item>
|
|
130
|
+
</a-col>
|
|
131
|
+
</a-row>
|
|
132
|
+
</a-form>
|
|
133
|
+
</a-skeleton>
|
|
134
|
+
<template #extra>
|
|
135
|
+
<a-space>
|
|
136
|
+
<a-button type="primary" @click="onSave" :loading="loading"
|
|
137
|
+
>保存</a-button
|
|
138
|
+
>
|
|
139
|
+
<a-button @click="resetForm">重置</a-button>
|
|
140
|
+
</a-space>
|
|
141
|
+
</template>
|
|
142
|
+
</a-drawer>
|
|
143
|
+
</template>
|
|
144
|
+
<script setup>
|
|
145
|
+
import { defineProps, defineEmits, ref, reactive, computed } from 'vue'
|
|
146
|
+
import { message } from 'ant-design-vue'
|
|
147
|
+
import sysMenu from '@/api/methods/sysMenu'
|
|
148
|
+
import useFormCRUD from '@/utils/useFormCRUD'
|
|
149
|
+
import IconPicker from '@/components/IconPicker.vue'
|
|
150
|
+
|
|
151
|
+
const props = defineProps({
|
|
152
|
+
open: {
|
|
153
|
+
type: Boolean,
|
|
154
|
+
required: true,
|
|
155
|
+
},
|
|
156
|
+
})
|
|
157
|
+
// 根据权限标识动态生成按钮选项
|
|
158
|
+
const btnoptions = computed(() => {
|
|
159
|
+
const basePerms = formInfo.perms || '';
|
|
160
|
+
return [
|
|
161
|
+
{
|
|
162
|
+
label: '详情',
|
|
163
|
+
value: basePerms ? `${basePerms}:details` : 'details',
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
label: '新增',
|
|
167
|
+
value: basePerms ? `${basePerms}:add` : 'add',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
label: '修改',
|
|
171
|
+
value: basePerms ? `${basePerms}:update` : 'update',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
label: '删除',
|
|
175
|
+
value: basePerms ? `${basePerms}:delete` : 'delete',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
label: '导入',
|
|
179
|
+
value: basePerms ? `${basePerms}:import` : 'import',
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
label: '导出',
|
|
183
|
+
value: basePerms ? `${basePerms}:export` : 'export',
|
|
184
|
+
},
|
|
185
|
+
];
|
|
186
|
+
});
|
|
187
|
+
//表单字段的默认值
|
|
188
|
+
const defaultformInfo = {
|
|
189
|
+
id: null,
|
|
190
|
+
parentId: '0',
|
|
191
|
+
title: '',
|
|
192
|
+
path: '/',
|
|
193
|
+
icon: '',
|
|
194
|
+
url: '',
|
|
195
|
+
sort: 0,
|
|
196
|
+
isEnable: true,
|
|
197
|
+
cache: true,
|
|
198
|
+
isShowMenu: true,
|
|
199
|
+
type: 1,
|
|
200
|
+
isExternalLink: false,
|
|
201
|
+
perms:'',
|
|
202
|
+
btnoptions: [],
|
|
203
|
+
}
|
|
204
|
+
// 使用 reactive 定义表单状态
|
|
205
|
+
const formInfo = reactive({ ...defaultformInfo })
|
|
206
|
+
const editTitle = ref('新增')
|
|
207
|
+
const formRef = ref(null)
|
|
208
|
+
const menuList = ref([])
|
|
209
|
+
// 定义 emits,用于触发关闭事件
|
|
210
|
+
const emit = defineEmits(['close', 'updateData'])
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* 重置表单到默认值
|
|
214
|
+
*/
|
|
215
|
+
const resetForm = () => {
|
|
216
|
+
Object.assign(formInfo, defaultformInfo)
|
|
217
|
+
formRef.value?.resetFields()
|
|
218
|
+
}
|
|
219
|
+
const { loading, save } = useFormCRUD(sysMenu)
|
|
220
|
+
|
|
221
|
+
// 获取菜单树数据
|
|
222
|
+
const getMenuTree = async () => {
|
|
223
|
+
try {
|
|
224
|
+
const res = await sysMenu.getTreeSelectMenu()
|
|
225
|
+
menuList.value = res.data
|
|
226
|
+
} catch (error) {}
|
|
227
|
+
}
|
|
228
|
+
const initloading = ref(false)
|
|
229
|
+
// 初始化方法
|
|
230
|
+
const init = async id => {
|
|
231
|
+
initloading.value = true
|
|
232
|
+
const isEdit = !!id
|
|
233
|
+
editTitle.value = isEdit ? '修改' : '新增'
|
|
234
|
+
|
|
235
|
+
if (isEdit) {
|
|
236
|
+
try {
|
|
237
|
+
const res = await sysMenu.get({ id })
|
|
238
|
+
initloading.value = false
|
|
239
|
+
Object.assign(formInfo, res.data)
|
|
240
|
+
|
|
241
|
+
} catch (error) {
|
|
242
|
+
message.error('获取信息失败,请重试')
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
initloading.value = false
|
|
246
|
+
resetForm()
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// 保存操作
|
|
251
|
+
const onSave = async () => {
|
|
252
|
+
await save(formRef.value, formInfo, {
|
|
253
|
+
onSuccess: () => {
|
|
254
|
+
emit('updateData')
|
|
255
|
+
onClose()
|
|
256
|
+
},
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// 选择处理变化
|
|
261
|
+
const selecthandleChange = value => {
|
|
262
|
+
if (value == '0') {
|
|
263
|
+
formInfo.path = '/'
|
|
264
|
+
} else {
|
|
265
|
+
menuList.value.forEach(item => {
|
|
266
|
+
if (item.value == value) {
|
|
267
|
+
formInfo.path = item.path + '/'
|
|
268
|
+
}
|
|
269
|
+
})
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// 添加子菜单
|
|
274
|
+
const addSubmenu = record => {
|
|
275
|
+
editTitle.value = '新增子菜单'
|
|
276
|
+
resetForm()
|
|
277
|
+
formInfo.id = null
|
|
278
|
+
formInfo.parentId = record.id
|
|
279
|
+
formInfo.path = record.path + '/'
|
|
280
|
+
formInfo.sort = record.sort
|
|
281
|
+
}
|
|
282
|
+
const addSubtn = record => {
|
|
283
|
+
editTitle.value = '新增按照'
|
|
284
|
+
resetForm()
|
|
285
|
+
formInfo.id = null
|
|
286
|
+
formInfo.parentId = record.id
|
|
287
|
+
formInfo.path = ''
|
|
288
|
+
formInfo.perms = record.perms
|
|
289
|
+
formInfo.sort = record.sort
|
|
290
|
+
formInfo.type = 4
|
|
291
|
+
}
|
|
292
|
+
// 关闭处理
|
|
293
|
+
const onClose = () => {
|
|
294
|
+
resetForm()
|
|
295
|
+
emit('close')
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// 使用 defineExpose 暴露方法
|
|
299
|
+
defineExpose({
|
|
300
|
+
init,
|
|
301
|
+
getMenuTree,
|
|
302
|
+
addSubmenu,
|
|
303
|
+
addSubtn,
|
|
304
|
+
})
|
|
305
|
+
</script>
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 全局配置文件
|
|
3
|
+
* 用于定义项目的全局配置信息
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// 项目基本信息
|
|
7
|
+
export const projectConfig = {
|
|
8
|
+
// 项目名称
|
|
9
|
+
name: 'ZAntAdmin',
|
|
10
|
+
// 项目版本
|
|
11
|
+
version: '1.0.0',
|
|
12
|
+
// 项目描述
|
|
13
|
+
description: '基于 Vue 3.5 + Ant Design Vue 的管理系统',
|
|
14
|
+
// 项目作者
|
|
15
|
+
author: 'ZC',
|
|
16
|
+
// 项目主页
|
|
17
|
+
homepage: '',
|
|
18
|
+
// 项目仓库
|
|
19
|
+
repository: '',
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// API 配置
|
|
23
|
+
export const apiConfig = {
|
|
24
|
+
// API 基础路径
|
|
25
|
+
baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
|
|
26
|
+
// 请求超时时间
|
|
27
|
+
timeout: 10000,
|
|
28
|
+
// 请求头
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
},
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// 应用配置
|
|
35
|
+
export const appConfig = {
|
|
36
|
+
// 应用标题
|
|
37
|
+
title: projectConfig.name,
|
|
38
|
+
// 应用图标
|
|
39
|
+
icon: '/logo.png',
|
|
40
|
+
// 默认语言
|
|
41
|
+
defaultLanguage: 'zh-cn',
|
|
42
|
+
// 默认主题
|
|
43
|
+
defaultTheme: 'dark',
|
|
44
|
+
// 默认导航模式
|
|
45
|
+
defaultNavigationMode: 'side',
|
|
46
|
+
// 默认表格大小
|
|
47
|
+
defaultTableSize: 'middle',
|
|
48
|
+
// 默认表格边框
|
|
49
|
+
defaultTableBordered: true,
|
|
50
|
+
// 是否显示页脚
|
|
51
|
+
showFooter: true,
|
|
52
|
+
// 页脚文本
|
|
53
|
+
footerText: `© ${new Date().getFullYear()} ${projectConfig.name}`,
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// 路由配置
|
|
57
|
+
export const routerConfig = {
|
|
58
|
+
// 首页路径
|
|
59
|
+
homePath: '/console',
|
|
60
|
+
// 登录页路径
|
|
61
|
+
loginPath: '/login',
|
|
62
|
+
// 404 页面路径
|
|
63
|
+
notFoundPath: '/404',
|
|
64
|
+
// 是否开启路由守卫
|
|
65
|
+
guard: true,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// 默认导出所有配置
|
|
69
|
+
export default {
|
|
70
|
+
project: projectConfig,
|
|
71
|
+
api: apiConfig,
|
|
72
|
+
app: appConfig,
|
|
73
|
+
router: routerConfig,
|
|
74
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { menuStore } from '@/stores/menu'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 按钮权限指令
|
|
5
|
+
* 使用方式:v-permission="'user:add'" 或 v-permission="['user:add', 'user:edit']"
|
|
6
|
+
*/
|
|
7
|
+
const permission = {
|
|
8
|
+
mounted(el, binding) {
|
|
9
|
+
const { value } = binding
|
|
10
|
+
const store = menuStore()
|
|
11
|
+
const { permissions } = store
|
|
12
|
+
|
|
13
|
+
if (value && value instanceof Array) {
|
|
14
|
+
// 多个权限,满足其中一个即可
|
|
15
|
+
const hasPermission = value.some(permission => permissions.includes(permission))
|
|
16
|
+
if (!hasPermission) {
|
|
17
|
+
el.parentNode && el.parentNode.removeChild(el)
|
|
18
|
+
}
|
|
19
|
+
} else if (value && typeof value === 'string') {
|
|
20
|
+
// 单个权限
|
|
21
|
+
if (!permissions.includes(value)) {
|
|
22
|
+
el.parentNode && el.parentNode.removeChild(el)
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
updated(el, binding) {
|
|
27
|
+
// 更新时重新检查权限
|
|
28
|
+
const { value } = binding
|
|
29
|
+
const store = menuStore()
|
|
30
|
+
const { permissions } = store
|
|
31
|
+
|
|
32
|
+
if (value && value instanceof Array) {
|
|
33
|
+
const hasPermission = value.some(permission => permissions.includes(permission))
|
|
34
|
+
if (!hasPermission && el.parentNode) {
|
|
35
|
+
el.parentNode.removeChild(el)
|
|
36
|
+
}
|
|
37
|
+
} else if (value && typeof value === 'string') {
|
|
38
|
+
if (!permissions.includes(value) && el.parentNode) {
|
|
39
|
+
el.parentNode.removeChild(el)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export default permission
|
package/src/main.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { createApp } from 'vue'
|
|
2
|
+
import { createPinia } from 'pinia'
|
|
3
|
+
import piniaPersist from 'pinia-plugin-persist'
|
|
4
|
+
import Antd from 'ant-design-vue'
|
|
5
|
+
import App from './App.vue'
|
|
6
|
+
import router from './router'
|
|
7
|
+
import './assets/css/style.css'
|
|
8
|
+
import './assets/css/zcui.css'
|
|
9
|
+
import * as Icons from '@ant-design/icons-vue'
|
|
10
|
+
// 引入权限指令
|
|
11
|
+
import permission from './directives/permission'
|
|
12
|
+
// 引入 Ant Design Vue 的语言包
|
|
13
|
+
|
|
14
|
+
const app = createApp(App)
|
|
15
|
+
// 注册所有图标为全局组件
|
|
16
|
+
Object.keys(Icons).forEach(key => {
|
|
17
|
+
app.component(key, Icons[key])
|
|
18
|
+
})
|
|
19
|
+
// 将图标注册为全局变量
|
|
20
|
+
app.config.globalProperties.$icons = Icons
|
|
21
|
+
|
|
22
|
+
const pinia = createPinia()
|
|
23
|
+
// 配置 Pinia 持久化插件
|
|
24
|
+
pinia.use(piniaPersist)
|
|
25
|
+
// 使用 Pinia
|
|
26
|
+
app.use(pinia)
|
|
27
|
+
//使用 Ant Design
|
|
28
|
+
app.use(Antd)
|
|
29
|
+
|
|
30
|
+
// 使用路由
|
|
31
|
+
app.use(router)
|
|
32
|
+
|
|
33
|
+
// 注册权限指令
|
|
34
|
+
app.directive('permission', permission)
|
|
35
|
+
|
|
36
|
+
// 挂载应用
|
|
37
|
+
app.mount('#app')
|
|
38
|
+
|