Compare commits

...
2 Commits
Author SHA1 Message Date
bestlee 2908a10ee5 Merge branch 'master' of https://git.djxinxi.net/bestlee/MOC
# Conflicts:
#	src/service/api/role.ts
#	src/views/my/initiateChange/index.vue
#	src/views/systemManage/role/index.vue
#	src/views/systemManage/user/index.vue
2026-08-26 10:21:08 +08:00
bestlee 4433cf521b 角色编辑接口完成 2026-08-26 10:14:55 +08:00
5 changed files with 2603 additions and 2633 deletions
+4 -9
View File
@@ -7,18 +7,13 @@ export function roleListApi() {
return request({ url: '/api/role' });
}
/**
* 登录
* 编辑角色
*
* @param username User name
* @param password Password
*/
export function fetchLogin(username: string, password: string) {
export function editRoleApi(params: { id: number, intro: string, name: string, perms: string[] }) {
return request({
url: '/api/auth/login',
url: '/api/role',
method: 'post',
data: {
username,
password
}
data: params
});
}
+19
View File
@@ -0,0 +1,19 @@
<script setup lang="ts">
const props = defineProps<{ status: any }>();
const BIG_STAGES = ["申请审批", "实施与关闭", "变更关闭"];
const bigStageOf = (s: any) => (s === "审批中" ? 0 : s === "已关闭" ? 2 : 1);
const cur = bigStageOf(props.status);
const pct = ((cur + 1) / BIG_STAGES.length) * 100;
const size = 34, stroke = 4, r = (size - stroke) / 2, c = 2 * Math.PI * r;
const title = `阶段进度 ${cur + 1}/${BIG_STAGES.length}${BIG_STAGES.slice(0, cur + 1).join(" → ")}${cur < BIG_STAGES.length - 1 ? " → …" : ""}`;
</script>
<template>
<span class="relative inline-flex shrink-0 items-center justify-center" :style="{ width: size + 'px', height: size + 'px' }" :title="title">
<svg :width="size" :height="size" class="-rotate-90">
<circle :cx="size / 2" :cy="size / 2" :r="r" stroke="#E2E8F0" :stroke-width="stroke" fill="none" />
<circle :cx="size / 2" :cy="size / 2" :r="r" stroke="#2080f0" :stroke-width="stroke" fill="none"
:stroke-dasharray="c" :stroke-dashoffset="c * (1 - pct / 100)" stroke-linecap="round" />
</svg>
<span class="absolute inset-0 flex items-center justify-center text-[9px] font-bold text-[#2080f0] dark:text-white">{{ cur + 1 }}/3</span>
</span>
</template>
+2 -2
View File
@@ -7,8 +7,8 @@ import {
countOpenStatus, type ChangeLevel, type ChangeOrder, type ChangeStatus, type ChangeType,
} from "@/typings/model";
import { getColorWithOpacity } from "@/utils/common";
import HighlightText from "@/views/home/modules/HighlightText.vue";
import Ed from "@/views/home/modules/Ed.vue";
import HighlightText from "@/views/my/modules/HighlightText.vue";
import Ed from "@/views/my/modules/Ed.vue";
const themeStore = useThemeStore();
+36 -80
View File
@@ -4,8 +4,8 @@ import { useAppStore } from '@/store/modules/app';
import { Icon } from '@iconify/vue'
import { useThemeStore } from '@/store/modules/theme';
import { useRouter } from 'vue-router';
import { NButton, NPopconfirm } from 'naive-ui';
import { roleListApi } from '@/service/api/role';
import { NButton } from 'naive-ui';
import { roleListApi, editRoleApi } from '@/service/api/role';
const router = useRouter();
const appStore = useAppStore();
@@ -14,11 +14,12 @@ const gap = computed(() => (appStore.isMobile ? 0 : 16));
const loading = ref<boolean>(false);
const btnLoading = ref<boolean>(false);
const currentType = ref<string>('add');
const formRef = ref<any>(null);
const currentRole = ref<{ id: number, name: string }>({
const currentRole = ref<{ id: number, intro: string, name: string, perms: string[] }>({
id: 0,
intro: '',
name: '',
perms: [],
});
const rules = ref({
name: { required: true, message: '角色名称不能为空', trigger: ['blur'] }
@@ -72,30 +73,6 @@ const columns = ref([
// 渲染按钮文本
default: () => '编辑'
}),
h(NPopconfirm, {
// 组件 Props
positiveText: '确定',
negativeText: '取消',
onPositiveClick: () => {
handleDelete(row)
},
// 可选:自定义确认/取消按钮的样式
positiveButtonProps: { size: 'tiny', type: 'primary' },
negativeButtonProps: { size: 'tiny' }
}, {
// 插槽 (Slots)
trigger: () => h(NButton,
{
text: true,
size: 'tiny',
type: 'error',
},
{
default: () => '删除' // 按钮文字
}
),
default: () => '确定要删除吗?' // 弹出框的提示内容
}),
]
})
}
@@ -114,66 +91,46 @@ const getList = async () => {
}
}
// 打开添加角色弹框
const addRole = () => {
currentType.value = 'add';
currentRole.value = {
id: 0,
name: '',
};
roleModal.value = true;
}
// 设置权限
const handleSetPermission = (row: any) => {
currentRole.value = {
id: row.id,
name: row.name,
};
currentRole.value = JSON.parse(JSON.stringify(row));
permissionModal.value = true;
}
// 编辑角色
const handleEdit = (row: any) => {
currentType.value = 'edit';
currentRole.value = {
id: row.id,
name: row.name,
};
currentRole.value = JSON.parse(JSON.stringify(row));
roleModal.value = true;
}
// 删除角色
const handleDelete = (row: any) => {
loading.value = true;
setTimeout(() => {
loading.value = false;
list.value = list.value.filter((item: any) => item.id !== row.id);
window.$message?.success('删除成功')
}, 1000)
}
// 保存角色
const saveRole = async (e: MouseEvent) => {
const saveRole = (e: MouseEvent) => {
e.preventDefault()
formRef.value?.validate((errors: any) => {
formRef.value?.validate(async (errors: any) => {
if (!errors) {
btnLoading.value = true;
setTimeout(() => {
// 新增
if(currentType.value === 'add'){
list.value.push({id:list.value.length+1,name:currentRole.value?.name})
}
// 编辑
if(currentType.value === 'edit'){
const target = list.value.find((item:any) => item.id === currentRole.value.id);
if (target) {
target.name = currentRole.value?.name;
}
try {
await editRoleApi(currentRole.value);
const target = list.value.find((item:any) => item.id === currentRole.value.id);
if (target) {
target.name = currentRole.value.name;
}
window.$message?.success('操作成功')
btnLoading.value = false;
roleModal.value = false;
}, 1000)
} finally {
btnLoading.value = false;
}
}
})
}
// 保存权限
const savePermission = async () => {
btnLoading.value = true;
setTimeout(() => {
window.$message?.success('操作成功')
btnLoading.value = false;
permissionModal.value = false;
}, 1000)
}
onMounted(() => {
const allRoutes = router.getRoutes();
@@ -186,20 +143,14 @@ onMounted(() => {
<!-- 角色管理 -->
<NCard :bordered="false" size="small" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<div class="border mb-3 py-2 px-3" :style="{ borderRadius: themeStore.themeRadius + 'px' }">
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:12 m:12">
<NGrid :x-gap="gap" :y-gap="16" responsive="screen" item-responsive>
<NGi span="24 s:24 m:24">
<div class="h-100% flex items-center gap-2">
<Icon icon="lucide:user" class="size-16px" :style="{ color: themeStore.themeColor }" />
<p class="text-[16px] font-600">角色管理</p>
</div>
</NGi>
<NGi span="24 s:12 m:12" class="flex items-center justify-end gap-12px">
<NButton type="primary" size="small" @click="addRole">
<Icon icon="ic:round-plus" class="size-16px" />
添加角色
</NButton>
</NGi>
</NGrid>
</NGrid>
</div>
<div class="scroll">
<NDataTable
@@ -216,7 +167,7 @@ onMounted(() => {
<NModal
v-model:show="roleModal"
preset="card"
:title="currentType === 'add' ? '新增角色' : '编辑角色'"
title="编辑角色"
:auto-focus="false"
:style="{ width: '450px', height: 'auto' }"
:segmented="{ content: true, footer: true }"
@@ -241,7 +192,12 @@ onMounted(() => {
<!-- 设置权限抽屉 -->
<NDrawer v-model:show="permissionModal" :width="502" placement="right">
<NDrawerContent :title="`设置权限-${currentRole.name}`" closable>
<template #footer>
<div class="flex justify-end gap-[10px]">
<NButton @click="permissionModal = false">取消</NButton>
<NButton type="primary" :loading="btnLoading" @click="savePermission">保存</NButton>
</div>
</template>
</NDrawerContent>
</NDrawer>
</NCard>
+1 -1
View File
@@ -546,7 +546,7 @@ onMounted(() => {
/>
</div>
<p class="mt-2 border-t pt-2 text-[11px] leading-4 text-slate-400">
点击层级查看该层级全员名录右键悬停 ···可编辑添加子级删除
点击层级查看该层级全员名录右键或点 ···可编辑添加子级删除
</p>
</div>
<div class="flex-1">