diff --git a/node_modules/.cache/logger/umi.log b/node_modules/.cache/logger/umi.log deleted file mode 100644 index e69de29..0000000 diff --git a/web-fe/package.json b/web-fe/package.json index f15808e..9d02e13 100644 --- a/web-fe/package.json +++ b/web-fe/package.json @@ -15,6 +15,7 @@ "@umijs/max": "^4.4.11", "antd": "^5.4.0", "dayjs": "^1.11.13", + "moment": "^2.30.1", "spark-md5": "^3.0.2", "uuid": "^11.1.0" }, diff --git a/web-fe/src/constants/constants.ts b/web-fe/src/constants/constants.ts index d518cf0..a21dcfe 100644 --- a/web-fe/src/constants/constants.ts +++ b/web-fe/src/constants/constants.ts @@ -23,9 +23,9 @@ export const GENDER_MAP = { // priority export const PRIORITY_MAP = { - 1: '低', - 2: '中', - 3: '高', + 1: '一级', + 2: '二级', + 3: '三级', } as const; export const USER_TYPE_OPTIONS = [ @@ -42,3 +42,9 @@ export const GENDER_OPTIONS = [ { value: 1, label: '女' }, { value: 2, label: '男' }, ]; + +export const PRIOPRITY_OPTIONS = [ + { value: 1, label: '一级' }, + { value: 2, label: '二级' }, + { value: 3, label: '三级' }, +]; diff --git a/web-fe/src/pages/terminal/index.tsx b/web-fe/src/pages/terminal/index.tsx index 4151e05..7543ce1 100644 --- a/web-fe/src/pages/terminal/index.tsx +++ b/web-fe/src/pages/terminal/index.tsx @@ -16,6 +16,7 @@ import { message, Popconfirm, Popover, + Spin, Table, Tooltip, } from 'antd'; @@ -34,6 +35,7 @@ const UserListPage: React.FC = () => { const [searchText, setSearchText] = useState(''); const [selectedRowKeys, setSelectedRowKeys] = useState<[]>([]); const [orgSearchText, setOrgSearchText] = useState(''); + const [spinning, setSpinning] = useState(false); // 分页参数 const [currentPage, setCurrentPage] = useState(1); @@ -42,7 +44,7 @@ const UserListPage: React.FC = () => { // 添加分组 const [visible, setVisible] = useState(false); // 编辑用户 - const [currentUserInfo, setCurrentUserInfo] = useState({ + const [currentDeviceInfo, setCurrentDeviceInfo] = useState({ visible: false, }); const [bindUserDta, setBindUserData] = useState({ @@ -55,7 +57,7 @@ const UserListPage: React.FC = () => { // 获取用户分组组织树 useEffect(() => { - // getGroupList(); + getGroupList(); }, []); const filterTreeData = ( @@ -91,28 +93,34 @@ const UserListPage: React.FC = () => { // 获取用户列表数据 useEffect(() => { - // if (selectedOrg) { - // getDataSource(); - // } + getDataSource(); }, [searchText, selectedOrg, currentPage, pageSize]); const getGroupList = async () => { + setSpinning(true); const params = { type: 2, }; try { const result = await getGroupTree(params); - if (result.error_code === ERROR_CODE) { - setOrgTreeData(result.data.data || []); - if (result.data.data.length > 0) { - setSelectedOrg(result.data.data[0].id as number); + console.log('result=====', result); + const { code, data = [] } = result || {}; + if (code === ERROR_CODE) { + if (data.length > 0) { + const { children = [] } = data[0] || {}; + setOrgTreeData(children); + // if (children.length > 0) { + // setSelectedOrg(children[0].id); + // } } + setSpinning(false); } else { + setSpinning(false); message.error(result.message || '获取终端分组失败'); } } catch (err) { message.error('获取终端分组失败'); - setLoading(false); + setSpinning(false); } }; @@ -121,15 +129,21 @@ const UserListPage: React.FC = () => { page_size: pageSize, page_num: currentPage, }; + if (selectedOrg) { + params.device_group_id = selectedOrg; + } if (searchText) { - params.keywords = searchText; + params.device_name = searchText; } setLoading(true); try { - const result = await getTerminalList(params); - if (result.error_code === ERROR_CODE) { - setDataSource(result.data.data || []); - setTotal(result.data.paging.total || 0); + const result: any = await getTerminalList(params); + console.log('result=====', result); + const { code, data } = result || {}; + const { data: list, total = 0 } = data || {}; + if (code === ERROR_CODE) { + setDataSource(list); + setTotal(total); setLoading(false); } else { message.error(result.message || '获取终端列表失败'); @@ -145,11 +159,11 @@ const UserListPage: React.FC = () => { try { const { id } = device || {}; const payload = { - ids: id ? [id] : selectedRowKeys, + ids: id ? id : selectedRowKeys, }; - const res = await deleteDevice(payload); - const { error_code } = res || {}; - if (error_code === ERROR_CODE) { + const res: any = await deleteDevice(payload); + const { code } = res || {}; + if (code === ERROR_CODE) { message.success('终端删除成功'); setSelectedRowKeys([]); getDataSource(); @@ -159,8 +173,8 @@ const UserListPage: React.FC = () => { } }; - const handleEditUserInfo = (device: Termial.TermialItem) => { - setCurrentUserInfo({ + const handleEditInfo = (device: Termial.TermialItem) => { + setCurrentDeviceInfo({ recordData: { ...device }, visible: true, }); @@ -186,9 +200,9 @@ const UserListPage: React.FC = () => { }, }, { - title: '终端分组', - dataIndex: 'device_group_name', - key: 'device_group_name', + title: '序列号', + dataIndex: 'device_id', + key: 'device_id', width: 220, align: 'center', render: (text) => { @@ -196,20 +210,10 @@ const UserListPage: React.FC = () => { }, }, { - title: 'IP地址', - dataIndex: 'ip_addr', - key: 'ip_addr', - width: 150, - align: 'center', - render: (text) => { - return {text || '--'}; - }, - }, - { - title: '终端标识', - dataIndex: 'mac_addr', - key: 'mac_addr', - ellipsis: true, + title: '终端分组', + dataIndex: 'device_group_name', + key: 'device_group_name', + width: 220, align: 'center', render: (text) => { return {text || '--'}; @@ -226,6 +230,46 @@ const UserListPage: React.FC = () => { return {DEVICE_TYPE_MAP[key] || '--'}; }, }, + { + title: '型号', + dataIndex: 'model', + key: 'model', + width: 150, + align: 'center', + render: (text) => { + return {text || '--'}; + }, + }, + { + title: 'IP地址', + dataIndex: 'ip_addr', + key: 'ip_addr', + width: 150, + align: 'center', + render: (text) => { + return {text || '--'}; + }, + }, + { + title: 'MAC地址', + dataIndex: 'mac_addr', + key: 'mac_addr', + ellipsis: true, + align: 'center', + render: (text) => { + return {text || '--'}; + }, + }, + { + title: '备注', + dataIndex: 'description', + key: 'description', + ellipsis: true, + align: 'center', + render: (text) => { + return {text || '--'}; + }, + }, { title: '操作', key: 'actions', @@ -234,7 +278,7 @@ const UserListPage: React.FC = () => { fixed: 'right', render: (_, record) => (
- { id: selectedOrg, }; const res = await deleteUserGroup(params); - const { error_code } = res || {}; - if (error_code === ERROR_CODE) { + const { code } = res || {}; + if (code === ERROR_CODE) { message.success('分组删除成功'); getGroupList(); } @@ -326,6 +370,26 @@ const UserListPage: React.FC = () => { } }; + const onSaveGroup = () => { + getGroupList(); + }; + + const onDeviceSave = () => { + setCurrentDeviceInfo({ + recordData: {}, + visible: false, + }); + getDataSource(); + }; + + const onBindUserSave = () => { + setBindUserData({ + recordData: {}, + visible: false, + }); + getDataSource(); + }; + return (
@@ -361,16 +425,18 @@ const UserListPage: React.FC = () => { />
- } - /> + + } + /> +
@@ -383,7 +449,7 @@ const UserListPage: React.FC = () => { }} >
- onDelete()} @@ -398,7 +464,7 @@ const UserListPage: React.FC = () => { > 删除 - + */} @@ -424,10 +490,10 @@ const UserListPage: React.FC = () => { dataSource={dataSource} loading={loading} rowKey="id" - rowSelection={{ - selectedRowKeys, - onChange: onSelectChange, - }} + // rowSelection={{ + // selectedRowKeys, + // onChange: onSelectChange, + // }} pagination={{ current: currentPage, pageSize: pageSize, @@ -446,40 +512,47 @@ const UserListPage: React.FC = () => {
- { - setVisible(false); - }} - selectedOrg={selectedOrg} - onOk={() => {}} - orgTreeData={orgTreeData} - /> - { - setCurrentUserInfo({ - recordData: {}, - visible: false, - }); - }} - onOk={() => {}} - /> + {visible && ( + { + setVisible(false); + }} + selectedOrg={selectedOrg} + onOk={() => { + onSaveGroup(); + }} + orgTreeData={orgTreeData} + /> + )} + {currentDeviceInfo.visible && ( + { + setCurrentDeviceInfo({ + recordData: {}, + visible: false, + }); + }} + onOk={() => { + onDeviceSave(); + }} + /> + )} {bindUserDta.visible && ( { setBindUserData({ recordData: {}, visible: false, }); }} - onOk={() => {}} + onOk={() => {onBindUserSave()}} /> )} {bindImageDta.visible && ( diff --git a/web-fe/src/pages/terminal/mod/ImageSelectedTable/index.tsx b/web-fe/src/pages/terminal/mod/ImageSelectedTable/index.tsx index 29576ae..4d6e839 100644 --- a/web-fe/src/pages/terminal/mod/ImageSelectedTable/index.tsx +++ b/web-fe/src/pages/terminal/mod/ImageSelectedTable/index.tsx @@ -8,10 +8,8 @@ import SelectConponents from './table'; interface SelectedTableProps { placement?: PopoverProps['placement']; - selectedOrg?: number; onCancel?: () => void; onOk?: (values: any) => void; - orgTreeData?: User.OrganizationNode[]; value?: any; onChange: (values: any) => void; } @@ -19,7 +17,6 @@ interface SelectedTableProps { const SelectedTable: React.FC = (props) => { const { placement = 'bottomLeft', - orgTreeData, value: formValue, onChange: onBindImageChange, } = props; @@ -95,7 +92,6 @@ const SelectedTable: React.FC = (props) => { const accessPopover = (
diff --git a/web-fe/src/pages/terminal/mod/ImageSelectedTable/table.tsx b/web-fe/src/pages/terminal/mod/ImageSelectedTable/table.tsx index 157f50c..3931fb3 100644 --- a/web-fe/src/pages/terminal/mod/ImageSelectedTable/table.tsx +++ b/web-fe/src/pages/terminal/mod/ImageSelectedTable/table.tsx @@ -1,14 +1,12 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ -import { IMAGES_TYPE_MAP } from '@/constants/images.constants'; import { ERROR_CODE } from '@/constants/constants'; -import { getImagesList } from '@/services/images'; -import { Input, Table, message,Tooltip } from 'antd'; +import { getImageList } from '@/services/terminal'; +import { Input, message, Table } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import React, { useEffect, useState } from 'react'; import styles from './index.less'; interface TableProps { - treeData?: User.OrganizationNode[]; selectedRowKeys?: any[]; onUserTableSelect?: (keys: any[], row: any[]) => void; } @@ -38,10 +36,13 @@ const TablePage: React.FC = ({ } setLoading(true); try { - const imagesRes = await getImagesList(params); - if (imagesRes.error_code === ERROR_CODE) { - setData(imagesRes.data.data || []); - setTotal(imagesRes.data.paging.total || 0); + const imagesRes: any = await getImageList(params); + console.log('imagesRes=========', imagesRes); + const { code, data } = imagesRes || {}; + const { data: list = [], total = 0 } = data || {}; + if (code === ERROR_CODE) { + setData(list); + setTotal(total); setLoading(false); } else { message.error(imagesRes.message || '获取镜像列表失败'); @@ -66,16 +67,6 @@ const TablePage: React.FC = ({ dataIndex: 'image_name', render: (text: any) => {text || ''}, }, - { - title: '桌面类型', - dataIndex: 'image_type', - key: 'image_type', - width: 200, - render: (text: number) => { - const key = text as keyof typeof IMAGES_TYPE_MAP; - return {IMAGES_TYPE_MAP[key] || '--'}; - }, - }, ]; const handleSearch = (value: string) => { diff --git a/web-fe/src/pages/terminal/mod/bindImage/index.tsx b/web-fe/src/pages/terminal/mod/bindImage/index.tsx index 5f7bc40..ee3f8f6 100644 --- a/web-fe/src/pages/terminal/mod/bindImage/index.tsx +++ b/web-fe/src/pages/terminal/mod/bindImage/index.tsx @@ -1,5 +1,7 @@ // index.tsx -import { Button, Form, Input, message, Modal } from 'antd'; +import { ERROR_CODE } from '@/constants/constants'; +import { getBindImageList } from '@/services/terminal'; +import { Button, Form, message, Modal } from 'antd'; import React, { useEffect } from 'react'; import SelectedTable from '../ImageSelectedTable/index'; import styles from './index.less'; @@ -19,11 +21,20 @@ const BindUserModal: React.FC = ({ dataDetial, }) => { const { recordData, visible, selectedOrg } = dataDetial || {}; + const { id: device_id } = recordData || {}; const [form] = Form.useForm(); useEffect(() => { - // const initialValues = { user_group_id: [selectedOrg], status: 1 }; - // form.setFieldsValue(initialValues); + const params = { device_id: device_id }; + getBindImageList(params).then((res: any) => { + const { code, data = [] } = res || {}; + if (code === ERROR_CODE) { + if (data && data.length) { + const initialValues = { image_list: data }; + form.setFieldsValue(initialValues); + } + } + }); }, [visible, form, recordData, selectedOrg]); const handleOk = async () => { @@ -73,19 +84,19 @@ const BindUserModal: React.FC = ({ style={{ paddingTop: '20px', paddingBottom: '20px' }} > - - + */}
diff --git a/web-fe/src/pages/terminal/mod/bindUser/index.tsx b/web-fe/src/pages/terminal/mod/bindUser/index.tsx index 119b4b3..58e3747 100644 --- a/web-fe/src/pages/terminal/mod/bindUser/index.tsx +++ b/web-fe/src/pages/terminal/mod/bindUser/index.tsx @@ -1,39 +1,129 @@ +/* eslint-disable array-callback-return */ // index.tsx -import { Button, Form, Input, message, Modal } from 'antd'; -import React, { useEffect } from 'react'; +import { ERROR_CODE } from '@/constants/constants'; +import { bindUserAdd, getBindUserList } from '@/services/terminal'; +import { getGroupTree } from '@/services/userList'; +import { Button, Form, message, Modal } from 'antd'; +import React, { useEffect, useState } from 'react'; import SelectedTable from '../selectedTable'; import styles from './index.less'; interface UserEditModalProps { // visible: boolean; - orgTreeData?: User.OrganizationNode[]; + // orgTreeData?: User.OrganizationNode[]; onCancel: () => void; - onOk: (values: any) => void; + onOk: (values?: any) => void; confirmLoading?: boolean; dataDetial?: Termial.ModalBaseNode; selectedOrg?: number; } const BindUserModal: React.FC = ({ - orgTreeData, + // orgTreeData, onCancel, onOk, confirmLoading = false, dataDetial, }) => { - const { recordData, visible, selectedOrg } = dataDetial || {}; + const { recordData, visible } = dataDetial || {}; + const { device_id, device_group_id } = recordData || {}; + const [orgTreeData, setOrgTreeData] = useState([]); const [form] = Form.useForm(); + const getGroupList = async () => { + const params = { + type: 1, + }; + try { + const result = await getGroupTree(params); + console.log('result=====', result); + const { code, data = [] } = result || {}; + if (code === ERROR_CODE) { + if (data.length > 0) { + const { children = [] } = data[0] || {}; + setOrgTreeData(children); + } + } else { + message.error(result.message || '获取终端分组失败'); + } + } catch (err) { + message.error('获取终端分组失败'); + } + }; + useEffect(() => { - // const initialValues = { user_group_id: [selectedOrg], status: 1 }; - // form.setFieldsValue(initialValues); - }, [visible, form, recordData, selectedOrg]); + getGroupList(); + }, [visible]); + + useEffect(() => { + if (!device_id) return; + const payload = { device_id: device_id }; + getBindUserList(payload).then((res: any) => { + console.log('res========', res); + const { code, data = [] } = res || {}; + if (code === ERROR_CODE) { + if (data && data.length > 0) { + const list: any[] = []; + data.map((item: any) => { + const { type, user_id, user_name, user_group_id, user_group_name } = + item || {}; + if (type === 1) { + list.push({ record_id: user_id, name: user_name, ...item }); + } else { + list.push({ + record_id: user_group_id, + name: user_group_name, + ...item, + }); + } + }); + const initialValues = { user_list: list, status: 1 }; + form.setFieldsValue(initialValues); + } + } + }); + }, [visible, form, recordData]); const handleOk = async () => { try { const values = await form.validateFields(); - console.log("values=====",values) - onOk(values); + const { user_list = [] } = values || {}; + const list: any[] = []; + if (user_list && user_list.length > 0) { + user_list.forEach((item: any) => { + const { record_id, type, id } = item || {}; + if (type === 1) { + // 用户 + list.push({ + user_id: record_id, + id: id, + device_id, + device_group_id, + type: type, + }); + } else { + //用户分组 + list.push({ + user_group_id: record_id, + id: id, + device_id: device_id, + device_group_id, + type: type, + }); + } + }); + const payload = { + data: list, + }; + bindUserAdd(payload) + .then(() => { + message.success('绑定成功'); + onOk(); + }) + .catch(() => {}); + } + console.log('list=====', list); + onOk(list); } catch (error) { message.error('请检查表单字段'); } @@ -78,17 +168,17 @@ const BindUserModal: React.FC = ({ - - + */} diff --git a/web-fe/src/pages/terminal/mod/eidtDevice/index.tsx b/web-fe/src/pages/terminal/mod/eidtDevice/index.tsx index d9877eb..a808cbb 100644 --- a/web-fe/src/pages/terminal/mod/eidtDevice/index.tsx +++ b/web-fe/src/pages/terminal/mod/eidtDevice/index.tsx @@ -1,16 +1,15 @@ // index.tsx -import { DEVICE_TYPE_OPTIONS,ERROR_CODE } from '@/constants/constants'; -import { } from '@/constants/constants'; -import { saveDevice } from '@/services/terminal'; +import { DEVICE_TYPE_OPTIONS, ERROR_CODE } from '@/constants/constants'; +import { getDevieDetial, saveDevice } from '@/services/terminal'; import { Button, Form, Input, message, Modal, Select, TreeSelect } from 'antd'; import React, { useEffect } from 'react'; interface UserEditModalProps { orgTreeData: User.OrganizationNode[]; onCancel: () => void; - onOk?: (values: any) => void; + onOk?: (values?: any) => void; confirmLoading?: boolean; - currentUserInfo?: Termial.ModalBaseNode; + currentDeviceInfo?: Termial.ModalBaseNode; selectedOrg?: number; } @@ -19,27 +18,34 @@ const UserEditModal: React.FC = ({ onCancel, onOk, confirmLoading = false, - currentUserInfo, + currentDeviceInfo, }) => { - const { recordData, visible, selectedOrg } = currentUserInfo || {}; - const { user_id } = recordData || {}; + const { recordData, visible, selectedOrg } = currentDeviceInfo || {}; + const { id, device_name } = recordData || {}; const [form] = Form.useForm(); useEffect(() => { - const initialValues = { user_group_id: [selectedOrg], status: 1 }; - form.setFieldsValue(initialValues); + const params = { id: id }; + getDevieDetial(params).then((res: any) => { + console.log('res=======', res); + const { code, data } = res || {}; + if (code === ERROR_CODE) { + const initialValues = { ...data }; + form.setFieldsValue(initialValues); + } + }); }, [visible, form, recordData, selectedOrg]); const handleOk = async () => { try { const values = await form.validateFields(); - const params = { ...values, user_id }; - const res = await saveDevice(params); - const { error_code } = res || {}; - if (error_code === ERROR_CODE) { + const params = { ...values, id }; + const res: any = await saveDevice(params); + const { code } = res || {}; + if (code === ERROR_CODE) { message.success('保存成功'); + onOk(); } - } catch (error) { message.error('保存失败'); } @@ -58,7 +64,7 @@ const UserEditModal: React.FC = ({ return ( = ({ /> + = ({ - {/* - - */} - = ({ selectedRowKeys, }) => { const [data, setData] = useState([]); - // const [selectedRowKeys, setSelectedRowKeys] = useState([]); + const [loading, setLoading] = useState(false); + const [selectedOrg, setSelectedOrg] = useState(); const [searchText, setSearchText] = useState(''); const [currentPage, setCurrentPage] = useState(1); const [pageSize, setPageSize] = useState(20); const [total, setTotal] = useState(0); - // Mock data generation - useEffect(() => { - const mockData: DataType[] = []; - for (let i = 0; i < 100; i++) { - mockData.push({ - id: i + 99, - name: `User ${i}`, - }); + const getDataSource = async () => { + const params: any = { + page_size: pageSize, + page_num: currentPage, + }; + if (selectedOrg) { + params.user_group_id = selectedOrg; } - setData(mockData); - setTotal(mockData.length); - }, []); + if (searchText) { + params.user_name = searchText; + } + setLoading(true); + try { + const result = await getUserList(params); + console.log('res======', result); + const { code, data = {} } = result || {}; + const { data: list, total = 0 } = data || {}; + if (code === ERROR_CODE) { + setData(list || []); + setTotal(total); + setLoading(false); + } else { + message.error(result.message || '获取用户列表失败'); + setLoading(false); + } + } catch (err) { + message.error('获取用户列表失败'); + } + }; - const columns: TableProps['columns'] = [ + useEffect(() => { + getDataSource(); + }, [selectedOrg, searchText]); + + const columns: ColumnsType = [ { - title: 'Name', - dataIndex: 'name', - sorter: (a, b) => a.name.localeCompare(b.name), + title: '序号', + dataIndex: 'order', + key: 'order', + width: 80, + align: 'center', + render: (_: any, record: any, index: number) => {index + 1}, + }, + { + title: '用户名', + dataIndex: 'user_name', + key: 'user_name', + align: 'center', + render: (text) => { + return {text || '--'}; + }, }, ]; @@ -63,16 +100,21 @@ const TablePage: React.FC = ({ setPageSize(size); }; + const onTreeChange = (newValue: any) => { + setSelectedOrg(newValue); + }; + return (
= ({
= (props) => { formValue.forEach((item: any) => { if (item.type === 1) { userList.push(item); - userId.push(item.id); + userId.push(item.record_id); } else { groupList.push(item); - groupId.push(item.id); + groupId.push(item.record_id); } }); + setTableData(formValue); setSelectedRowKeys(userId); setSelectedRows(userList); setCheckedKeys(groupId); @@ -63,10 +64,10 @@ const SelectedTable: React.FC = (props) => { // const onOrgSelect = (selectedKeys: React.Key[], info: any) => {}; const onCheckChange = (keys: any[], info: any) => { - const { checkedNodes } = info; + // const { checkedNodes } = info; console.log('info=========', info); setCheckedKeys(keys); - setCheckedRow(checkedNodes); + setCheckedRow(info); }; const onHnadleCancel = () => { @@ -82,15 +83,15 @@ const SelectedTable: React.FC = (props) => { // 用户 (selectedRows || []).forEach((item) => { list.push({ - id: item.id, - name: item.name, + record_id: item.id, + name: item.user_name, type: 1, }); }); // 用户组 - checkedRow.forEach((item) => { + (checkedRow || []).forEach((item) => { list.push({ - id: item.id, + record_id: item.id, name: item.name, type: 2, }); @@ -116,13 +117,13 @@ const SelectedTable: React.FC = (props) => { console.log('record=====handleDelete', record); if (record) { // 单个删除 - const { id } = record || {}; - const newData = tableData.filter((item) => item.id !== id); + const { record_id } = record || {}; + const newData = tableData.filter((item) => item.record_id !== record_id); setTableData(newData); } else { // 批量删除 const newData = tableData.filter( - (item) => !bindTableKeys.includes(item.id), + (item) => !bindTableKeys.includes(item.record_id), ); setTableData(newData); setSelectedRowKeys([]); @@ -131,39 +132,39 @@ const SelectedTable: React.FC = (props) => { }; const getColumns = (): ColumnsType => { - const columns: ColumnsType = [ - { - title: '序号', - dataIndex: 'order', - key: 'order', - width: 80, - render: (_, record, index) => {index + 1}, - }, - { - title: '名称', - dataIndex: 'name', - key: 'name', - }, - { - title: '类型', - dataIndex: 'type', - key: 'type', - render: (text) => ( - {text == 1 ? '用户' : text == 2 ? '用户组' : ''} - ), - }, - { - title: '操作', - key: 'action', - render: (_, record) => ( - - ), - } - ]; - return columns; - }; + const columns: ColumnsType = [ + { + title: '序号', + dataIndex: 'order', + key: 'order', + width: 80, + render: (_, record, index) => {index + 1}, + }, + { + title: '名称', + dataIndex: 'name', + key: 'name', + }, + { + title: '类型', + dataIndex: 'type', + key: 'type', + render: (text) => ( + {text == 1 ? '用户' : text == 2 ? '用户组' : ''} + ), + }, + { + title: '操作', + key: 'action', + render: (_, record) => ( + + ), + }, + ]; + return columns; + }; const accessPopover = (
@@ -178,6 +179,7 @@ const SelectedTable: React.FC = (props) => { = (props) => { handleDelete()} + onConfirm={() => handleDelete()} disabled={bindTableKeys.length === 0} okText="删除" cancelText="取消" > - +
@@ -254,9 +256,9 @@ const SelectedTable: React.FC = (props) => { dataSource={tableData} onDelete={handleDelete} scrollY={400} - rowKey="id" + rowKey="record_id" pagination={false} - columns={getColumns()} + columns={getColumns()} rowSelection={{ bindTableKeys, onChange: onSelectChange, diff --git a/web-fe/src/pages/userList/index.tsx b/web-fe/src/pages/userList/index.tsx index 21c3a4b..8510beb 100644 --- a/web-fe/src/pages/userList/index.tsx +++ b/web-fe/src/pages/userList/index.tsx @@ -62,13 +62,13 @@ const UserListPage: React.FC = () => { // 获取用户列表数据 useEffect(() => { getDataSource(); - }, [searchText,selectedOrg, currentPage, pageSize]); + }, [searchText, selectedOrg, currentPage, pageSize]); const getUserGroupList = async () => { + setSpinning(true); const params = { type: 1, }; - setSpinning(true); try { const result = await getGroupTree(params); console.log('result=====', result); @@ -144,24 +144,24 @@ const UserListPage: React.FC = () => { setTotal(total); setLoading(false); } else { - message.error(result.message || '获取终端列表失败'); + message.error(result.message || '获取用户列表失败'); setLoading(false); } } catch (err) { - message.error('获取终端列表失败'); + message.error('获取用户列表失败'); setLoading(false); } }; const onDelete = (user?: User.UserItem) => { - const { user_id } = user || {}; + const { id } = user || {}; const payload = { - ids: user_id ? [user_id] : selectedRowKeys, + id: id ? id : selectedRowKeys, }; deleteUser(payload as any).then((res) => { console.log('res=====', res); - const { success } = res || {}; - if (success) { + const { code } = res || {}; + if (code === ERROR_CODE) { message.success('删除成功'); setSelectedRowKeys([]); getDataSource(); @@ -267,7 +267,7 @@ const UserListPage: React.FC = () => { key: 'cell_phone', width: 150, align: 'center', - render: (text:any) => { + render: (text: any) => { return {text || '--'}; }, }, @@ -277,7 +277,7 @@ const UserListPage: React.FC = () => { key: 'birthday', width: 150, align: 'center', - render: (text:any) => { + render: (text: any) => { return {text || '--'}; }, }, @@ -287,7 +287,7 @@ const UserListPage: React.FC = () => { key: 'identity_no', width: 150, align: 'center', - render: (text:any) => { + render: (text: any) => { return {text || '--'}; }, }, @@ -299,9 +299,9 @@ const UserListPage: React.FC = () => { fixed: 'right', render: (_, record) => (
- + */} @@ -346,6 +346,14 @@ const UserListPage: React.FC = () => { getUserGroupList(); }; + const onSaveUserCallback = () => { + setCurrentUserInfo({ + recordData: {}, + visible: false, + }); + getDataSource(); + }; + const onDeleteGroup = async () => { if (selectedOrg) { try { @@ -440,7 +448,7 @@ const UserListPage: React.FC = () => { > 新建用户 - onDelete()} @@ -452,10 +460,11 @@ const UserListPage: React.FC = () => { - + */} @@ -494,38 +503,44 @@ const UserListPage: React.FC = () => { return `共${total}条数据`; }, }} - rowSelection={{ - selectedRowKeys, - onChange: onSelectChange, - }} + // rowSelection={{ + // selectedRowKeys, + // onChange: onSelectChange, + // }} scroll={{ x: 'max-content', y: 55 * 12 }} />
- { - setVisible(false); - }} - onOk={onSaveGroup} - orgTreeData={orgTreeData} - /> - { - setCurrentUserInfo({ - recordData: {}, - visible: false, - }); - }} - onOk={() => {}} - /> + {visible && ( + { + setVisible(false); + }} + onOk={onSaveGroup} + orgTreeData={orgTreeData} + /> + )} + {currentUserInfo.visible && ( + { + setCurrentUserInfo({ + recordData: {}, + visible: false, + }); + }} + onOk={() => { + onSaveUserCallback(); + }} + /> + )} { diff --git a/web-fe/src/pages/userList/mod/eidtUser/index.tsx b/web-fe/src/pages/userList/mod/eidtUser/index.tsx index 51893d7..6782dee 100644 --- a/web-fe/src/pages/userList/mod/eidtUser/index.tsx +++ b/web-fe/src/pages/userList/mod/eidtUser/index.tsx @@ -1,6 +1,10 @@ -// index.tsx -import { GENDER_OPTIONS, USER_TYPE_OPTIONS } from '@/constants/constants'; -import { idIDIntl } from '@ant-design/pro-components'; +import { + ERROR_CODE, + GENDER_OPTIONS, + PRIOPRITY_OPTIONS, + USER_TYPE_OPTIONS, +} from '@/constants/constants'; +import { addUser, editUser, getUserById } from '@/services/userList'; import { Button, Form, @@ -10,6 +14,7 @@ import { Radio, Select, TreeSelect, + DatePicker } from 'antd'; import React, { useEffect } from 'react'; @@ -17,7 +22,7 @@ interface UserEditModalProps { // visible: boolean; orgTreeData: User.OrganizationNode[]; onCancel: () => void; - onOk: (values: any) => void; + onOk: (values?: any) => void; confirmLoading?: boolean; currentUserInfo?: User.UserModalBaseNode; selectedOrg?: number; @@ -35,14 +40,31 @@ const UserEditModal: React.FC = ({ const [form] = Form.useForm(); useEffect(() => { - const initialValues = { user_group_id: [selectedOrg], status: 1 }; - form.setFieldsValue(initialValues); + if (id) { + getUserById({ id }).then((res) => { + const { data } = res; + form.setFieldsValue(data); + }); + } else { + const initialValues = { user_group_id: [selectedOrg], status: 1 }; + form.setFieldsValue(initialValues); + } }, [visible, form, recordData, selectedOrg]); const handleOk = async () => { + const values = await form.validateFields(); try { - const values = await form.validateFields(); - onOk(values); + const params = { ...values }; + if (id) { + params.id = id; + } + const result: any = id ? await editUser(params) : await addUser(params); + const { code } = result || {}; + if (code === ERROR_CODE) { + onOk(); + } else { + message.error('保存失败'); + } } catch (error) { message.error('请检查表单字段'); } @@ -53,13 +75,41 @@ const UserEditModal: React.FC = ({ types: { email: '${label} is not a valid email!', number: '${label} is not a valid number!', - cell_phone: '${label} is not a valid cell phone number!', }, number: { range: '${label} must be between ${min} and ${max}', }, }; + // Password validation rule + const passwordValidator = (_: any, value: string) => { + if (!value) { + return Promise.reject('请输入新密码'); + } + + if (value.length < 6) { + return Promise.reject('密码长度至少6位'); + } + + const hasNumber = /\d/.test(value); + const hasLetter = /[a-zA-Z]/.test(value); + // const hasSpecialChar = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/.test(value); + + if (!hasNumber) { + return Promise.reject('密码必须包含数字'); + } + + if (!hasLetter) { + return Promise.reject('密码必须包含字母'); + } + + // if (!hasSpecialChar) { + // return Promise.reject('密码必须包含特殊字符'); + // } + + return Promise.resolve(); + }; + return ( = ({ validateMessages={validateMessages} > - - - - + + + + = ({ > + void; @@ -22,14 +22,14 @@ const CreatGroup: React.FC = (props) => { onOk, orgTreeData, selectedOrg, - type + type, } = props; const [loading, setLoading] = useState(false); const [form] = Form.useForm(); useEffect(() => { if (selectedOrg) { - const initialValues = { parent_id: [selectedOrg] }; + const initialValues = { parent_id: selectedOrg }; form.setFieldsValue(initialValues); } }, [visible, form, selectedOrg]); @@ -49,10 +49,11 @@ const CreatGroup: React.FC = (props) => { try { console.log('values=====', values); const { name, parent_id } = values || {}; - const params: any = { name, type: type }; - if (parent_id) { - params.parent_id = parent_id; - } + const params: any = { name, type: type, parent_id: parent_id }; + // if (parent_id) { + // params.parent_id = + // parent_id && parent_id.length > 0 ? parent_id[0] : null; + // } const res = await addUserGroup(params); setLoading(false); const { code } = res || {}; diff --git a/web-fe/src/services/terminal/index.ts b/web-fe/src/services/terminal/index.ts index daeca3d..cc5e3e5 100644 --- a/web-fe/src/services/terminal/index.ts +++ b/web-fe/src/services/terminal/index.ts @@ -1,28 +1,74 @@ import { request } from '@umijs/max'; -const BASE_URL = '/api/v1/terminal'; +const BASE_URL = '/api/nex/v1'; // 根据终端序列号查询镜像列表 -export async function getTerminalList(params:any) { - // console.log('终端列表 params', params); - return request(`${BASE_URL}/query/devicelist`, { +export async function getTerminalList(params: any) { + return request(`${BASE_URL}/device/select/page`, { method: 'POST', data: params, }); } -export async function deleteDevice(params:any) { - // console.log('终端列表 params', params); - return request(`${BASE_URL}/delete/device`, { +// 根据id查询终端信息 +export async function getDevieDetial(params: any) { + return request(`${BASE_URL}/device/query`, { method: 'POST', data: params, }); } -export async function saveDevice(params:any) { - // console.log('终端列表 params', params); - return request(`${BASE_URL}/save/device`, { +//删除终端 +export async function deleteDevice(params: any) { + return request(`${BASE_URL}/device/delete`, { method: 'POST', data: params, }); -} \ No newline at end of file +} + +// 终端编辑保存 +export async function saveDevice(params: any) { + return request(`${BASE_URL}/device/update`, { + method: 'POST', + data: params, + }); +} + +// 终端绑定用户 +export async function bindUserAdd(params: any) { + return request(`${BASE_URL}/device/user/mapping/add`, { + method: 'POST', + data: params, + }); +} + +export async function getBindUserList(params: any) { + return request(`${BASE_URL}/device/user/mapping/select`, { + method: 'POST', + data: params, + }); +} + +// 镜像列表 +export async function getImageList(params: any) { + return request(`${BASE_URL}/image/select/page`, { + method: 'POST', + data: params, + }); +} + +// 终端绑定镜像列表 +export async function getBindImageList(params: any) { + return request(`${BASE_URL}/device/image/mapping/select`, { + method: 'POST', + data: params, + }); +} + +// 终端绑定镜像列表 +export async function getBindImageAdd(params: any) { + return request(`${BASE_URL}/device/image/mapping/add`, { + method: 'POST', + data: params, + }); +} diff --git a/web-fe/src/services/userList/index.ts b/web-fe/src/services/userList/index.ts index 73253c8..937de38 100644 --- a/web-fe/src/services/userList/index.ts +++ b/web-fe/src/services/userList/index.ts @@ -58,7 +58,7 @@ export async function getUserById(body?: any) { //删除用户 export async function deleteUser(body?: any) { return request(`${BASE_URL}/user/delete`, { - method: 'DELETE', + method: 'POST', data: body, }); } diff --git a/web-fe/src/types/user.d.ts b/web-fe/src/types/user.d.ts index 384e721..b26e2e4 100644 --- a/web-fe/src/types/user.d.ts +++ b/web-fe/src/types/user.d.ts @@ -15,6 +15,7 @@ declare namespace User { } interface UserItem { + id?:number; user_id?: number; user_group_id?: number; user_group_name?: number; diff --git a/web-fe/yarn.lock b/web-fe/yarn.lock index 07353d0..de73b06 100644 --- a/web-fe/yarn.lock +++ b/web-fe/yarn.lock @@ -6665,7 +6665,7 @@ minimist-options@4.1.0: resolved "https://registry.npmmirror.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== -moment@^2.24.0, moment@^2.29.2, moment@^2.29.4: +moment@^2.24.0, moment@^2.29.2, moment@^2.29.4, moment@^2.30.1: version "2.30.1" resolved "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== @@ -9412,7 +9412,16 @@ string-convert@^0.2.0: resolved "https://registry.npmmirror.com/string-convert/-/string-convert-0.2.1.tgz#6982cc3049fbb4cd85f8b24568b9d9bf39eeff97" integrity sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.npmmirror.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -9502,7 +9511,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.npmmirror.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -10260,7 +10276,16 @@ word-wrap@^1.2.5: resolved "https://registry.npmmirror.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34" integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==