first commit

This commit is contained in:
wang_yp 2025-01-21 22:03:04 +08:00
parent 484e918229
commit b08c912644
16 changed files with 200 additions and 188 deletions

View File

@ -1,6 +1,5 @@
import { import {
Button, Button,
message,
Pagination, Pagination,
PaginationProps, PaginationProps,
Popconfirm, Popconfirm,
@ -10,7 +9,15 @@ import {
} from "antd"; } from "antd";
import { useState } from "react"; import { useState } from "react";
const BTable = (props: any) => { const BTable = (props: any) => {
const { store, dataSource, selectCallback, scroll } = props; const {
store,
dataSource,
selectCallback,
scroll,
editCallback,
deleteCallback,
actionCloumn,
} = props;
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]); const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const onSelectChange = (newSelectedRowKeys: React.Key[]) => { const onSelectChange = (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys); setSelectedRowKeys(newSelectedRowKeys);
@ -33,30 +40,37 @@ const BTable = (props: any) => {
Size: 20, Size: 20,
}); });
}; };
const cancel: PopconfirmProps["onCancel"] = (e) => { const cancel: PopconfirmProps["onCancel"] = (e) => {};
message.error("Click on No");
}; const actionDefultColumn = {
const confirm: PopconfirmProps["onConfirm"] = (e) => {
message.success("Click on Yes");
};
const actionColumn = {
title: "操作", title: "操作",
fixed: "right", fixed: "right",
with: 200, with: 200,
render: (any, record) => ( render: (any, record) => (
<Space wrap> <Space wrap>
<Button type="dashed" size="small"> <Button
type="dashed"
size="small"
onClick={() => {
editCallback(record);
}}
>
</Button> </Button>
{actionCloumn}
<Popconfirm <Popconfirm
title="Delete the task" title="删除确认"
description="Are you sure to delete this task?" description="您是否需要删除该数据?"
onConfirm={confirm} onConfirm={() => {
deleteCallback(record.identity);
}}
onCancel={cancel} onCancel={cancel}
okText="Yes" okText="Yes"
cancelText="No" cancelText="No"
> >
<Button type="dashed" danger size="small"></Button> <Button type="dashed" danger size="small">
</Button>
</Popconfirm> </Popconfirm>
</Space> </Space>
), ),
@ -69,7 +83,7 @@ const BTable = (props: any) => {
scroll={scroll} scroll={scroll}
loading={store.listStatus} loading={store.listStatus}
rowSelection={rowSelection} rowSelection={rowSelection}
columns={[...props.columns, actionColumn]} columns={[...props.columns, actionDefultColumn]}
dataSource={dataSource} dataSource={dataSource}
/> />
<div style={{ textAlign: "right", padding: "10px" }}> <div style={{ textAlign: "right", padding: "10px" }}>

View File

@ -37,7 +37,7 @@ export interface SimpleFormData {
initialValues?: Object | null | undefined, initialValues?: Object | null | undefined,
onFinish: Function, onFinish: Function,
formRef?: React.RefObject<FormInstance<any>>, formRef?: React.RefObject<FormInstance<any>>,
onFinishFailed: Function, onFinishFailed?: Function,
formDatas: Array<FormDatas>, formDatas: Array<FormDatas>,
createCallback?: Function createCallback?: Function
children?: React.ReactElement children?: React.ReactElement

View File

@ -41,7 +41,7 @@ const SimpleForm = (props: SimpleFormData) => {
name={v.name} name={v.name}
rules={v.rules} rules={v.rules}
> >
<Input defaultValue={v.value} value={v.value} /> <Input />
</Form.Item> </Form.Item>
); );
case FormType.inputNumber: case FormType.inputNumber:
@ -52,7 +52,7 @@ const SimpleForm = (props: SimpleFormData) => {
name={v.name} name={v.name}
rules={v.rules} rules={v.rules}
> >
<InputNumber defaultValue={v.value} value={v.value} /> <InputNumber />
</Form.Item> </Form.Item>
); );
case FormType.password: case FormType.password:
@ -63,7 +63,7 @@ const SimpleForm = (props: SimpleFormData) => {
name={v.name} name={v.name}
rules={v.rules} rules={v.rules}
> >
<Input.Password value={v.name} /> <Input.Password />
</Form.Item> </Form.Item>
); );
case FormType.cehckbox: case FormType.cehckbox:
@ -87,7 +87,6 @@ const SimpleForm = (props: SimpleFormData) => {
> >
<Checkbox.Group <Checkbox.Group
options={v.checkboxData} options={v.checkboxData}
defaultValue={["Pear"]}
onChange={(res) => { onChange={(res) => {
form.setFieldValue(v.name, res); form.setFieldValue(v.name, res);
}} }}
@ -116,7 +115,6 @@ const SimpleForm = (props: SimpleFormData) => {
<AliUpload <AliUpload
imgList={form.getFieldValue(v.name) ?? []} imgList={form.getFieldValue(v.name) ?? []}
onChnage={(res) => { onChnage={(res) => {
console.log(res);
form.setFieldValue(v.name, res); form.setFieldValue(v.name, res);
}} }}
/> />

View File

@ -22,6 +22,18 @@ const LayOut = (props: Store) => {
justifyContent: "space-between", justifyContent: "space-between",
}; };
const logoStyle = { width: 60, color: "white" }; const logoStyle = { width: 60, color: "white" };
const contentstyle = {
padding: 12,
margin: 0,
minHeight: 280,
background: colorBgContainer,
borderRadius: borderRadiusLG,
};
const breadItem = [
{ title: "首页" },
{ title: "数据集管理" },
{ title: "数据管理" },
];
useEffect(() => { useEffect(() => {
// if (usrStore.isNeedLogin) { // if (usrStore.isNeedLogin) {
// nav("/login"); // nav("/login");
@ -59,19 +71,8 @@ const LayOut = (props: Store) => {
/> />
</Sider> </Sider>
<Layout style={{ padding: "0 15px 15px" }}> <Layout style={{ padding: "0 15px 15px" }}>
<Breadcrumb <Breadcrumb items={breadItem} style={{ margin: "10px 0" }} />
items={[{ title: "Home" }, { title: "List" }, { title: "App" }]} <Content style={contentstyle}>
style={{ margin: "10px 0" }}
/>
<Content
style={{
padding: 12,
margin: 0,
minHeight: 280,
background: colorBgContainer,
borderRadius: borderRadiusLG,
}}
>
<Outlet /> <Outlet />
</Content> </Content>
<Footer style={{ textAlign: "center" }}> <Footer style={{ textAlign: "center" }}>

View File

@ -1,36 +1,68 @@
import React, { useEffect, useState } from "react";
import { Button, Space, Modal, FormInstance } from "antd"; import { Button, Space, Modal, FormInstance } from "antd";
import { Store } from "antd/lib/form/interface";
import { inject, observer } from "mobx-react"; import { inject, observer } from "mobx-react";
import BTable from "@/components/b_table"; import BTable from "@/components/b_table";
import { useEffect, useState } from "react"; import SimpleForm from "@/components/form/simple_form";
import { Store } from "antd/lib/form/interface"; import { columns, defaultConfig } from "./source_config";
import React from "react";
import { columns } from "./source_config";
import "./source.less"; import "./source.less";
import { base as baseHttp } from '@/service/base';
const Source = (props: Store) => { const Source = (props: Store) => {
const { usrStore } = props; const { sourceStore } = 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);
const [record, setRecord] = useState<any>(null);
useEffect(() => {}, []); // 获取列表数据
useEffect(() => {
const addHandler = () => {}; sourceStore.getlist();
}, [sourceStore]);
const gotoDetail = () => {};
const upload = (e) => {
console.log("upload", e.target.files);
let param = new FormData();
param.append("file", e.target.files[0]);
baseHttp.upload("public/fts/upload",param)
};
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="default" onClick={() => addHandler()}> <Button type="default" onClick={() => setIsModalOpen(true)}>
</Button> </Button>
<BTable <BTable
store={usrStore} store={sourceStore}
scroll={{ x: "max-content" }} scroll={{ x: "max-content" }}
columns={columns} columns={columns}
dataSource={usrStore.list} dataSource={sourceStore.list}
deleteCallback={(id) => {
sourceStore.deleteItem(id);
}}
actionCloumn={
<>
<Button size="small" onClick={() => gotoDetail()}>
</Button>
<input
type="file"
name="文件上传"
accept=".xlsx"
onChange={upload}
/>
</>
}
editCallback={(record) => {
setIsModalOpen(true);
formRef.current?.setFieldsValue(record);
setRecord(record);
setId(record.id);
}}
/> />
<Modal <Modal
title={!userId ? "添加用户" : "编辑用户"} title={!userId ? "添加数据集" : "编辑数据集"}
width={800} width={800}
open={isModalOpen} open={isModalOpen}
afterClose={() => formRef.current?.resetFields()} afterClose={() => formRef.current?.resetFields()}
@ -39,12 +71,27 @@ const Source = (props: Store) => {
cancelText="取消" cancelText="取消"
onCancel={() => { onCancel={() => {
setId(null); setId(null);
setRecord(null);
setIsModalOpen(false); setIsModalOpen(false);
}} }}
></Modal> >
<SimpleForm
formName={"source_form"}
formRef={formRef}
colProps={25}
onFinish={() => {
sourceStore.add(formRef.current?.getFieldsValue());
setIsModalOpen(false);
}}
createCallback={() => {
formRef.current?.setFieldsValue(record);
}}
formDatas={defaultConfig as any}
></SimpleForm>
</Modal>
</Space> </Space>
</div> </div>
); );
}; };
export default inject("usrStore")(observer(Source)); export default inject("sourceStore")(observer(Source));

View File

@ -1,97 +1,35 @@
import { FormType } from "@/components/form/interface"; import { FormType } from "@/components/form/interface";
import { UserDataType } from "@/model/userModel"; import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table"; import { ColumnsType } from "antd/lib/table";
import { Image } from "antd"; import dayjs from "dayjs";
import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [ export const defaultConfig = [
{ {
type: FormType.input, type: FormType.input,
label: "用户名", label: "数据集名称",
name: "user_name", name: "resource_name",
value: "", value: "",
rules: [{ required: true, message: "请输入用户名称!" }], 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> = [ export const columns: ColumnsType<UserDataType> = [
{ {
title: "用户名", title: "数据集名称",
dataIndex: "resource_name",
width: 200,
},
{
title: "上传用户",
dataIndex: "user_name", dataIndex: "user_name",
width: 200, width: 200,
fixed: "left",
}, },
{ {
title: "性别", title: "上传时间",
width: 150, dataIndex: "created_at",
render: (render) => ( width: 200,
<span>{getBirthDateAndGender(render.id_card)?.gender}</span> render: (created_at) => (
<span>{dayjs(created_at).format("YYYY-MM-DD")}</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

@ -4,25 +4,26 @@ import BTable from "@/components/b_table";
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { Store } from "antd/lib/form/interface"; import { Store } from "antd/lib/form/interface";
import React from "react"; import React from "react";
import { columns } from "./user_config"; import { columns, defaultConfig } from "./user_config";
import "./user.less"; import "./user.less";
import SimpleForm from "@/components/form/simple_form";
const User = (props: Store) => { const User = (props: Store) => {
const { usrStore } = props; const { usrStore } = 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);
const [record, setRecord] = useState<any>(null);
// 获取列表数据 // 获取列表数据
useEffect(() => { useEffect(() => {
usrStore.getlist(); usrStore.getlist();
}, [usrStore]); }, [usrStore]);
const addHandler = () => {};
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="default" onClick={() => addHandler()}> <Button type="default" onClick={() => setIsModalOpen(true)}>
</Button> </Button>
<BTable <BTable
@ -30,6 +31,12 @@ const User = (props: Store) => {
scroll={{ x: "max-content" }} scroll={{ x: "max-content" }}
columns={columns} columns={columns}
dataSource={usrStore.list} dataSource={usrStore.list}
editCallback={(record) => {
setIsModalOpen(true);
formRef.current?.setFieldsValue(record);
setRecord(record);
setId(record.id);
}}
/> />
<Modal <Modal
@ -42,9 +49,23 @@ const User = (props: Store) => {
cancelText="取消" cancelText="取消"
onCancel={() => { onCancel={() => {
setId(null); setId(null);
setRecord(null);
setIsModalOpen(false); setIsModalOpen(false);
}} }}
></Modal> >
<SimpleForm
formName={"user_form"}
formRef={formRef}
colProps={25}
onFinish={() => {
usrStore.add(formRef.current?.getFieldsValue())
}}
createCallback={() => {
formRef.current?.setFieldsValue(record);
}}
formDatas={defaultConfig as any}
></SimpleForm>
</Modal>
</Space> </Space>
</div> </div>
); );

View File

@ -3,7 +3,7 @@ import { UserDataType } from "@/model/userModel";
import { ColumnsType } from "antd/lib/table"; import { ColumnsType } from "antd/lib/table";
import { Image } from "antd"; import { Image } from "antd";
import { getBirthDateAndGender } from "@/util/util"; import { getBirthDateAndGender } from "@/util/util";
export const defaultConfig = (team, per) => [ export const defaultConfig = [
{ {
type: FormType.input, type: FormType.input,
label: "用户名", label: "用户名",
@ -11,14 +11,6 @@ export const defaultConfig = (team, per) => [
value: "", value: "",
rules: [{ required: true, message: "请输入用户名称!" }], rules: [{ required: true, message: "请输入用户名称!" }],
}, },
{
type: FormType.inputNumber,
label: "年龄",
name: "age",
value: "",
rules: [{ required: true, message: "请输入年龄" }],
},
{ {
type: FormType.input, type: FormType.input,
label: "身份证", label: "身份证",
@ -33,14 +25,12 @@ export const defaultConfig = (team, per) => [
value: "", value: "",
rules: [{ required: true, message: "请输入登录账号" }], rules: [{ required: true, message: "请输入登录账号" }],
}, },
{ {
type: FormType.input, type: FormType.input,
label: "联系电话", label: "联系电话",
name: "tel", name: "tel",
value: "", value: "",
}, },
{ {
type: FormType.input, type: FormType.input,
label: "邮箱", label: "邮箱",

View File

@ -72,6 +72,9 @@ class BaseHttps {
}; };
async upload(url: string, params: any) { async upload(url: string, params: any) {
let res = await axios({ let res = await axios({
headers: {
'Content-Type': 'multipart/form-data'
},
method: 'post', method: 'post',
url: url, url: url,
data: params data: params

View File

@ -0,0 +1,8 @@
class SourceConfig {
static ADD: string = "/desc";
static EDIT: string = "/desc";
static LIST: string = "/desc/list";
static DELETE: string = "/desc";
}
export default SourceConfig;

View File

@ -1,25 +0,0 @@
import { base } from '@/service/base';
class UserService {
static configAdd: string = "/user";
static configEdit: string = "/user";
static configList: string = "/user/list";
static configDelete: string = "/user";
static async add(params) {
return await base.post(UserService.configAdd, params);
}
static async edit(identity: string, params: any) {
return await base.put(UserService.configEdit + "/" + identity, params);
}
static async remove(identity) {
return await base.delete(UserService.configEdit + "/" + identity, {});
}
static async list(params) {
return await base.get(UserService.configList, params);
}
}
export default UserService ;

View File

@ -0,0 +1,9 @@
class UserConfig {
static LOGINURI: string = "/anth/login/pc"
static ADD: string = "/user";
static EDIT: string = "/user";
static LIST: string = "/user/list";
static DELETE: string = "/user";
}
export default UserConfig;

View File

@ -1,5 +1,4 @@
import { base } from "@/service/base"; import {base} from "@/service/base";
import userService from "@/service/user";
import { Pages } from "@/util/model/interface"; import { Pages } from "@/util/model/interface";
import { message } from "antd"; import { message } from "antd";
import { action, makeObservable, observable, runInAction } from "mobx"; import { action, makeObservable, observable, runInAction } from "mobx";
@ -31,6 +30,7 @@ class BaseStore<B> implements BaseStoreInterface<B> {
add: action, add: action,
listStatus: observable, listStatus: observable,
}) })
console.log(urlConfig)
this.urlConfig = urlConfig; this.urlConfig = urlConfig;
} }
@ -51,7 +51,7 @@ class BaseStore<B> implements BaseStoreInterface<B> {
// 添加 // 添加
async add(param: any, listParam?: any) { async add(param: any, listParam?: any) {
try { try {
let res = await userService.add(param); let res = await base.post(this.urlConfig.ADD, param)
if (res.code !== 200) { if (res.code !== 200) {
message.error(res.msg) message.error(res.msg)
return false return false
@ -66,7 +66,7 @@ class BaseStore<B> implements BaseStoreInterface<B> {
// 更新 // 更新
async putItem(id: string, param: any, listParam?: any) { async putItem(id: string, param: any, listParam?: any) {
try { try {
let res = await userService.edit(id, param) let res = await base.put(this.urlConfig.EDIT + "/" + id, param)
if (res.code !== 200) { if (res.code !== 200) {
message.error(res.msg) message.error(res.msg)
return false return false
@ -82,23 +82,23 @@ class BaseStore<B> implements BaseStoreInterface<B> {
async getlist(params?: any) { async getlist(params?: any) {
this.listStatus = true; this.listStatus = true;
try { try {
let res = await userService.list({ let res = await base.get(this.urlConfig.LIST, {
size: this.page?.Size ?? 20, size: this.page?.Size ?? 20,
offset: this.page?.Offset ?? 1, offset: this.page?.Offset ?? 1,
...params ...params
}); });
this.listStatus = false;
let data: Array<B> = [] let data: Array<B> = []
if (!res?.data) { if (!res?.data?.record) {
runInAction(() => { runInAction(() => {
this.list = data; this.list = data;
}) })
this.listStatus = false;
return; return;
} }
for (let i = 0; i < res.data.length; i++) { for (let i = 0; i < res.data.record.length; i++) {
data.push({ data.push({
key: res.data[i].id, key: res.data.record[i].id,
...res.data[i] ...res.data.record[i]
}) })
} }
runInAction(() => { runInAction(() => {

View File

@ -1,7 +1,9 @@
import usrStore from '@/store/user' import usrStore from '@/store/user'
import sourceStore from '@/store/source';
const store = { const store = {
usrStore, usrStore,
sourceStore
}; };
export default store; export default store;

14
src/store/source.ts Normal file
View File

@ -0,0 +1,14 @@
import { makeObservable } from "mobx";
import BaseStore from "./baseStore";
import { UserDataType } from "@/model/userModel";
import SourceConfig from "@/service/source_config";
class SourceStore extends BaseStore<UserDataType> {
constructor() {
super(SourceConfig)
makeObservable(this, {
})
}
}
const sourceStore = new SourceStore();
export default sourceStore;

View File

@ -1,18 +1,14 @@
import { action, computed, makeObservable, observable } from "mobx"; import { action, computed, makeObservable, observable } from "mobx";
// 用户信息
import { base } from "@/service/base"; 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";
class UserConfig { import UserConfig from "@/service/user_config";
static LOGINURI: string = "/anth/login/pc"
}
class UserStore extends BaseStore<UserDataType> { class UserStore extends BaseStore<UserDataType> {
_userinfo: UserInfos = {}; // 用户信息 _userinfo: UserInfos = {}; // 用户信息
userDetail = {} userDetail = {}
isNeedLogin: boolean = false; // 是否需要登录 isNeedLogin: boolean = false; // 是否需要登录
poverDetail: boolean = false; // 是否展示民兵详情
constructor() { constructor() {
super(UserConfig) super(UserConfig)
@ -21,7 +17,6 @@ class UserStore extends BaseStore<UserDataType> {
login: action, login: action,
_userinfo: observable, _userinfo: observable,
isNeedLogin: observable, isNeedLogin: observable,
poverDetail: observable,
userDetail: observable, userDetail: observable,
openLoginDilog: action, openLoginDilog: action,
userInfo: computed, userInfo: computed,
@ -32,7 +27,6 @@ class UserStore extends BaseStore<UserDataType> {
if (!this._userinfo.token) { if (!this._userinfo.token) {
let token = window.localStorage.getItem("token") let token = window.localStorage.getItem("token")
this._userinfo.token = token; this._userinfo.token = token;
} }
return this._userinfo; return this._userinfo;
} }
@ -68,9 +62,7 @@ class UserStore extends BaseStore<UserDataType> {
closeLoginDilog() { closeLoginDilog() {
this.isNeedLogin = false; this.isNeedLogin = false;
} }
setPoverDe(status: boolean) {
this.poverDetail = status
}
setUserDetaul(data) { setUserDetaul(data) {
this.userDetail = data this.userDetail = data
} }