This commit is contained in:
wang_yp 2025-06-09 23:08:14 +08:00
parent 9d75e261d2
commit 70815fe9a8
20 changed files with 227 additions and 40 deletions

37
package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "ball_admin", "name": "store",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "ball_admin", "name": "store",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1", "@amap/amap-jsapi-loader": "^1.0.1",
@ -43,6 +43,7 @@
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0", "dotenv-expand": "^5.1.0",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"echarts-for-react": "^3.0.2",
"eslint": "^8.3.0", "eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1", "eslint-webpack-plugin": "^3.1.1",
@ -9566,6 +9567,19 @@
"zrender": "5.6.0" "zrender": "5.6.0"
} }
}, },
"node_modules/echarts-for-react": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz",
"integrity": "sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"size-sensor": "^1.0.1"
},
"peerDependencies": {
"echarts": "^3.0.0 || ^4.0.0 || ^5.0.0",
"react": "^15.0.0 || >=16.0.0"
}
},
"node_modules/ee-first": { "node_modules/ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
@ -29964,6 +29978,11 @@
"resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz",
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="
}, },
"node_modules/size-sensor": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/size-sensor/-/size-sensor-1.0.2.tgz",
"integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw=="
},
"node_modules/slash": { "node_modules/slash": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",
@ -40855,6 +40874,15 @@
"zrender": "5.6.0" "zrender": "5.6.0"
} }
}, },
"echarts-for-react": {
"version": "3.0.2",
"resolved": "https://registry.npmmirror.com/echarts-for-react/-/echarts-for-react-3.0.2.tgz",
"integrity": "sha512-DRwIiTzx8JfwPOVgGttDytBqdp5VzCSyMRIxubgU/g2n9y3VLUmF2FK7Icmg/sNVkv4+rktmrLN9w22U2yy3fA==",
"requires": {
"fast-deep-equal": "^3.1.3",
"size-sensor": "^1.0.1"
}
},
"ee-first": { "ee-first": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz", "resolved": "https://registry.npmmirror.com/ee-first/-/ee-first-1.1.1.tgz",
@ -56084,6 +56112,11 @@
"resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz", "resolved": "https://registry.npmmirror.com/sisteransi/-/sisteransi-1.0.5.tgz",
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="
}, },
"size-sensor": {
"version": "1.0.2",
"resolved": "https://registry.npmmirror.com/size-sensor/-/size-sensor-1.0.2.tgz",
"integrity": "sha512-2NCmWxY7A9pYKGXNBfteo4hy14gWu47rg5692peVMst6lQLPKrVjhY+UTEsPI5ceFRJSl3gVgMYaUi/hKuaiKw=="
},
"slash": { "slash": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz", "resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",

View File

@ -38,6 +38,7 @@
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0", "dotenv-expand": "^5.1.0",
"echarts": "^5.5.1", "echarts": "^5.5.1",
"echarts-for-react": "^3.0.2",
"eslint": "^8.3.0", "eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1", "eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1", "eslint-webpack-plugin": "^3.1.1",
@ -94,7 +95,7 @@
"build": "node scripts/build.js", "build": "node scripts/build.js",
"test": "node scripts/test.js" "test": "node scripts/test.js"
}, },
"proxy":"http://127.0.0.1:12216/v1", "proxy": "http://127.0.0.1:12216/v1",
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [
"react-app", "react-app",

View File

@ -139,11 +139,19 @@ const BTable = (props: any) => {
formRef={formRef} formRef={formRef}
colProps={25} colProps={25}
onFinish={() => { onFinish={() => {
if(!record){ if (!record) {
store.add(formRef.current?.getFieldsValue()); store.add(formRef.current?.getFieldsValue()).then((res) => {
if (res) {
setIsModalOpen(false);
}
});
return return
} }
store.putItem(record.identity,formRef.current?.getFieldsValue()); store.putItem(record.identity, formRef.current?.getFieldsValue()).then((res) => {
if (res) {
setIsModalOpen(false);
}
});
}} }}
createCallback={() => { createCallback={() => {
formRef.current?.setFieldsValue(record); formRef.current?.setFieldsValue(record);

View File

@ -0,0 +1,28 @@
import { FormDatas } from "./interface";
import { useEffect, useState } from "react";
import { base } from "@/service/base";
import { Checkbox, Form } from "antd";
export const FormCheckBox = (v: FormDatas) => {
const [list, setList] = useState<any>([]);
useEffect(() => {
if (v.selectList && v.selectList.length > 0) {
setList(v.selectList);
} else {
base.get(`${v.selectUrl}/?size=50&offset=1`, "").then((res) => {
setList(res.data.record ?? []);
});
}
}, [v.selectUrl, v.selectList]);
return (
<Form.Item {...v} key={v.label}>
<Checkbox.Group>
{list.map((item, index) => {
return <Checkbox key={item.identity} value={item.identity}>
{item.data_name}
</Checkbox>
})}
</Checkbox.Group>
</Form.Item>
);
};

View File

@ -15,6 +15,7 @@ export enum FormType {
password = "password", password = "password",
treeVideo = "treeVideo", treeVideo = "treeVideo",
fetchList = "fetchList", fetchList = "fetchList",
treeSelect = "treeSelect"
} }
export interface FormDatas { export interface FormDatas {
@ -24,6 +25,7 @@ export interface FormDatas {
value: any, value: any,
selectUrl?: string, selectUrl?: string,
key?: string, key?: string,
treeCheckbox:boolean,
selectList?: Array<selectItem> selectList?: Array<selectItem>
checkboxData?: Array<any>, checkboxData?: Array<any>,
radioData?: Array<any>, radioData?: Array<any>,

View File

@ -5,6 +5,8 @@ import { FormSelect } from "./select";
import AliUpload from "../ali_upload"; import AliUpload from "../ali_upload";
import MyEditor from "../edittor"; import MyEditor from "../edittor";
import MapFrom from "../map/MapFrom"; import MapFrom from "../map/MapFrom";
import { FormTreeSelect } from "./tree_select";
import { FormCheckBox } from "./checkbox";
// import VideoSelect from "../video_select"; // import VideoSelect from "../video_select";
const { TextArea } = Input; const { TextArea } = Input;
const SimpleForm = (props: SimpleFormData) => { const SimpleForm = (props: SimpleFormData) => {
@ -67,16 +69,9 @@ const SimpleForm = (props: SimpleFormData) => {
</Form.Item> </Form.Item>
); );
case FormType.cehckbox: case FormType.cehckbox:
return ( return FormCheckBox(v)
<Form.Item case FormType.treeSelect:
key={v.label} return FormTreeSelect(v);
label={v.label}
name={v.name}
rules={v.rules}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
);
case FormType.cehckboxGroup: case FormType.cehckboxGroup:
return ( return (
<Form.Item <Form.Item

View File

@ -0,0 +1,37 @@
import { Form } from "antd";
import { FormDatas } from "./interface";
import { useEffect, useState } from "react";
import { base } from "@/service/base";
import { TreeSelect } from 'antd';
export const FormTreeSelect = (v: FormDatas) => {
const [list, setList] = useState<any>([]);
useEffect(() => {
if (v.selectList && v.selectList.length > 0) {
setList(v.selectList);
} else {
base.get(`${v.selectUrl}/?size=50&offset=1`, "").then((res) => {
setList(res.data.record ?? []);
});
}
}, [v.selectUrl, v.selectList]);
return (
<Form.Item {...v}>
<TreeSelect
key={v.name}
fieldNames={{
label: "name",
value: "identity",
children: "children"
}}
treeCheckable={v.treeCheckbox}
showSearch
style={{ width: '100%' }}
placeholder="请选择"
allowClear
treeDefaultExpandAll
treeData={list}
/>
</Form.Item>
);
};

View File

@ -83,11 +83,12 @@ const LayOut = (props: Store) => {
<div style={logoStyle}></div> <div style={logoStyle}></div>
<Dropdown menu={{ <Dropdown menu={{
items: headItems, selectable: true, onClick: (e) => { items: headItems, selectable: true, onClick: (e) => {
console.log(e.key === "loginout")
if (e.key === "loginout") { if (e.key === "loginout") {
window.localStorage.removeItem("token") window.localStorage.removeItem("token")
nav("/login") nav("/login")
return
} }
nav(e.key)
} }
}}> }}>
<Avatar icon={<UserOutlined />} /> <Avatar icon={<UserOutlined />} />

View File

@ -1,39 +1,50 @@
import { HomeOutlined, UserSwitchOutlined, DatabaseOutlined, PaperClipOutlined, SettingOutlined } from '@ant-design/icons';
export const items = [ export const items = [
{ {
key: "/", key: "/",
label: `首页看板`, label: `首页看板`,
icon: <HomeOutlined />
}, },
{ {
key: "/user", key: "/user",
label: `用户管理`, label: `用户管理`,
icon: <UserSwitchOutlined />,
children: [{ key: "/user/list", label: `用户管理` }], children: [{ key: "/user/list", label: `用户管理` }],
}, },
{ {
key: "/source", key: "/source",
label: `数据管理`, label: `数据管理`,
children: [{ label: "数据管理", key: "/source/list" }], icon: <DatabaseOutlined />,
children: [
{ label: "人员", key: "/source/list" },
{ label: "事件", key: "/source/event" }
],
}, },
{ {
key: "/permi", key: "/permi",
label: `权限管理`, label: `权限管理`,
icon: <PaperClipOutlined />,
children: [ children: [
{ label: `企业管理`, key: "/permi/company" }, { label: `企业管理`, key: "/permi/company" },
{ label: `部门管理`, key: "/permi/dep" }, { label: `部门管理`, key: "/permi/dep" },
{ label: `权限管理`, key: "/permi/permi" },
{ label: `角色管理`, key: "/permi/role" }, { label: `角色管理`, key: "/permi/role" },
{ label: `菜单管理`, key: "/permi/menu" }, { label: `菜单管理`, key: "/permi/menu" },
], ],
}, },
// { {
// key: "/sys", icon: <SettingOutlined />,
// label: `系统管理`, key: "/sys",
// children: [], label: `系统管理`,
// }, children: [
// { label: `常用`, key: "/sys/use" },
],
},
]; ];
export const headItems = [ export const headItems = [
{ {
key: "my", key: "/my/use",
label: `我的`, label: `我的`,
}, },
{ {

View File

@ -2,8 +2,8 @@ import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table"; import BTable from "@/components/b_table";
import { useEffect } from "react"; import { useEffect } from "react";
import { Store } from "antd/lib/form/interface"; import { Store } from "antd/lib/form/interface";
import { columns, defaultConfig } from "./company_config"; import { columns, defaultConfig } from "./config";
import "./company.less"; import "./index.less";
const Company = (props: Store) => { const Company = (props: Store) => {
const { companyStore } = props; const { companyStore } = props;

View File

@ -3,12 +3,32 @@ 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";
import "./index.less"; import "./index.less";
import ReactECharts from 'echarts-for-react';
const Dashbord = (props: Store) => { const Dashbord = (props: Store) => {
const options = {
grid: { top: 8, right: 8, bottom: 24, left: 36 },
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
},
yAxis: {
type: 'value',
},
series: [
{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true,
},
],
tooltip: {
trigger: 'axis',
},
};
return ( return (
<div className="contentBox"> <div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}> <Space direction="vertical" size="middle" style={{ display: "flex" }}>
<ReactECharts option={options} />
</Space> </Space>
</div> </div>
); );

View File

@ -48,7 +48,7 @@ export const defaultConfig = [
rules: [], rules: [],
}, },
{ {
type: FormType.select, type: FormType.treeSelect,
label: "所属企业", label: "所属企业",
name: "company_id", name: "company_id",
value: 0, value: 0,

View File

@ -2,7 +2,7 @@ import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table"; import BTable from "@/components/b_table";
import { useEffect } from "react"; import { useEffect } from "react";
import { Store } from "antd/lib/form/interface"; import { Store } from "antd/lib/form/interface";
import { columns, defaultConfig } from "./dep_config"; import { columns, defaultConfig } from "./config";
import "./dep.less"; import "./dep.less";
const Dep = (props: Store) => { const Dep = (props: Store) => {

View File

@ -0,0 +1,6 @@
const Event = () => {
return <div>dev
</div>
}
export default Event;

5
src/pages/my/index.tsx Normal file
View File

@ -0,0 +1,5 @@
export const My = () => {
return <div>
my
</div>
}

View File

@ -3,9 +3,15 @@ import BTable from "@/components/b_table";
import { Store } from "antd/lib/form/interface"; import { Store } from "antd/lib/form/interface";
import { columns, defaultConfig } from "./role_config"; import { columns, defaultConfig } from "./role_config";
import "./role.less"; import "./role.less";
import { useEffect } from "react";
const Role = (props: Store) => { const Role = (props: Store) => {
const { roleStore } = props; const { roleStore } = props;
useEffect(() => {
roleStore.getlist();
}, [roleStore]);
return ( return (
<div className="contentBox"> <div className="contentBox">
<BTable <BTable

View File

@ -1,6 +1,7 @@
import { FormType } from "@/components/form/interface"; import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel"; import { UserDataType } from "@/model/userModel";
import { MenuConfig } from "@/service/user_config"; import SourceConfig from "@/service/source_config";
import { CompanyConfig, DepConfig, MenuConfig } from "@/service/user_config";
import { ColumnsType } from "antd/lib/table"; import { ColumnsType } from "antd/lib/table";
export const defaultConfig = [ export const defaultConfig = [
@ -13,7 +14,7 @@ export const defaultConfig = [
}, },
{ {
type: FormType.inputNumber, type: FormType.input,
label: "职位描述", label: "职位描述",
name: "desc", name: "desc",
value: "", value: "",
@ -21,18 +22,38 @@ export const defaultConfig = [
}, },
{ {
type: FormType.select, type: FormType.select,
label: "所属部门",
name: "dep_id",
selectUrl: DepConfig.LIST,
key: "dep_name",
value: "",
rules: [{ required: true, message: "所属部门不能为空" }],
},
{
type: FormType.treeSelect,
label: "所属单位",
name: "company_id",
treeCheckbox:false,
selectUrl: CompanyConfig.LIST,
value: "",
rules: [{ required: true, message: "所属单位不能为空" }],
},
{
type: FormType.treeSelect,
treeCheckbox:true,
label: "菜单权限", label: "菜单权限",
name: "menu_rights", name: "menu_id",
selectUrl: MenuConfig.LIST, selectUrl: MenuConfig.LIST,
value: "", value: "",
rules: [{ required: true, message: "请选择菜单" }], rules: [{ required: true, message: "请选择菜单" }],
}, },
{ {
type: FormType.input, type: FormType.cehckbox,
label: "接口权限", label: "数据列",
name: "api_rights", name: "column_ids",
value: "", selectUrl: SourceConfig.Headers,
rules: [{ required: true, message: "请输入接口权限" }], value: [],
rules: [{ required: true, message: "请选择默认数据" }],
}, },
]; ];

View File

@ -9,6 +9,8 @@ import Role from "@/pages/role";
import Permission from "@/pages/permission"; import Permission from "@/pages/permission";
import Dep from "@/pages/dep"; import Dep from "@/pages/dep";
import Company from "@/pages/company"; import Company from "@/pages/company";
import Event from "@/pages/event";
import { My } from "@/pages/my";
const routers = createHashRouter([ const routers = createHashRouter([
{ {
@ -29,6 +31,11 @@ const routers = createHashRouter([
path: "/source/list", path: "/source/list",
index: true, index: true,
element: <Source />, element: <Source />,
},
{
path: "/source/event",
index: true,
element: <Event />,
}, },
{ {
path: "/permi/permi", path: "/permi/permi",
@ -49,17 +56,23 @@ const routers = createHashRouter([
index: true, index: true,
element: <Role />, element: <Role />,
}, },
{ {
path: "/permi/company", path: "/permi/company",
index: true, index: true,
element: <Company />, element: <Company />,
}, },
], ],
}, },
{ {
path: "/login", path: "/login",
element: <Login />, element: <Login />,
}, },
{
path: "/my/use",
index: true,
element: <My />,
},
]); ]);
export { routers }; export { routers };