diff --git a/src/components/b_table.tsx b/src/components/b_table.tsx index 458f21e..69a9f2e 100644 --- a/src/components/b_table.tsx +++ b/src/components/b_table.tsx @@ -17,6 +17,8 @@ const BTable = (props: any) => { editCallback, deleteCallback, actionCloumn, + onSizeChange, + onPageChange, } = props; const [selectedRowKeys, setSelectedRowKeys] = useState([]); const onSelectChange = (newSelectedRowKeys: React.Key[]) => { @@ -29,16 +31,24 @@ const BTable = (props: any) => { onChange: onSelectChange, }; const onShowSizeChange = (current, pageSize) => { - store.setPages({ - Offset: current, - Size: pageSize, - }); + if (onSizeChange) { + onSizeChange(current, pageSize); + } else { + store.setPages({ + Offset: current, + Size: pageSize, + }); + } }; const onChange: PaginationProps["onChange"] = (page) => { - store.setPages({ - Offset: page, - Size: 20, - }); + if (onPageChange) { + onPageChange(page); + } else { + store.setPages({ + Offset: page, + Size: 20, + }); + } }; const cancel: PopconfirmProps["onCancel"] = (e) => {}; diff --git a/src/components/layout/layout.tsx b/src/components/layout/layout.tsx index 0ee1fdb..6049717 100644 --- a/src/components/layout/layout.tsx +++ b/src/components/layout/layout.tsx @@ -6,9 +6,10 @@ import { useEffect, useState } from "react"; import { Avatar, Breadcrumb, Layout, Menu, theme } from "antd"; import { UserOutlined } from "@ant-design/icons"; import Sider from "antd/es/layout/Sider"; -import { items } from "./layout_config"; +import { items, headItems } from "./layout_config"; import { Dropdown } from "antd/lib"; import { Outlet, useNavigate } from "react-router"; + const LayOut = (props: Store) => { const { usrStore } = props; const [collapsed, setCollapsed] = useState(false); @@ -45,7 +46,13 @@ const LayOut = (props: Store) => {
logo
- + { + console.log(e.key==="loginout") + if (e.key==="loginout"){ + window.localStorage.removeItem("token") + nav("/login") + } + } }}> } />
diff --git a/src/components/layout/layout_config.ts b/src/components/layout/layout_config.ts index d4d9ef4..bf25eaf 100644 --- a/src/components/layout/layout_config.ts +++ b/src/components/layout/layout_config.ts @@ -1,35 +1,40 @@ export const items = [ - { - key: "/", - label: `首页看板`, - }, - { - key: "/user", - label: `用户管理`, - children: [ - { key: "/user/list", label: `用户管理` }, - ], - }, - { - key: "/source", - label: `数据管理`, - children: [ - { label: "数据管理", key: "/source/list" }, - ], - }, - { - key: "/permission", - label: `权限管理`, - children: [ - { label: `角色管理`, key: "/permission/role" }, - { label: `菜单管理`, key: "/permission/menu" }, - ], - }, - { - key: "/sys", - label: `系统管理`, - children: [ - { label: `部门管理`, key: "/dep" }, - ], - }, -]; \ No newline at end of file + { + key: "/", + label: `首页看板`, + }, + { + key: "/user", + label: `用户管理`, + children: [{ key: "/user/list", label: `用户管理` }], + }, + { + key: "/source", + label: `数据管理`, + children: [{ label: "数据管理", key: "/source/list" }], + }, + { + key: "/permission", + label: `权限管理`, + children: [ + { label: `角色管理`, key: "/permission/role" }, + { label: `菜单管理`, key: "/permission/menu" }, + ], + }, + { + key: "/sys", + label: `系统管理`, + children: [{ label: `部门管理`, key: "/dep" }], + }, +]; + +export const headItems = [ + { + key: "my", + label: `我的`, + }, + { + key: "loginout", + label: `退出登录`, + }, +]; diff --git a/src/pages/login/login.less b/src/pages/login/login.less index fc56354..a700fa4 100644 --- a/src/pages/login/login.less +++ b/src/pages/login/login.less @@ -1,74 +1,117 @@ -.login_model { +*, +*:before, +*:after { + padding: 0; + margin: 0; + box-sizing: border-box; +} +.login { + background-color: #080710; + width: 100%; + height: 100%; + .background { + width: 430px; + height: 520px; + position: absolute; + transform: translate(-50%, -50%); + left: 50%; + top: 50%; + } + .background .shape { + height: 200px; + width: 200px; + position: absolute; + border-radius: 50%; + } + .shape:first-child { + background: linear-gradient(#1845ad, #23a2f6); + left: -80px; + top: -80px; + } + .shape:last-child { + background: linear-gradient(to right, #ff512f, #f09819); + right: -30px; + bottom: -80px; + } + form { + height: 520px; + width: 400px; + background-color: rgba(255, 255, 255, 0.13); + position: absolute; + transform: translate(-50%, -50%); + top: 50%; + left: 50%; + border-radius: 10px; + backdrop-filter: blur(10px); + border: 2px solid rgba(255, 255, 255, 0.1); + box-shadow: 0 0 40px rgba(8, 7, 16, 0.6); + padding: 50px 35px; + } + form * { + font-family: "Poppins", sans-serif; + color: #ffffff; + letter-spacing: 0.5px; + outline: none; + border: none; + } + form h3 { + font-size: 32px; + font-weight: 500; + line-height: 42px; + text-align: center; + } + + label { + display: block; + margin-top: 30px; + font-size: 16px; + font-weight: 500; + } + input { + display: block; + height: 50px; width: 100%; - height: 100%; - background-repeat: no-repeat; - background-size: 100% 100%; + background-color: rgba(255, 255, 255, 0.07); + border-radius: 3px; + padding: 0 10px; + margin-top: 8px; + font-size: 14px; + font-weight: 300; + } + ::placeholder { + color: #e5e5e5; + } + button { + margin-top: 50px; + width: 100%; + background-color: #ffffff; + color: #080710; + padding: 15px 0; + font-size: 18px; + font-weight: 600; + border-radius: 5px; + cursor: pointer; + } + .social { + margin-top: 30px; display: flex; - align-items: center; - justify-content: center; - .login_box { - text-align: right; - width: 100%; - height: 100%; - - #login_basic { - width: 100%; - } - .container { - height: 100%; - } - .login-wrapper { - background-color: #fff; - width: 35%; - height: 400px; - border-radius: 15px; - padding: 0 50px; - position: relative; - left: 50%; - top: 50%; - transform: translate(-50%, -50%); - } - - .header { - font-size: 38px; - font-weight: bold; - text-align: center; - line-height: 180px; - } - - .input-item { - display: block; - width: 100%; - margin-bottom: 20px; - border: 0; - padding: 10px; - font-size: 15px; - outline: none; - } - - .input-item:placeholder { - text-transform: uppercase; - } - - .btn { - text-align: center; - cursor: pointer; - background-color: red; - color: #fff; - padding: 10px; - border-radius: 10px; - width: 100%; - margin-top: 40px; - } - - .msg { - text-align: center; - line-height: 88px; - } - - a { - text-decoration-line: none; - color: #abc1ee; - } - } -} \ No newline at end of file + } + .social div { + background: red; + width: 150px; + border-radius: 3px; + padding: 5px 10px 10px 5px; + background-color: rgba(255, 255, 255, 0.27); + color: #eaf0fb; + text-align: center; + } + .social div:hover { + background-color: rgba(255, 255, 255, 0.47); + } + .social .fb { + margin-left: 25px; + } + .social i { + margin-right: 4px; + } +} diff --git a/src/pages/login/login.tsx b/src/pages/login/login.tsx index a667ac5..334a63a 100644 --- a/src/pages/login/login.tsx +++ b/src/pages/login/login.tsx @@ -1,68 +1,39 @@ -import { useNavigate } from "react-router-dom"; -import "./login.less"; import { inject, observer } from "mobx-react"; -import React from "react"; -import { FormInstance } from "antd/lib/form"; -import SimpleForm from "@/components/form/simple_form"; -const Login = (props) => { +import "./login.less"; +import { Store } from "antd/es/form/interface"; +import { useNavigate } from "react-router"; +import { useRef } from "react"; +const Login = (props: Store) => { const { usrStore } = props; - const formRef = React.useRef(null); + const formRef = useRef(null); const navigate = useNavigate(); - const onFinish = async (values: any) => { + const onFinish = async (e: any) => { + e.preventDefault(); + const formData = new FormData(formRef.current); + const data = Object.fromEntries(formData); let status = await usrStore.login({ - userName: values.account, - passWord: values.password, + userName: data.account, + passWord: data.password, }); if (status) { usrStore.closeLoginDilog(); navigate("/user/list", { replace: true }); } }; - const onFinishFailed = () => {}; - const loginForm = [ - { - type: "input", - label: "用户名", - name: "account", - value: "", - rules: [{ required: true, message: "请输入用户名!" }], - }, - { - type: "password", - label: "密码", - name: "password", - value: "", - rules: [{ required: true, message: "请输入密码!" }], - }, - ]; return ( -
-
-
-
-
Login
-
- -
{ - formRef.current?.submit(); - }} - > - 登录 -
-
-
-
+
+
+
+
+

Login Here

+
+ + + + + +
); }; diff --git a/src/pages/source/source.tsx b/src/pages/source/source.tsx index 87763e8..4193c84 100644 --- a/src/pages/source/source.tsx +++ b/src/pages/source/source.tsx @@ -1,47 +1,237 @@ -import React, { useEffect, useState } from "react"; -import { Space } from "antd"; +import { useEffect, useState } from "react"; +import { + Button, + Checkbox, + Form, + Input, + message, + PaginationProps, + Popconfirm, + Space, + Table, + Typography, +} from "antd"; import { Store } from "antd/lib/form/interface"; import { inject, observer } from "mobx-react"; -import BTable from "@/components/b_table"; import "./source.less"; +import { DataType } from "@/util/model/interface"; +import Upload from "./upload"; const Source = (props: Store) => { const { sourceStore } = props; - const [coloums,setColumns] = useState([]) - const [content,setContent] = useState([]) + const [form] = Form.useForm(); + const [coloums, setColumns] = useState([]); + const [content, setContent] = useState([]); + const [selectKey, setSelectKey] = useState>([]); + const [page, setPage] = useState(1); + const [editingKey, setEditingKey] = useState(""); + const [loading, setLoading] = useState(false); + const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const isEditing = (record) => record.key === editingKey; + const edit = (record: any) => { + form.setFieldsValue({ ...record }); + setEditingKey(record.key); + }; // 获取列表数据 useEffect(() => { - sourceStore.getHead().then((res)=>{ - res.forEach(element => { - element.dataIndex = "dbs_"+element.identity.toLowerCase() - element.title = element.data_name + sourceStore.getHead().then((res) => { + res.forEach((element) => { + element.dataIndex = "dbs_" + element.identity.toLowerCase(); + element.title = element.data_name; + element.label = element.data_name; + element.value = element.identity; + element.editable = true; }); - setColumns(res) - }); - sourceStore.geContent().then((res)=>{ - res.forEach(element => { - element.key = "dbs_"+element.identity - }); - setContent(res) + setColumns(res); }); + getContent([], 1); + // eslint-disable-next-line react-hooks/exhaustive-deps }, [sourceStore]); + const save = async (key: React.Key) => { + try { + const row = (await form.validateFields()) as DataType; + const newData: any = [...content]; + const index = newData.findIndex((item: any) => key === item.key); + if (index > -1) { + const item = newData[index]; + setLoading(true); + let res = await sourceStore.modefyData(row, item.id_card); + if (res) { + getContent(selectKey, 1); + } + setLoading(false); + setEditingKey(""); + } + } catch (errInfo) { + console.log("Validate Failed:", errInfo); + } + }; + const getContent = (list, index) => { + sourceStore.geContent(list, index, 20).then((res) => { + res.forEach((element) => { + element.key = "dbs_" + element.identity; + }); + setContent(res); + }); + }; + const saveClo = () => { + if (selectKey.length === 0) { + message.info("请勾选需要收藏的数据"); + } + }; + const cancel = () => { + setEditingKey(""); + }; + interface EditableCellProps extends React.HTMLAttributes { + editing: boolean; + dataIndex: string; + fixed: string; + index: number; + } + const actionCloumn = { + title: "操作", + with: 200, + fixed: "right", + render: (_: any, record) => { + const editable = isEditing(record); + return editable ? ( + + { + save(record.key); + }} + style={{ marginInlineEnd: 8 }} + > + 保存 + + + 取消 + + + ) : ( + + edit(record)} + > + 编辑 + + { + // deleteCallback(record.identity); + }} + onCancel={cancel} + okText="Yes" + cancelText="No" + > + + + + ); + }, + }; + + const EditableCell: React.FC> = ({ + editing, + dataIndex, + children, + ...restProps + }) => { + const inputNode = ; + + return ( + + {editing ? ( + + {inputNode} + + ) : ( + children + )} + + ); + }; + + const mergedColumns = coloums.map((col) => { + if (!col.editable) { + return col; + } + return { + ...col, + onCell: (record: DataType) => ({ + record, + dataIndex: col.dataIndex, + title: col.title, + editing: isEditing(record), + }), + }; + }); + const onChange: PaginationProps["onChange"] = (page) => { + setPage(page); + getContent(selectKey, page); + cancel(); + }; + const rowSelection = { + selectedRowKeys, + preserveSelectedRowKeys: true, + fixed: true, + onChange: (keys, rowKeys, info) => { + setSelectedRowKeys(keys); + }, + }; return (
- { - sourceStore.deleteItem(id); - }} - actionCloumn={(e)=>{ - - }} - editCallback={(record) => { - }} - /> + + + { + setSelectKey(v); + getContent(v, 1); + }} + /> + + + +
+ + ); diff --git a/src/pages/source/source_config.tsx b/src/pages/source/source_config.tsx index 1ad6646..ead7bc6 100644 --- a/src/pages/source/source_config.tsx +++ b/src/pages/source/source_config.tsx @@ -1,7 +1,6 @@ import { FormType } from "@/components/form/interface"; import { UserDataType } from "@/model/userModel"; import { ColumnsType } from "antd/lib/table"; -import dayjs from "dayjs"; export const defaultConfig = [ { diff --git a/src/pages/source/upload.tsx b/src/pages/source/upload.tsx new file mode 100644 index 0000000..6b53a00 --- /dev/null +++ b/src/pages/source/upload.tsx @@ -0,0 +1,26 @@ +import Config from "@/util/config"; +import { Button, message, Upload, UploadProps } from "antd"; + +const Uploads = () => { + const props: UploadProps = { + name: "file", + action: `${Config.baseUrl}/public/fts/uploadthree`, + headers: { + authorization: "authorization-text", + }, + onChange(info: any) { + if (info.file.status === "done" && info.file.response.code !== 200) { + message.error(`${info.file.response.msg}`); + } else if (info.file.status === "error") { + message.error(`${info.file.name} file upload failed.`); + } + }, + }; + return ( + + + + ); +}; + +export default Uploads; diff --git a/src/pages/user/user.tsx b/src/pages/user/user.tsx index 7da4f6b..c48a3b6 100644 --- a/src/pages/user/user.tsx +++ b/src/pages/user/user.tsx @@ -31,6 +31,9 @@ const User = (props: Store) => { scroll={{ x: "max-content" }} columns={columns} dataSource={usrStore.list} + deleteCallback={(record) => { + usrStore.deleteItem(record); + }} editCallback={(record) => { setIsModalOpen(true); formRef.current?.setFieldsValue(record); diff --git a/src/service/user_config.ts b/src/service/user_config.ts index 4cbf863..49a774b 100644 --- a/src/service/user_config.ts +++ b/src/service/user_config.ts @@ -1,5 +1,5 @@ class UserConfig { - static LOGINURI: string = "/anth/login/pc" + static LOGINURI: string = "/anth/login" static ADD: string = "/user"; static EDIT: string = "/user"; static LIST: string = "/user/list"; diff --git a/src/store/source.ts b/src/store/source.ts index 7fd9362..77bc978 100644 --- a/src/store/source.ts +++ b/src/store/source.ts @@ -6,35 +6,56 @@ import { base } from "@/service/base"; import { message } from "antd"; class SourceStore extends BaseStore { - headlist =[] - contentList =[] + headlist = [] + contentList = [] + total: any = 0; constructor() { super(SourceConfig) makeObservable(this, { - getHead:action, - - headlist:observable, - contentList:observable + getHead: action, + headlist: observable, + contentList: observable }) } - async getHead(){ + async getHead() { let res = await base.get(SourceConfig.Headers, {}) - if (res.code !== 200) { - message.error(res.msg) - return false - } + if (res.code !== 200) { + message.error(res.msg) + return false + } this.headlist = res.data.record; return res.data.record; } - async geContent(){ - let res = await base.get(SourceConfig.Content, {}) - if (res.code !== 0) { - message.error(res.msg) - return false + async modefyData(obj, idcard) { + let list: any = [] + for (let value in obj) { + if (obj[value]) { + list.push({ + key: value, + val: obj[value] + }) } - this.contentList = res.data; - return res.data; + } + let res = await base.put(SourceConfig.EDIT, { + list:list, + id_card:idcard, + }) + if (res.code !== 200) { + message.error(res.msg) + return false + } + return true + } + + async geContent(list, page, size) { + let res = await base.post(SourceConfig.Content, { identity: list, offset: page ?? 1, size: size ?? 10 }) + if (res.code !== 200) { + message.error(res.msg) + return false + } + this.total = res.data.count; + return res.data.record; } } const sourceStore = new SourceStore(); diff --git a/src/store/user.ts b/src/store/user.ts index 3f886d8..1986be5 100644 --- a/src/store/user.ts +++ b/src/store/user.ts @@ -44,10 +44,11 @@ class UserStore extends BaseStore { } try { let data = await base.post(UserConfig.LOGINURI, param) - if (data.code !== 0) { + if (data.code !== 200) { message.error(data.msg) return false } + console.log(data.data.token) window.localStorage.setItem("token", data.data.token ?? ""); return true } catch (error) { diff --git a/src/util/config.ts b/src/util/config.ts index 6d0cec7..9acf9f9 100644 --- a/src/util/config.ts +++ b/src/util/config.ts @@ -1,4 +1,4 @@ class Config { - static baseUrl = "/"; + static baseUrl = "http://127.0.0.1:12214/v1"; } export default Config;