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",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "ball_admin",
"name": "store",
"version": "0.1.0",
"dependencies": {
"@amap/amap-jsapi-loader": "^1.0.1",
@ -43,6 +43,7 @@
"dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
"echarts": "^5.5.1",
"echarts-for-react": "^3.0.2",
"eslint": "^8.3.0",
"eslint-config-react-app": "^7.0.1",
"eslint-webpack-plugin": "^3.1.1",
@ -9566,6 +9567,19 @@
"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": {
"version": "1.1.1",
"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",
"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": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",
@ -40855,6 +40874,15 @@
"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": {
"version": "1.1.1",
"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",
"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": {
"version": "3.0.0",
"resolved": "https://registry.npmmirror.com/slash/-/slash-3.0.0.tgz",

View File

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

View File

@ -139,11 +139,19 @@ const BTable = (props: any) => {
formRef={formRef}
colProps={25}
onFinish={() => {
if(!record){
store.add(formRef.current?.getFieldsValue());
if (!record) {
store.add(formRef.current?.getFieldsValue()).then((res) => {
if (res) {
setIsModalOpen(false);
}
});
return
}
store.putItem(record.identity,formRef.current?.getFieldsValue());
store.putItem(record.identity, formRef.current?.getFieldsValue()).then((res) => {
if (res) {
setIsModalOpen(false);
}
});
}}
createCallback={() => {
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",
treeVideo = "treeVideo",
fetchList = "fetchList",
treeSelect = "treeSelect"
}
export interface FormDatas {
@ -24,6 +25,7 @@ export interface FormDatas {
value: any,
selectUrl?: string,
key?: string,
treeCheckbox:boolean,
selectList?: Array<selectItem>
checkboxData?: Array<any>,
radioData?: Array<any>,

View File

@ -5,6 +5,8 @@ import { FormSelect } from "./select";
import AliUpload from "../ali_upload";
import MyEditor from "../edittor";
import MapFrom from "../map/MapFrom";
import { FormTreeSelect } from "./tree_select";
import { FormCheckBox } from "./checkbox";
// import VideoSelect from "../video_select";
const { TextArea } = Input;
const SimpleForm = (props: SimpleFormData) => {
@ -67,16 +69,9 @@ const SimpleForm = (props: SimpleFormData) => {
</Form.Item>
);
case FormType.cehckbox:
return (
<Form.Item
key={v.label}
label={v.label}
name={v.name}
rules={v.rules}
>
<Checkbox>Remember me</Checkbox>
</Form.Item>
);
return FormCheckBox(v)
case FormType.treeSelect:
return FormTreeSelect(v);
case FormType.cehckboxGroup:
return (
<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>
<Dropdown menu={{
items: headItems, selectable: true, onClick: (e) => {
console.log(e.key === "loginout")
if (e.key === "loginout") {
window.localStorage.removeItem("token")
nav("/login")
return
}
nav(e.key)
}
}}>
<Avatar icon={<UserOutlined />} />

View File

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

View File

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

View File

@ -3,12 +3,32 @@ import { inject, observer } from "mobx-react";
import { Store } from "antd/lib/form/interface";
import React from "react";
import "./index.less";
import ReactECharts from 'echarts-for-react';
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 (
<div className="contentBox">
<Space direction="vertical" size="middle" style={{ display: "flex" }}>
<ReactECharts option={options} />
</Space>
</div>
);

View File

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

View File

@ -2,7 +2,7 @@ import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table";
import { useEffect } from "react";
import { Store } from "antd/lib/form/interface";
import { columns, defaultConfig } from "./dep_config";
import { columns, defaultConfig } from "./config";
import "./dep.less";
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 { columns, defaultConfig } from "./role_config";
import "./role.less";
import { useEffect } from "react";
const Role = (props: Store) => {
const { roleStore } = props;
useEffect(() => {
roleStore.getlist();
}, [roleStore]);
return (
<div className="contentBox">
<BTable

View File

@ -1,6 +1,7 @@
import { FormType } from "@/components/form/interface";
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";
export const defaultConfig = [
@ -13,7 +14,7 @@ export const defaultConfig = [
},
{
type: FormType.inputNumber,
type: FormType.input,
label: "职位描述",
name: "desc",
value: "",
@ -21,18 +22,38 @@ export const defaultConfig = [
},
{
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: "菜单权限",
name: "menu_rights",
name: "menu_id",
selectUrl: MenuConfig.LIST,
value: "",
rules: [{ required: true, message: "请选择菜单" }],
},
{
type: FormType.input,
label: "接口权限",
name: "api_rights",
value: "",
rules: [{ required: true, message: "请输入接口权限" }],
type: FormType.cehckbox,
label: "数据列",
name: "column_ids",
selectUrl: SourceConfig.Headers,
value: [],
rules: [{ required: true, message: "请选择默认数据" }],
},
];

View File

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