feat: 添加角色和权限页面
parent
6ce573fda7
commit
9096d4d71d
2
.env
2
.env
|
|
@ -24,7 +24,7 @@ VITE_API_BASE_URL = http://127.0.0.1:3030
|
|||
VITE_API_PROXY_URL = /api
|
||||
|
||||
# API文档地址(开发环境) 备注:需为openapi规范的json文件
|
||||
VITE_API_DOCS_URL = https://petstore.swagger.io/v2/swagger.json
|
||||
VITE_API_DOCS_URL = http://127.0.0.1:3030/openapi.json
|
||||
|
||||
# 端口号(开发环境)
|
||||
VITE_DEV_PORT = 3020
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -90,7 +90,7 @@ export const FormModal = defineComponent({
|
|||
try {
|
||||
const model = formRef.value?.getModel() || {};
|
||||
const res = await props.submit?.({ items: props.items, model });
|
||||
res?.message && Message.success(`提示: ${res.message}`);
|
||||
res?.data?.message && Message.success(`提示: ${res.data.message}`);
|
||||
emit("submited", res);
|
||||
} catch (error: any) {
|
||||
error.message && Message.error(`提示: ${error.message}`);
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ const initOptions = ({ item, model }: any) => {
|
|||
const fetchData = item.options;
|
||||
item._updateOptions = async () => {
|
||||
let data = await fetchData({ item, model });
|
||||
if (Array.isArray(data?.data)) {
|
||||
data = data.data.map((i: any) => ({ label: i.name, value: i.id }));
|
||||
if (Array.isArray(data?.data?.data)) {
|
||||
data = data.data.data.map((i: any) => ({ label: i.name, value: i.id }));
|
||||
}
|
||||
if (Array.isArray(data)) {
|
||||
item.nodeProps.options.splice(0);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ export const Form = defineComponent({
|
|||
props.items.forEach((item: any) => {
|
||||
const node = nodeMap[item.type as NodeType];
|
||||
defaultsDeep(item, { nodeProps: node?.nodeProps ?? {} });
|
||||
(node as any).init?.({ item, model: props.model });
|
||||
(node as any)?.init?.({ item, model: props.model });
|
||||
});
|
||||
|
||||
const getItem = (field: string) => {
|
||||
|
|
|
|||
|
|
@ -97,11 +97,10 @@ export const Table = defineComponent({
|
|||
try {
|
||||
loading.value = true;
|
||||
const resData = await props.data(model, paging);
|
||||
const { data = [], meta = {} } = resData || {};
|
||||
const { page: pageNum, total } = meta;
|
||||
const { data = [], total = 0 } = resData?.data || {};
|
||||
renderData.value = data;
|
||||
props.pagination.total = total;
|
||||
props.pagination.current = pageNum;
|
||||
props.pagination.current = paging.page;
|
||||
} catch (error) {
|
||||
console.log("table error", error);
|
||||
} finally {
|
||||
|
|
@ -160,9 +159,9 @@ export const Table = defineComponent({
|
|||
|
||||
<div class={`mb-2 flex justify-between ${!this.inlined && "mt-2"}`}>
|
||||
<div class="flex-1 flex gap-2">
|
||||
{this.create && <FormModal ref="createRef" onOk={this.reloadData} {...(this.create as any)}></FormModal>}
|
||||
{this.create && <FormModal ref="createRef" onSubmited={this.reloadData} {...(this.create as any)}></FormModal>}
|
||||
{this.modify && (
|
||||
<FormModal ref="modifyRef" onOk={this.reloadData} trigger={false} {...(this.modify as any)}></FormModal>
|
||||
<FormModal ref="modifyRef" onSubmited={this.reloadData} trigger={false} {...(this.modify as any)}></FormModal>
|
||||
)}
|
||||
{this.$slots.action?.()}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ type ExtendableFormItem = (
|
|||
/**
|
||||
* 继承common.items中指定field值的项
|
||||
*/
|
||||
extend: string;
|
||||
extend?: string;
|
||||
} & Partial<IFormItem>)
|
||||
| IFormItem
|
||||
)[];
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Link, Message, Modal, TableColumnData } from "@arco-design/web-vue";
|
||||
import { defaultsDeep, isArray, isFunction, mergeWith } from "lodash-es";
|
||||
import { reactive } from "vue";
|
||||
import { useFormModal } from "../form";
|
||||
import { TableInstance } from "./table";
|
||||
import { config } from "./table.config";
|
||||
import { UseTableOptions } from "./use-interface";
|
||||
|
|
@ -125,14 +126,14 @@ export const useTable = (optionsOrFn: UseTableOptions | (() => UseTableOptions))
|
|||
* 新增表单处理
|
||||
*/
|
||||
if (options.create && propTruly(options.create, "extend")) {
|
||||
options.create = merge(options.common, options.create);
|
||||
options.create = useFormModal(merge(options.common, options.create)) as any;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改表单处理
|
||||
*/
|
||||
if (options.modify && propTruly(options.modify, "extend")) {
|
||||
options.modify = merge(options.common, options.modify);
|
||||
options.modify = useFormModal(merge(options.common, options.modify)) as any;
|
||||
}
|
||||
|
||||
return reactive({ ...options, columns });
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
<template>
|
||||
<BreadPage>
|
||||
<Table v-bind="table"></Table>
|
||||
</BreadPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { api } from "@/api";
|
||||
import { Table, useTable } from "@/components";
|
||||
import { dayjs } from "@/plugins";
|
||||
|
||||
const table = useTable({
|
||||
data: async (model, paging) => {
|
||||
return api.permission.getPermissions();
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "index",
|
||||
},
|
||||
{
|
||||
title: "权限名称",
|
||||
dataIndex: "username",
|
||||
width: 200,
|
||||
render({ record }) {
|
||||
return (
|
||||
<div class="flex flex-col overflow-hidden">
|
||||
<span>{record.name}</span>
|
||||
<span class="text-gray-400 text-xs truncate">标识:{record.slug}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "权限描述",
|
||||
dataIndex: "description",
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdAt",
|
||||
width: 200,
|
||||
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
type: "button",
|
||||
width: 70,
|
||||
buttons: [
|
||||
{
|
||||
type: "modify",
|
||||
text: "修改",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
common: {
|
||||
items: [
|
||||
{
|
||||
field: "name",
|
||||
label: "角色名称",
|
||||
type: "input",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: "slug",
|
||||
label: "角色标识",
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
field: "description",
|
||||
label: "个人描述",
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
field: "permissions",
|
||||
label: "关联角色",
|
||||
type: "select",
|
||||
options: () => api.permission.getPermissions(),
|
||||
component: ({ item }) => {
|
||||
return (
|
||||
<div class="flex flex-col">
|
||||
<span>关联角色</span>
|
||||
<div>
|
||||
<span></span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
},
|
||||
],
|
||||
modalProps: {
|
||||
width: 580,
|
||||
maskClosable: false,
|
||||
},
|
||||
formProps: {
|
||||
layout: "vertical",
|
||||
},
|
||||
},
|
||||
search: {
|
||||
items: [
|
||||
{
|
||||
field: "name",
|
||||
label: "权限名称",
|
||||
type: "input",
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
create: {
|
||||
title: "添加权限",
|
||||
submit: ({ model }) => {
|
||||
return api.permission.addPermission(model as any);
|
||||
},
|
||||
},
|
||||
modify: {
|
||||
title: "修改权限",
|
||||
submit: ({ model }) => {
|
||||
return api.permission.updatePermission(model.id, model);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"sort": 10303,
|
||||
"title": "权限管理",
|
||||
"icon": "icon-park-outline-permissions"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"sort": 10401,
|
||||
"sort": 10300,
|
||||
"title": "文章管理",
|
||||
"icon": "icon-park-outline-document-folder"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
<template>
|
||||
<BreadPage>
|
||||
<Table v-bind="table"></Table>
|
||||
</BreadPage>
|
||||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { api } from "@/api";
|
||||
import { Table, useTable } from "@/components";
|
||||
import { dayjs } from "@/plugins";
|
||||
|
||||
const table = useTable({
|
||||
data: async (model, paging) => {
|
||||
return api.role.getRoles();
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "index",
|
||||
},
|
||||
{
|
||||
title: "角色名称",
|
||||
dataIndex: "username",
|
||||
width: 200,
|
||||
render({ record }) {
|
||||
return (
|
||||
<div class="flex flex-col overflow-hidden">
|
||||
<span>{record.name}</span>
|
||||
<span class="text-gray-400 text-xs truncate">标识:{record.slug}</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "角色描述",
|
||||
dataIndex: "description",
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdAt",
|
||||
width: 200,
|
||||
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
type: "button",
|
||||
width: 70,
|
||||
buttons: [
|
||||
{
|
||||
type: "modify",
|
||||
text: "修改",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
common: {
|
||||
items: [
|
||||
{
|
||||
field: "name",
|
||||
label: "角色名称",
|
||||
type: "input",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: "slug",
|
||||
label: "角色标识",
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
field: "description",
|
||||
label: "个人描述",
|
||||
type: "textarea",
|
||||
},
|
||||
{
|
||||
field: "permissions",
|
||||
label: "关联角色",
|
||||
type: "select",
|
||||
options: () => api.permission.getPermissions(),
|
||||
},
|
||||
],
|
||||
modalProps: {
|
||||
width: 580,
|
||||
maskClosable: false,
|
||||
},
|
||||
formProps: {
|
||||
layout: "vertical",
|
||||
},
|
||||
},
|
||||
search: {
|
||||
items: [
|
||||
{
|
||||
field: "name",
|
||||
label: "角色名称",
|
||||
type: "input",
|
||||
required: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
create: {
|
||||
title: "新建角色",
|
||||
submit: ({ model }) => {
|
||||
return api.role.addRole(model as any);
|
||||
},
|
||||
},
|
||||
modify: {
|
||||
title: "修改角色",
|
||||
submit: ({ model }) => {
|
||||
return api.role.updateRole(model.id, model);
|
||||
},
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
|
||||
<route lang="json">
|
||||
{
|
||||
"meta": {
|
||||
"sort": 10302,
|
||||
"title": "角色管理",
|
||||
"icon": "icon-park-outline-key"
|
||||
}
|
||||
}
|
||||
</route>
|
||||
|
|
@ -5,27 +5,50 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="tsx">
|
||||
import { api } from "@/api";
|
||||
import { Table, useTable } from "@/components";
|
||||
import { dayjs } from "@/plugins";
|
||||
import { Avatar } from "@arco-design/web-vue";
|
||||
|
||||
const table = useTable({
|
||||
data: async (model, paging) => ({ data: [{}], meta: { total: 0 } }),
|
||||
data: async (model, paging) => {
|
||||
return api.user.getUsers({ ...model, ...paging });
|
||||
},
|
||||
columns: [
|
||||
{
|
||||
type: "index",
|
||||
},
|
||||
{
|
||||
title: "姓名",
|
||||
title: "用户昵称",
|
||||
dataIndex: "username",
|
||||
width: 200,
|
||||
render({ record }) {
|
||||
return (
|
||||
<div class="flex items-center">
|
||||
<Avatar size={32}>
|
||||
<img src={record.avatar} alt="" />
|
||||
</Avatar>
|
||||
<span class="ml-2 flex-1 flex flex-col overflow-hidden">
|
||||
<span>{record.nickname}</span>
|
||||
<span class="text-gray-400 text-xs truncate">账号:{record.username}</span>
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "昵称",
|
||||
dataIndex: "name",
|
||||
title: "用户描述",
|
||||
dataIndex: "description",
|
||||
},
|
||||
{
|
||||
title: "用户邮箱",
|
||||
dataIndex: "email",
|
||||
},
|
||||
{
|
||||
title: "创建时间",
|
||||
dataIndex: "createdAt",
|
||||
width: 200,
|
||||
render: ({ record }) => dayjs(record.createdAt).format(),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
|
|
@ -46,13 +69,13 @@ const table = useTable({
|
|||
items: [
|
||||
{
|
||||
field: "username",
|
||||
label: "姓名1",
|
||||
label: "登录账号",
|
||||
type: "input",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
field: "nickname",
|
||||
label: "昵称",
|
||||
label: "用户昵称",
|
||||
type: "input",
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue