This commit is contained in:
wang_yp 2025-04-08 12:24:31 +08:00
parent 81d5e6a9d1
commit fcf7e37404
19 changed files with 352 additions and 109 deletions

View File

@ -24,7 +24,7 @@ const LayOut = (props: Store) => {
}; };
const logoStyle = { width: 60, color: "white" }; const logoStyle = { width: 60, color: "white" };
const contentstyle = { const contentstyle = {
padding: 12, padding: "12px 0px 12px 12px",
margin: 0, margin: 0,
minHeight: 280, minHeight: 280,
background: colorBgContainer, background: colorBgContainer,
@ -45,7 +45,7 @@ const LayOut = (props: Store) => {
return ( return (
<Layout> <Layout>
<Header style={headStyle}> <Header style={headStyle}>
<div style={logoStyle}>logo</div> <div style={logoStyle}></div>
<Dropdown menu={{ items: headItems,selectable: true, onClick: (e) => { <Dropdown menu={{ items: headItems,selectable: true, onClick: (e) => {
console.log(e.key==="loginout") console.log(e.key==="loginout")
if (e.key==="loginout"){ if (e.key==="loginout"){

View File

@ -14,18 +14,20 @@ export const items = [
children: [{ label: "数据管理", key: "/source/list" }], children: [{ label: "数据管理", key: "/source/list" }],
}, },
{ {
key: "/permission", key: "/permi",
label: `权限管理`, label: `权限管理`,
children: [ children: [
{ label: `角色管理`, key: "/permission/role" }, { label: `权限管理`, key: "/permi/permi" },
{ label: `菜单管理`, key: "/permission/menu" }, { label: `角色管理`, key: "/permi/role" },
{ label: `菜单管理`, key: "/permi/menu" },
{ label: `部门管理`, key: "/permi/dep" }
], ],
}, },
{ // {
key: "/sys", // key: "/sys",
label: `系统管理`, // label: `系统管理`,
children: [{ label: `部门管理`, key: "/dep" }], // children: [],
}, // },
]; ];
export const headItems = [ export const headItems = [

View File

@ -1,4 +1,4 @@
import { Button, Space } from "antd"; import { Space } from "antd";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import { Store } from "antd/lib/form/interface"; import { Store } from "antd/lib/form/interface";
import React from "react"; import React from "react";
@ -8,9 +8,7 @@ const Dashbord = (props: Store) => {
return ( return (
<div className="contentBox"> <div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}> <Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="primary" onClick={() => props.usrStore.getUserList()}>
</Button>
</Space> </Space>
</div> </div>
); );

50
src/pages/dep/index.tsx Normal file
View File

@ -0,0 +1,50 @@
import { Button, Space, Modal, FormInstance } from "antd";
import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface";
import React from "react";
import { columns } from "./permission_config";
import "./permission.less";
const Dep = (props: Store) => {
const { usrStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
useEffect(() => {}, []);
const addHandler = () => {};
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="default" onClick={() => addHandler()}>
</Button>
<BTable
store={usrStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
/>
<Modal
title={!userId ? "添加权限" : "编辑权限"}
width={800}
open={isModalOpen}
afterClose={() => formRef.current?.resetFields()}
onOk={() => formRef.current?.submit()}
okText="确定"
cancelText="取消"
onCancel={() => {
setId(null);
setIsModalOpen(false);
}}
></Modal>
</Space>
</div>
);
};
export default inject("usrStore")(observer(Dep));

View File

@ -0,0 +1,8 @@
.contentBox{
overflow-y: auto;
height: 100%;
.tableName{
height: 100%;
overflow-y: auto;
}
}

View File

@ -0,0 +1,97 @@
import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table";
import { Image } from "antd";
import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [
{
type: FormType.input,
label: "用户名",
name: "user_name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],
},
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{
type: FormType.input,
label: "身份证",
name: "id_card",
value: "",
rules: [{ required: true, message: "请输入身份证" }],
},
{
type: FormType.input,
label: "登录账号",
name: "account",
value: "",
rules: [{ required: true, message: "请输入登录账号" }],
},
{
type: FormType.input,
label: "联系电话",
name: "tel",
value: "",
},
{
type: FormType.input,
label: "邮箱",
name: "email",
value: "",
},
{
type: FormType.upload,
label: "头像",
name: "head_img",
value: [],
},
];
export const columns: ColumnsType<UserDataType> = [
{
title: "用户名",
dataIndex: "user_name",
width: 200,
fixed: "left",
},
{
title: "性别",
width: 150,
render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span>
),
},
{
title: "头像",
dataIndex: "head_img",
width: 150,
render: (head_img) => {
return <Image src={head_img}></Image>;
},
},
{
title: "登录账号",
width: 150,
dataIndex: "account",
},
{
title: "身份证",
width: 150,
dataIndex: "id_card",
},
{
title: "联系电话",
width: 150,
dataIndex: "tel",
},
];

View File

@ -8,7 +8,7 @@ import { columns } from "./menu_config";
import "./menu.less"; import "./menu.less";
const Menu = (props: Store) => { const Menu = (props: Store) => {
const { usrStore } = props; const { menuStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null); const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null); const [userId, setId] = useState<Number | null>(null);
@ -23,10 +23,10 @@ const Menu = (props: Store) => {
</Button> </Button>
<BTable <BTable
store={usrStore} store={menuStore}
scroll={{ x: "max-content" }} scroll={{ x: "max-content" }}
columns={columns} columns={columns}
dataSource={usrStore.list} dataSource={menuStore.list}
/> />
<Modal <Modal
@ -47,4 +47,4 @@ const Menu = (props: Store) => {
); );
}; };
export default inject("usrStore")(observer(Menu)); export default inject("menuStore")(observer(Menu));

View File

@ -6,92 +6,46 @@ import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [ export const defaultConfig = (team, per) => [
{ {
type: FormType.input, type: FormType.input,
label: "用户名", label: "菜单名称",
name: "user_name", name: "name",
value: "", value: "",
rules: [{ required: true, message: "请输入用户名称!" }], rules: [{ required: true, message: "请输入名称!" }],
}, },
{ {
type: FormType.inputNumber, type: FormType.inputNumber,
label: "年龄", label: "icon",
name: "age", name: "icon",
value: "", value: "",
rules: [{ required: true, message: "请输入年龄" }], rules: [{ required: true, message: "请输入年龄" }],
}, },
{ {
type: FormType.input, type: FormType.input,
label: "身份证", label: "路径",
name: "id_card", name: "id_card",
value: "", value: "",
rules: [{ required: true, message: "请输入身份证" }], rules: [{ required: true, message: "请输入身份证" }],
}, },
{
type: FormType.input,
label: "登录账号",
name: "account",
value: "",
rules: [{ required: true, message: "请输入登录账号" }],
},
{
type: FormType.input,
label: "联系电话",
name: "tel",
value: "",
},
{
type: FormType.input,
label: "邮箱",
name: "email",
value: "",
},
{
type: FormType.upload,
label: "头像",
name: "head_img",
value: [],
},
]; ];
export const columns: ColumnsType<UserDataType> = [ export const columns: ColumnsType<UserDataType> = [
{ {
title: "用户名", title: "菜单名称",
dataIndex: "user_name", dataIndex: "name",
width: 200,
fixed: "left", fixed: "left",
}, },
{ {
title: "性别", title: "icon图标",
width: 150,
render: (render) => ( render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span> <span>{getBirthDateAndGender(render.id_card)?.gender}</span>
), ),
}, },
{ {
title: "头像", title: "路径",
dataIndex: "head_img", dataIndex: "head_img",
width: 150,
render: (head_img) => { render: (head_img) => {
return <Image src={head_img}></Image>; return <Image src={head_img}></Image>;
}, },
}, },
{
title: "登录账号",
width: 150,
dataIndex: "account",
},
{
title: "身份证",
width: 150,
dataIndex: "id_card",
},
{
title: "联系电话",
width: 150,
dataIndex: "tel",
},
]; ];

View File

@ -8,7 +8,7 @@ import { columns } from "./role_config";
import "./role.less"; import "./role.less";
const Role = (props: Store) => { const Role = (props: Store) => {
const { usrStore } = props; const { roleStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false); const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null); const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null); const [userId, setId] = useState<Number | null>(null);
@ -23,10 +23,10 @@ const Role = (props: Store) => {
</Button> </Button>
<BTable <BTable
store={usrStore} store={roleStore}
scroll={{ x: "max-content" }} scroll={{ x: "max-content" }}
columns={columns} columns={columns}
dataSource={usrStore.list} dataSource={roleStore.list}
/> />
<Modal <Modal
@ -47,4 +47,4 @@ const Role = (props: Store) => {
); );
}; };
export default inject("usrStore")(observer(Role)); export default inject("roleStore")(observer(Role));

View File

@ -6,7 +6,7 @@ import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [ export const defaultConfig = (team, per) => [
{ {
type: FormType.input, type: FormType.input,
label: "用户名", label: "角色名称",
name: "user_name", name: "user_name",
value: "", value: "",
rules: [{ required: true, message: "请输入用户名称!" }], rules: [{ required: true, message: "请输入用户名称!" }],

View File

@ -4,7 +4,6 @@ import {
Checkbox, Checkbox,
Form, Form,
Input, Input,
message,
PaginationProps, PaginationProps,
Popconfirm, Popconfirm,
Space, Space,
@ -16,16 +15,30 @@ import { inject, observer } from "mobx-react";
import "./source.less"; import "./source.less";
import { DataType } from "@/util/model/interface"; import { DataType } from "@/util/model/interface";
import Upload from "./upload"; import Upload from "./upload";
import toExcel from "@/util/xmsx";
const Source = (props: Store) => { const Source = (props: Store) => {
const { sourceStore } = props; const { sourceStore } = props;
const [form] = Form.useForm(); const [form] = Form.useForm();
const [coloums, setColumns] = useState<any>([]); const [coloums, setColumns] = useState<any>([]);
const [content, setContent] = useState([]); const [content, setContent] = useState([]);
const [selectKey, setSelectKey] = useState<Array<string>>([]); const [selectKey, setSelectKey] = useState<Array<string>>([
"01JM4XMY2N9KN23XSZJSQQM3HY",
"01JM4XMY2N9KN23XSZJSWQHHKA",
"01JM4XMY2N9KN23XSZJW02PRCF",
"01JM4XMY2N9KN23XSZJYCKT6XQ",
"01JM4XMY2N9KN23XSZK0AJ6QEZ",
"01JM4XMY2N9KN23XSZK10KM59Y",
"01JM4XMY2N9KN23XSZK479Y59M",
"01JM4XMY2N9KN23XSZK5F8Z2J8",
"01JM4XMY2N9KN23XSZK6W7Q25F",
"01JM4XMY2N9KN23XSZK7ET1GEB",
"01JM4XMY2N9KN23XSZK9DNRCZZ",
]);
const [page, setPage] = useState<number>(1); const [page, setPage] = useState<number>(1);
const [editingKey, setEditingKey] = useState(""); const [editingKey, setEditingKey] = useState("");
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [rowKeys, setRowKeys] = useState<any[]>([]);
const isEditing = (record) => record.key === editingKey; const isEditing = (record) => record.key === editingKey;
const edit = (record: any) => { const edit = (record: any) => {
form.setFieldsValue({ ...record }); form.setFieldsValue({ ...record });
@ -66,17 +79,33 @@ const Source = (props: Store) => {
} }
}; };
const getContent = (list, index) => { const getContent = (list, index) => {
setLoading(true);
sourceStore.geContent(list, index, 20).then((res) => { sourceStore.geContent(list, index, 20).then((res) => {
res.forEach((element) => { res.forEach((element) => {
element.key = "dbs_" + element.identity; element.key = "dbs_" + element.identity;
}); });
setContent(res); setContent(res);
setLoading(false);
}); });
}; };
const getHead = () => {
let head = coloums.filter((value) => selectKey.includes(value.identity));
console.log(head);
return head;
};
const saveClo = () => { const saveClo = () => {
if (selectKey.length === 0) { let list: any = [];
message.info("请勾选需要收藏的数据"); for (let i = 0; i < rowKeys.length; i++) {
let obj = {};
for (const key in rowKeys[i]) {
if (key.indexOf("dbs") > -1) {
obj[key] = rowKeys[i][key];
}
}
list.push(obj);
} }
toExcel(getHead(), list, "test.xlsx", "Sheet1");
}; };
const cancel = () => { const cancel = () => {
setEditingKey(""); setEditingKey("");
@ -115,7 +144,7 @@ const Source = (props: Store) => {
> >
</Typography.Link> </Typography.Link>
<Popconfirm {/* <Popconfirm
title="删除确认" title="删除确认"
description="您是否需要删除该数据?" description="您是否需要删除该数据?"
onConfirm={() => { onConfirm={() => {
@ -127,8 +156,8 @@ const Source = (props: Store) => {
> >
<Button type="dashed" danger size="small"> <Button type="dashed" danger size="small">
</Button> </Button> */}
</Popconfirm> {/* </Popconfirm> */}
</Space> </Space>
); );
}, },
@ -181,6 +210,7 @@ const Source = (props: Store) => {
fixed: true, fixed: true,
onChange: (keys, rowKeys, info) => { onChange: (keys, rowKeys, info) => {
setSelectedRowKeys(keys); setSelectedRowKeys(keys);
setRowKeys(rowKeys);
}, },
}; };
return ( return (
@ -190,25 +220,13 @@ const Source = (props: Store) => {
<Space> <Space>
<Checkbox.Group <Checkbox.Group
options={coloums} options={coloums}
defaultValue={[ defaultValue={selectKey}
"01JM4XMY2N9KN23XSZJSQQM3HY",
"01JM4XMY2N9KN23XSZJSWQHHKA",
"01JM4XMY2N9KN23XSZJW02PRCF",
"01JM4XMY2N9KN23XSZJYCKT6XQ",
"01JM4XMY2N9KN23XSZK0AJ6QEZ",
"01JM4XMY2N9KN23XSZK10KM59Y",
"01JM4XMY2N9KN23XSZK479Y59M",
"01JM4XMY2N9KN23XSZK5F8Z2J8",
"01JM4XMY2N9KN23XSZK6W7Q25F",
"01JM4XMY2N9KN23XSZK7ET1GEB",
"01JM4XMY2N9KN23XSZK9DNRCZZ",
]}
onChange={(v) => { onChange={(v) => {
setSelectKey(v); setSelectKey(v);
getContent(v, 1); getContent(v, 1);
}} }}
/> />
<Button onClick={saveClo}></Button> <Button onClick={saveClo}></Button>
</Space> </Space>
<Form form={form} component={false}> <Form form={form} component={false}>

View File

@ -4,8 +4,9 @@ import Login from "@/pages/login/login";
import User from "@/pages/user/user"; import User from "@/pages/user/user";
import Dashbord from "@/pages/dashbord"; import Dashbord from "@/pages/dashbord";
import Source from "@/pages/source/source"; import Source from "@/pages/source/source";
import Menu from "@/pages/menu/menu"; import Menu from "@/pages/menu";
import Role from "@/pages/role/role"; import Role from "@/pages/role";
import Permission from "@/pages/permission";
const routers = createHashRouter([ const routers = createHashRouter([
{ {
@ -28,12 +29,21 @@ const routers = createHashRouter([
element: <Source />, element: <Source />,
}, },
{ {
path: "/permission/menu", path: "/permi/permi",
index: true,
element: <Permission />,
}, {
path: "/permi/dep",
index: true,
element: <Permission />,
},
{
path: "/permi/menu",
index: true, index: true,
element: <Menu />, element: <Menu />,
}, },
{ {
path: "/permission/role", path: "/permi/role",
index: true, index: true,
element: <Role />, element: <Role />,
}, },

View File

@ -6,4 +6,21 @@ class UserConfig {
static DELETE: string = "/user"; static DELETE: string = "/user";
} }
export default UserConfig;
class RoleConfig {
static ADD: string = "/role";
static EDIT: string = "/role";
static LIST: string = "/role/list";
static DELETE: string = "/role";
}
class MenuConfig {
static ADD: string = "/role";
static EDIT: string = "/role";
static LIST: string = "/role/list";
static DELETE: string = "/role";
}
export { RoleConfig, UserConfig,MenuConfig };

View File

@ -1,9 +1,13 @@
import usrStore from '@/store/user' import usrStore from '@/store/user'
import sourceStore from '@/store/source'; import sourceStore from '@/store/source';
import roleStore from './role';
import menuStore from './menu';
const store = { const store = {
usrStore, usrStore,
sourceStore sourceStore,
roleStore,
menuStore,
}; };
export default store; export default store;

15
src/store/menu.ts Normal file
View File

@ -0,0 +1,15 @@
import { makeObservable } from "mobx";
import BaseStore from "./baseStore";
import { UserDataType } from "@/model/userModel";
import { RoleConfig } from "@/service/user_config";
class MenuStore extends BaseStore<UserDataType> {
constructor() {
super(RoleConfig)
makeObservable(this, {
})
}
}
const menuStore = new MenuStore();
export default menuStore;

15
src/store/role.ts Normal file
View File

@ -0,0 +1,15 @@
import { makeObservable } from "mobx";
import BaseStore from "./baseStore";
import { UserDataType } from "@/model/userModel";
import { RoleConfig } from "@/service/user_config";
class RoleStore extends BaseStore<UserDataType> {
constructor() {
super(RoleConfig)
makeObservable(this, {
})
}
}
const roleStore = new RoleStore();
export default roleStore;

View File

@ -3,7 +3,7 @@ import { base } from "@/service/base";
import BaseStore from "./baseStore"; import BaseStore from "./baseStore";
import { UserDataType, UserInfos } from "@/model/userModel"; import { UserDataType, UserInfos } from "@/model/userModel";
import { message } from "antd"; import { message } from "antd";
import UserConfig from "@/service/user_config"; import { UserConfig } from "@/service/user_config";
class UserStore extends BaseStore<UserDataType> { class UserStore extends BaseStore<UserDataType> {
_userinfo: UserInfos = {}; // 用户信息 _userinfo: UserInfos = {}; // 用户信息

55
src/util/xmsx.ts Normal file
View File

@ -0,0 +1,55 @@
const toHTML = (titles, datas) =>{
// 显示表格边框
var table = '<table border="1" rull="all" style="border-collapse:collapse">';
// header设置行高为32px
table += '<tr style="height:32px">';
// 遍历拼接header行
for (var t = 0; t < titles.length; t++) {
// 设置header行样式为垂直居中、列宽90px、水平居中
table += '<td style="vertical-align:middle;width:90px;text-align:center">' + titles[t].title + '</td>';
}
table += '</tr>';
// body
for (var d = 0; d < datas.length; d++) {
// 设置行高为24px垂直居中水平居中
table += '<tr style="height:24px">';
let h = datas[d]
for (let value in h) {
table += '<td style="vertical-align:middle;text-align:center">' + h[value] + '</td>';
}
table += '</tr>';
}
table += '</table>';
return table;
};
const toExcel =(titles, datas, fileName, sheetName) =>{
/*
1
2
3
3sheet名
*/
var uri = 'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,'
, template = '<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40"><meta http-equiv="content-type" content="application/vnd.ms-excel; charset=UTF-8"><head><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body>{table}</body></html>'
, base64 = function (s) { return window.btoa(unescape(encodeURIComponent(s))) }
, format = function (s, c) { return s.replace(/{(\w+)}/g, function (m, p) { return c[p]; }) }
var table = toHTML(titles, datas);
var ctx = { worksheet: sheetName, table: table };
var data = base64(format(template, ctx));
var alink = document.createElement('a');
alink.append('body')
alink.href = uri + data;
alink.download = fileName;
alink.click();
alink.remove();
};
export default toExcel;
// toExcel("titles", [{}], 'test.xlsx', 'Sheet1');