wms-antdvue/.svn/pristine/72/72070b3ce70f1bf990433da06028bc08c32c4a75.svn-base
2024-11-07 16:33:03 +08:00

237 lines
7.8 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<a-modal
v-model:visible="props.visible"
:title="props.menuId ? '编辑' : '新增'"
width="600px"
:maskClosable="false"
@cancel="handleClose"
style="top: 20px"
>
<a-form ref="formRef" :model="formData" :label-col="{ style: { width: '90px' } }">
<a-form-item label="菜单类型" name="type" required>
<a-radio-group v-model:value="formData.type">
<a-radio :value="0">菜单</a-radio>
<a-radio :value="1">按钮</a-radio>
</a-radio-group>
</a-form-item>
<a-form-item
label="父级菜单"
name="parentId"
:rules="{ required: true, message: '请选择父级菜单', trigger: 'change' }"
>
<a-tree-select
class="flex-1"
v-model:value="formData.parentId"
:tree-data="menuOptions"
tree-default-expand-all
:fieldNames="{ children: 'children', label: 'name', value: 'id' }"
placeholder="请选择父级菜单"
/>
</a-form-item>
<a-form-item
label="菜单名称"
name="name"
:rules="{ required: true, message: '请输入菜单名称', trigger: 'blur' }"
>
<a-input v-model:value="formData.name" placeholder="请输入菜单名称" allow-clear />
</a-form-item>
<a-form-item v-if="formData.type == 0" label="菜单图标" name="icon2">
<icon-picker v-model:icon="formData.icon2">
<template #iconSelect>
<a-input v-model:value="formData.icon2" placeholder="请选择菜单图标">
<template #addonBefore>
<component :is="iconComponent(formData.icon2)" />
</template>
</a-input>
</template>
</icon-picker>
</a-form-item>
<a-form-item label="打开方式" name="target" v-if="formData.type == 0">
<div>
<a-radio-group v-model:value="formData.target">
<a-radio :value="0">组件</a-radio>
<a-radio :value="1">内链</a-radio>
<a-radio :value="2">外链</a-radio>
</a-radio-group>
<div class="form-tips"> 选择外链,则新窗口打开页面 </div>
</div>
</a-form-item>
<a-form-item
v-if="formData.type == 0 && (formData.target == 0 || formData.target == 1)"
label="路由路径"
name="path"
:rules="{ required: true, message: '请输入路由路径', trigger: 'blur' }"
>
<div class="flex-1">
<a-input v-model:value="formData.path" placeholder="请输入路由路径" allow-clear />
<div class="form-tips"> 访问的路由地址 </div>
</div>
</a-form-item>
<a-form-item v-if="formData.type == 0" label="组件路径" name="component">
<div class="flex-1">
<a-auto-complete
style="width: 100%"
v-model:value="formData.component"
:options="dataSource"
:filter-option="filterOption"
placeholder="请输入组件路径"
/>
<div class="form-tips">
访问的组件路径,如:`permission/admin/index`,默认在`views`目录下,如外网地址需内链访问则以`http(s)://`开头
</div>
</div>
</a-form-item>
<a-form-item v-if="formData.target == 0" label="权限字符" name="permission">
<div class="flex-1">
<a-input v-model:value="formData.permission" placeholder="请输入权限字符" allow-clear />
<div class="form-tips">
将作为server端API验权使用如`system:admin:list`,请谨慎修改
</div>
</div>
</a-form-item>
<a-form-item v-if="formData.type == 0" label="是否显示" name="hide" required>
<div>
<a-radio-group v-model:value="formData.hide">
<a-radio :value="0">显示</a-radio>
<a-radio :value="1">隐藏</a-radio>
</a-radio-group>
<div class="form-tips"> 选择隐藏则路由将不会出现在侧边栏,但仍然可以访问 </div>
</div>
</a-form-item>
<a-form-item v-if="formData.type == 0" label="菜单状态" name="status" required>
<div>
<a-radio-group v-model:value="formData.status">
<a-radio :value="0">正常</a-radio>
<a-radio :value="1">停用</a-radio>
</a-radio-group>
<div class="form-tips"> 选择停用则路由将不会出现在侧边栏,也不能被访问 </div>
</div>
</a-form-item>
<a-form-item label="菜单排序" name="sort">
<div>
<a-input-number v-model:value="formData.sort" :max="9999" />
<div class="form-tips">数值越小越排前</div>
</div>
</a-form-item>
</a-form>
<template #footer>
<span class="dialog-footer">
<a-button @click="handleClose">取消</a-button>
<a-button :loading="subLoading" type="primary" @click="submit"> 确定 </a-button>
</span>
</template>
</a-modal>
</template>
<script lang="ts" setup>
import { menuAdd, menuUpdate, getMenuList, getMenuDetail } from '@/api/system/menu';
import { onMounted, reactive, ref, shallowRef } from 'vue';
import type { FormInstance } from 'ant-design-vue';
import { getModulesKey } from '@/router';
import { arrayToTree, treeToArray, buildTree } from '@/utils/auth';
import { useLockFn } from '@/utils/useLockFn';
import IconPicker from '@/components/icon/picker.vue';
import * as VueIcon from '@ant-design/icons-vue';
import { message } from 'ant-design-vue';
const props = defineProps({
visible: {
type: Boolean,
required: true,
default: false,
},
menuId: {
type: Number,
required: true,
default: 0,
},
pid: {
type: Number,
default: 0,
},
});
const emit = defineEmits(['success', 'update:visible']);
const formRef = shallowRef<FormInstance>();
const dataSource = ref([]);
const componentsOptions = ref(getModulesKey());
const filterOption = (input: string, option: Option) => {
return option.value.toUpperCase().indexOf(input.toUpperCase()) >= 0;
};
const formData = reactive({
id: '',
//父级id
parentId: 0,
//类型
type: 0,
//图标
icon2: '',
//名称
name: '',
//排序号
sort: 0,
// 路由路径
path: '',
//权限链接
permission: '',
//前端组件
component: '',
//是否显示 0=显示, 1=不显示
hide: 0,
//是否外链 0=不是, 1=是
target: 0,
status: 0,
});
const menuOptions = ref<any[]>([]);
const iconComponent = (icon) => {
const IconComponent = VueIcon[icon];
return IconComponent;
};
const getMenu = async () => {
const data: any = await getMenuList();
const menu: any = { id: 0, name: '顶级', children: [] };
const lists = buildTree(data.filter((item) => item.type == 0));
menu.children = lists;
menuOptions.value.push(menu);
};
const handleSubmit = async () => {
await formRef.value?.validate();
props.menuId ? await menuUpdate(formData) : await menuAdd(formData);
message.success('操作成功');
emit('update:visible', false);
emit('success');
};
const { isLock: subLoading, lockFn: submit } = useLockFn(handleSubmit);
const setFormData = (data: Record<any, any>) => {
for (const key in formData) {
if (data[key] != null && data[key] != undefined) {
formData[key] = data[key];
}
}
};
const getDetail = async () => {
const data = await getMenuDetail(props.menuId);
setFormData(data);
};
const handleClose = () => {
emit('update:visible', false);
};
onMounted(() => {
componentsOptions.value.map((item) => {
dataSource.value.push({ label: item, value: item });
});
getMenu();
if (props.menuId) {
getDetail();
} else {
formData.parentId = props.pid;
}
});
</script>