feat:按钮权限,fix更新角色菜单没过滤关联表状态9的数据问题

This commit is contained in:
zy7y 2022-09-14 16:22:39 +08:00
parent aa20898bc8
commit 2ff52ce086
14 changed files with 231 additions and 7 deletions

View File

@ -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],
) )

View File

@ -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.

View File

@ -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):

View File

@ -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",

View File

@ -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",

View File

@ -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();

View File

@ -29,3 +29,10 @@ export function selectRole(rid) {
method: "put", method: "put",
}); });
} }
// 获取用户列表
export function getUsers() {
return request({
url: "/user",
});
}

View 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);
}
},
});
};

View File

@ -0,0 +1,5 @@
import moment from "moment";
export const formatTime = (value) => {
return moment(value).format("YYYY-MM-DD HH:mm:ss");
};

View File

@ -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) => {

View 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",
},
];

View File

@ -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>