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

View File

@ -14,18 +14,20 @@ export const items = [
children: [{ label: "数据管理", key: "/source/list" }],
},
{
key: "/permission",
key: "/permi",
label: `权限管理`,
children: [
{ label: `角色管理`, key: "/permission/role" },
{ label: `菜单管理`, key: "/permission/menu" },
{ label: `权限管理`, key: "/permi/permi" },
{ label: `角色管理`, key: "/permi/role" },
{ label: `菜单管理`, key: "/permi/menu" },
{ label: `部门管理`, key: "/permi/dep" }
],
},
{
key: "/sys",
label: `系统管理`,
children: [{ label: `部门管理`, key: "/dep" }],
},
// {
// key: "/sys",
// label: `系统管理`,
// children: [],
// },
];
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 { Store } from "antd/lib/form/interface";
import React from "react";
@ -8,9 +8,7 @@ const Dashbord = (props: Store) => {
return (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<Button type="primary" onClick={() => props.usrStore.getUserList()}>
</Button>
</Space>
</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";
const Menu = (props: Store) => {
const { usrStore } = props;
const { menuStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
@ -23,10 +23,10 @@ const Menu = (props: Store) => {
</Button>
<BTable
store={usrStore}
store={menuStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
dataSource={menuStore.list}
/>
<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) => [
{
type: FormType.input,
label: "用户名",
name: "user_name",
label: "菜单名称",
name: "name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],
rules: [{ required: true, message: "请输入名称!" }],
},
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
label: "icon",
name: "icon",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{
type: FormType.input,
label: "身份证",
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,
title: "菜单名称",
dataIndex: "name",
fixed: "left",
},
{
title: "性别",
width: 150,
title: "icon图标",
render: (render) => (
<span>{getBirthDateAndGender(render.id_card)?.gender}</span>
),
},
{
title: "头像",
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 "./role_config";
import "./role.less";
const Role = (props: Store) => {
const { usrStore } = props;
const { roleStore } = props;
const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
const formRef = React.useRef<FormInstance>(null);
const [userId, setId] = useState<Number | null>(null);
@ -23,10 +23,10 @@ const Role = (props: Store) => {
</Button>
<BTable
store={usrStore}
store={roleStore}
scroll={{ x: "max-content" }}
columns={columns}
dataSource={usrStore.list}
dataSource={roleStore.list}
/>
<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) => [
{
type: FormType.input,
label: "用户名",
label: "角色名称",
name: "user_name",
value: "",
rules: [{ required: true, message: "请输入用户名称!" }],

View File

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

View File

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

View File

@ -6,4 +6,21 @@ class UserConfig {
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 sourceStore from '@/store/source';
import roleStore from './role';
import menuStore from './menu';
const store = {
usrStore,
sourceStore
sourceStore,
roleStore,
menuStore,
};
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 { UserDataType, UserInfos } from "@/model/userModel";
import { message } from "antd";
import UserConfig from "@/service/user_config";
import { UserConfig } from "@/service/user_config";
class UserStore extends BaseStore<UserDataType> {
_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');