init project

This commit is contained in:
Timi
2026-08-01 18:01:23 +08:00
parent 286fa1ba56
commit 11c48bf00c
107 changed files with 19350 additions and 1 deletions
+194
View File
@@ -0,0 +1,194 @@
<template>
<div v-role="permissionManagementRoleAccess" v-can="pageAccess" class="role-edit">
<t-form class="form" label-align="left">
<t-form-item label="名称">
<t-input v-model.trim="formModel.name" placeholder="角色名称" borderless />
</t-form-item>
<t-form-item label="代码">
<t-input v-model.trim="formModel.code" placeholder="如 front-desk" borderless />
</t-form-item>
<t-form-item label="模块">
<t-input v-model.trim="formModel.moduleCode" placeholder="模块代码" borderless />
</t-form-item>
<t-form-item label="说明">
<t-textarea v-model.trim="formModel.description" class="textarea" placeholder="角色说明" autosize borderless />
</t-form-item>
</t-form>
<section class="children">
<div class="title">
<span>子角色</span>
<span class="hint">父角色会继承子角色权限</span>
</div>
<t-checkbox-group class="group" v-model="formModel.childRoleIdList">
<t-checkbox
class="item bg-transparent"
v-for="item in childOptions"
:key="item.id"
:value="item.id"
:label="item.name"
icon="line"
borderless
default-checked
/>
</t-checkbox-group>
</section>
<t-button v-can="savePermissionCode" class="save" theme="primary" @click="saveRole">保存</t-button>
</div>
</template>
<script setup lang="ts">
import { Toast } from "tdesign-mobile-vue";
import { gaoModuleCode, usePermissionSettingsStore } from "@/store/permissionSettingsStore";
import { corePermissionCodes, permissionManagementRoleAccess } from "@/utils/gaoPermission";
defineOptions({
name: "RoleEdit"
});
const route = useRoute();
const router = useRouter();
const permissionStore = usePermissionSettingsStore();
const routeId = computed(() => String(route.params.id || ""));
const isCreateMode = computed(() => !routeId.value);
const savePermissionCode = computed(() => isCreateMode.value ? corePermissionCodes.role.create : corePermissionCodes.role.update);
const pageAccess = computed(() => ({
value: [corePermissionCodes.role.read, corePermissionCodes.permission.read, savePermissionCode.value],
mode: "and" as const
}));
const formModel = reactive({
id: "",
moduleCode: gaoModuleCode,
code: "",
name: "",
description: "",
childRoleIdList: [] as string[]
});
const childOptions = computed(() => permissionStore.roleList.filter(item => item.id !== formModel.id && !hasChildRole(item.id, formModel.id)));
function hasChildRole(roleId: string, targetRoleId: string, visitedRoleIds = new Set<string>()): boolean {
if (visitedRoleIds.has(roleId)) {
return false;
}
const current = permissionStore.getRoleById(roleId);
if (!current) {
return false;
}
visitedRoleIds.add(roleId);
return current.childRoleIdList.some(childRoleId => childRoleId === targetRoleId || hasChildRole(childRoleId, targetRoleId, visitedRoleIds));
}
async function fillForm(): Promise<void> {
await permissionStore.loadAll();
const current = await permissionStore.loadRoleDetail(routeId.value);
Object.assign(formModel, {
id: current.id,
moduleCode: current.moduleCode || gaoModuleCode,
code: current.code,
name: current.name,
description: current.description,
childRoleIdList: [...current.childRoleIdList]
});
}
async function saveRole(): Promise<void> {
const role = await permissionStore.upsertRole({
id: formModel.id,
moduleCode: gaoModuleCode,
code: formModel.code,
name: formModel.name,
description: formModel.description,
permissionIdList: permissionStore.getRoleById(formModel.id)?.permissionIdList || [],
childRoleIdList: [...formModel.childRoleIdList]
}, isCreateMode.value);
Toast({
theme: "success",
direction: "row",
message: "角色已保存"
});
await router.push(isCreateMode.value ? "/management/permissions/roles" : `/management/permissions/roles/${role?.id || formModel.id}`);
}
onMounted(async () => {
await fillForm();
});
</script>
<style scoped lang="less">
.role-edit {
padding: calc(var(--app-nav-height) + 1rem) 0 5rem 0;
.form {
border-radius: .75rem;
}
.textarea {
width: 100%;
}
.children {
gap: .75rem;
display: flex;
padding: 1rem;
flex-direction: column;
.title {
gap: .25rem;
display: flex;
flex-direction: column;
span:first-child {
font-weight: 700;
}
.hint {
color: #52607a;
font-size: .8125rem;
}
}
.group {
--td-checkbox-vertical-padding: 10px;
background: #FFF;
border-radius: 1rem;
.item:not(:last-child)::after {
content: ' ';
left: 16px;
right: 0;
bottom: 0;
position: absolute;
box-sizing: border-box;
border-bottom: 1px solid var(--td-component-stroke, var(--td-gray-color-3, #e7e7e7));
pointer-events: none;
-webkit-box-sizing: border-box;
}
}
}
.save {
left: 1rem;
right: 1rem;
bottom: calc(.75rem + env(safe-area-inset-bottom, 0));
position: fixed;
}
}
:global(html.theme-dark) {
.role-edit {
.children {
.title .hint {
color: #94a3b8;
}
.group .card {
color: #e2e8f0;
background: rgba(15, 23, 42, .72);
border-color: rgba(148, 163, 184, .16);
}
}
}
}
</style>