feat:按钮权限,fix更新角色菜单没过滤关联表状态9的数据问题
This commit is contained in:
parent
aa20898bc8
commit
2ff52ce086
@ -13,7 +13,7 @@ async def get_role_menus(rid: int):
|
|||||||
"""
|
"""
|
||||||
select m.id, m.name, m.meta, m.path, m.type, m.component, m.pid, m.identifier
|
select m.id, m.name, m.meta, m.path, m.type, m.component, m.pid, m.identifier
|
||||||
FROM sys_menu as m, sys_role_menu WHERE m.id = sys_role_menu.mid
|
FROM sys_menu as m, sys_role_menu WHERE m.id = sys_role_menu.mid
|
||||||
AND sys_role_menu.rid = (?) AND m.`status` = 1""",
|
AND sys_role_menu.rid = (?) AND sys_role_menu.`status` = 1""",
|
||||||
[rid],
|
[rid],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,7 +32,20 @@ async def get_user_info(user: UserModel):
|
|||||||
[user.id],
|
[user.id],
|
||||||
)
|
)
|
||||||
|
|
||||||
return {**jsonable_encoder(user), "roles": sql_result}
|
# 当前激活角色的按钮权限列表
|
||||||
|
perm_result = await db.execute_query_dict(
|
||||||
|
"""
|
||||||
|
select m.identifier from sys_role_menu as rm, sys_menu as m where rm.mid = m.id and rm.rid = (?) and
|
||||||
|
m.identifier not null and m.identifier != "" and rm.status != 9
|
||||||
|
""",
|
||||||
|
[sql_result[0]["id"]],
|
||||||
|
)
|
||||||
|
|
||||||
|
return {
|
||||||
|
**jsonable_encoder(user),
|
||||||
|
"roles": sql_result,
|
||||||
|
"permissions": [i["identifier"] for i in perm_result],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async def get_users(skip: int, limit: int, kwargs: dict = None):
|
async def get_users(skip: int, limit: int, kwargs: dict = None):
|
||||||
|
Binary file not shown.
Binary file not shown.
@ -41,6 +41,7 @@ class UserInfo(UserRead):
|
|||||||
"""用户信息模型"""
|
"""用户信息模型"""
|
||||||
|
|
||||||
roles: list[UserHasRole] = Field(..., description="用户拥有角色")
|
roles: list[UserHasRole] = Field(..., description="用户拥有角色")
|
||||||
|
permissions: list[str] = Field(..., description="角色拥有的按钮权限标识")
|
||||||
|
|
||||||
|
|
||||||
class RoleActive(BaseModel):
|
class RoleActive(BaseModel):
|
||||||
|
25
frontend/package-lock.json
generated
25
frontend/package-lock.json
generated
@ -10,6 +10,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^3.2.12",
|
"ant-design-vue": "^3.2.12",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"moment": "^2.29.4",
|
||||||
|
"monent": "^0.0.2-security",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.0.21",
|
"pinia": "^2.0.21",
|
||||||
"pinia-plugin-persistedstate": "^2.2.0",
|
"pinia-plugin-persistedstate": "^2.2.0",
|
||||||
@ -1131,6 +1133,19 @@
|
|||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/moment": {
|
||||||
|
"version": "2.29.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||||
|
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
|
||||||
|
"engines": {
|
||||||
|
"node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/monent": {
|
||||||
|
"version": "0.0.2-security",
|
||||||
|
"resolved": "https://registry.npmjs.org/monent/-/monent-0.0.2-security.tgz",
|
||||||
|
"integrity": "sha512-qghr6SG18OAHdr2emuACuhMJWUi1Yax10+V0N1Fr3ISC921hOtw6g7fuDxdgJszzSGTMFyKiUgBRafpKRrsjkQ=="
|
||||||
|
},
|
||||||
"node_modules/ms": {
|
"node_modules/ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@ -2365,6 +2380,16 @@
|
|||||||
"brace-expansion": "^2.0.1"
|
"brace-expansion": "^2.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"moment": {
|
||||||
|
"version": "2.29.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
|
||||||
|
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
|
||||||
|
},
|
||||||
|
"monent": {
|
||||||
|
"version": "0.0.2-security",
|
||||||
|
"resolved": "https://registry.npmjs.org/monent/-/monent-0.0.2-security.tgz",
|
||||||
|
"integrity": "sha512-qghr6SG18OAHdr2emuACuhMJWUi1Yax10+V0N1Fr3ISC921hOtw6g7fuDxdgJszzSGTMFyKiUgBRafpKRrsjkQ=="
|
||||||
|
},
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ant-design-vue": "^3.2.12",
|
"ant-design-vue": "^3.2.12",
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
|
"moment": "^2.29.4",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
"pinia": "^2.0.21",
|
"pinia": "^2.0.21",
|
||||||
"pinia-plugin-persistedstate": "^2.2.0",
|
"pinia-plugin-persistedstate": "^2.2.0",
|
||||||
|
@ -10,9 +10,10 @@ import "normalize.css";
|
|||||||
import "@/assets/css/base.css";
|
import "@/assets/css/base.css";
|
||||||
|
|
||||||
import "ant-design-vue/dist/antd.css";
|
import "ant-design-vue/dist/antd.css";
|
||||||
|
import hasPermisson from "@/utils/directive";
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
hasPermisson(app);
|
||||||
app.use(store);
|
app.use(store);
|
||||||
|
|
||||||
userStore().loadRoleRouter();
|
userStore().loadRoleRouter();
|
||||||
|
@ -29,3 +29,10 @@ export function selectRole(rid) {
|
|||||||
method: "put",
|
method: "put",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取用户列表
|
||||||
|
export function getUsers() {
|
||||||
|
return request({
|
||||||
|
url: "/user",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
17
frontend/src/utils/directive.js
Normal file
17
frontend/src/utils/directive.js
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { userStore } from "@/stores/user";
|
||||||
|
|
||||||
|
export default (app) => {
|
||||||
|
// 按钮权限
|
||||||
|
app.directive("per", {
|
||||||
|
mounted(el, binding) {
|
||||||
|
console.log(el, binding.value);
|
||||||
|
if (
|
||||||
|
// 是否存在
|
||||||
|
userStore().userInfo.permissions.indexOf(binding.value) === -1
|
||||||
|
) {
|
||||||
|
// 删除元素
|
||||||
|
el.parentNode && el.parentNode.removeChild(el);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
5
frontend/src/utils/format.js
Normal file
5
frontend/src/utils/format.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import moment from "moment";
|
||||||
|
|
||||||
|
export const formatTime = (value) => {
|
||||||
|
return moment(value).format("YYYY-MM-DD HH:mm:ss");
|
||||||
|
};
|
@ -20,7 +20,7 @@ export default (config) => {
|
|||||||
if (res.data.code !== 200) {
|
if (res.data.code !== 200) {
|
||||||
message.error(res.data.msg);
|
message.error(res.data.msg);
|
||||||
}
|
}
|
||||||
|
console.log(res.data);
|
||||||
return res.data;
|
return res.data;
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
|
39
frontend/src/views/main/system/user/conf.js
Normal file
39
frontend/src/views/main/system/user/conf.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// 表格数据列 表头配置
|
||||||
|
export const columns = [
|
||||||
|
{
|
||||||
|
title: "序号",
|
||||||
|
dataIndex: "index",
|
||||||
|
key: "index",
|
||||||
|
align: "center",
|
||||||
|
customRender: ({ text, record, index }) => `${index + 1}`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "用户名",
|
||||||
|
dataIndex: "username",
|
||||||
|
key: "username",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "昵称",
|
||||||
|
dataIndex: "nickname",
|
||||||
|
key: "nickname",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "状态",
|
||||||
|
dataIndex: "status",
|
||||||
|
key: "status",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "创建时间",
|
||||||
|
dataIndex: "created",
|
||||||
|
key: "created",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "更新时间",
|
||||||
|
dataIndex: "modified",
|
||||||
|
key: "modified",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "操作",
|
||||||
|
key: "action",
|
||||||
|
},
|
||||||
|
];
|
@ -1,7 +1,122 @@
|
|||||||
<script setup></script>
|
<script setup>
|
||||||
|
import { getUsers } from "@/service/user";
|
||||||
|
import { columns } from "./conf";
|
||||||
|
import { formatTime } from "@/utils/format";
|
||||||
|
|
||||||
|
import { ref, reactive, onMounted } from "vue";
|
||||||
|
|
||||||
|
import { PlusOutlined, SearchOutlined } from "@ant-design/icons-vue";
|
||||||
|
|
||||||
|
// 列表数据
|
||||||
|
const dataSource = ref([]);
|
||||||
|
|
||||||
|
// 页面展示数据条数变化回调
|
||||||
|
const pageSizeChange = (current, size) => {
|
||||||
|
console.log(current, size, "展示数量变化");
|
||||||
|
};
|
||||||
|
|
||||||
|
// 页码变化回调
|
||||||
|
const pageChange = (page, pageSize) => {
|
||||||
|
console.log(page, pageSize, "页码变化");
|
||||||
|
};
|
||||||
|
|
||||||
|
//分页
|
||||||
|
const pagination = reactive({
|
||||||
|
current: 1, //当前页
|
||||||
|
pageSize: 10, // 每页数量
|
||||||
|
showSizeChanger: true,
|
||||||
|
total: 200,
|
||||||
|
pageSizeOptions: ["10", "50", "100"],
|
||||||
|
showTotal: (total) => `共${total}条数据`,
|
||||||
|
onShowSizeChange: pageSizeChange,
|
||||||
|
onChange: pageChange,
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
getPageData();
|
||||||
|
});
|
||||||
|
|
||||||
|
const getPageData = () => {
|
||||||
|
getUsers().then((res) => {
|
||||||
|
dataSource.value = res.data.items;
|
||||||
|
pagination.total = res.data.total;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>user</div>
|
<div class="user">
|
||||||
|
<!-- 查询 -->
|
||||||
|
<div class="search">
|
||||||
|
<a-form layout="inline">
|
||||||
|
<a-form-item label="用户名">
|
||||||
|
<a-input placeholder="用户名"> </a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="昵称">
|
||||||
|
<a-input placeholder="昵称"> </a-input>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item>
|
||||||
|
<a-button type="primary" v-per="'user:query'">
|
||||||
|
<template #icon> <SearchOutlined /> </template>查询</a-button
|
||||||
|
>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<div class="data">
|
||||||
|
<a-card title="用户列表"
|
||||||
|
><template #extra>
|
||||||
|
<a-button type="primary" v-per="'user:create'">
|
||||||
|
<template #icon><plus-outlined /></template>
|
||||||
|
新增</a-button
|
||||||
|
>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<!-- 数据 -->
|
||||||
|
<a-table
|
||||||
|
:columns="columns"
|
||||||
|
:data-source="dataSource"
|
||||||
|
:pagination="pagination"
|
||||||
|
>
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.key === 'status'">
|
||||||
|
<a-tag :color="record.status !== 9 ? 'green' : 'red'">
|
||||||
|
{{ record.status !== 9 ? "正常" : "已删除" }}
|
||||||
|
</a-tag>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'created'">
|
||||||
|
{{ formatTime(record.created) }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'modified'">
|
||||||
|
{{ formatTime(record.modified) }}
|
||||||
|
</template>
|
||||||
|
<template v-else-if="column.key === 'action'">
|
||||||
|
<span>
|
||||||
|
<a v-pre="'user:update'">修改</a>
|
||||||
|
<a-divider type="vertical" />
|
||||||
|
<template v-if="record.status !== 9">
|
||||||
|
<a v-per="'user:delete'">删除</a>
|
||||||
|
</template>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped>
|
||||||
|
.search {
|
||||||
|
display: flex;
|
||||||
|
/* justify-content: center; */
|
||||||
|
align-content: center;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
padding: 24px;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
.data {
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
Loading…
Reference in New Issue
Block a user