WGShare.Client.Electron/src/page/Home/User/index.tsx

621 lines
23 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import styles from '@/page/Home/User/index.module.scss'
import { useEffect, useState, useRef } from "react";
import Operation from '@/components/Operation';
import { Button, Input, Table, Pagination, Modal, message, Select } from "antd";
import { ExclamationCircleFilled, SearchOutlined } from '@ant-design/icons';
import { GetUserList, PostUser, PutUser, DeleteUser, PutUserPwd, GetRoleDpList, PostUserImport, GetSubDpList, PutUserBth } from '@/api/Home/User';
import * as CryptoJS from 'crypto-js';
import ImageUrl from '@/utils/package/imageUrl';
import { storage } from '@/utils';
import StupWizard from '@/components/StupWizard';
const { Column } = Table
const { confirm } = Modal;
const { exec } = require('child_process');
const fs = require('fs').promises;
const User: React.FC = () => {
const stupWizardRef = useRef<any>();
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [isCreateUser, setIsCreateUser] = useState<'add' | 'batch' | 'edit'>();
const [list, setList] = useState({
data: [],
searchKeywod: '',
total: 0,
pageIndex: 1,
pageSize: 14,
})
const [roleList, setRoleList] = useState([])
const [addUserModal, setAddUserModal] = useState(false)
const [addUserFrom, setAddUserFrom] = useState({
Id: "",
Account: "",
RoleId: null,
Pwd: "",
UserName: "",
subject: null,
year: "",
})
const [changeUserPawModal, setChangeUserPawModal] = useState(false)
const [changeImportModal, setChangeImportModal] = useState(false)
const [changeUserPawFrom, setChangeUserPawFrom] = useState({
Pwd: "",
newPwd: '',
})
const [deleteUserPawModal, setDeleteUserPawModal] = useState(false)
const [subjectList, setSubjectList] = useState<any>([]);
useEffect(() => {
getSubDpList()
}, []);
useEffect(() => {
getUserList()
}, [list.pageIndex, list.pageSize]);
const getUserList = async (): Promise<void> => {
await GetUserList({
pageIndex: list.pageIndex,
pageSize: list.pageSize,
searchKeywod: list.searchKeywod,
}).then(res => {
if (res.code === 200) {
setList({
...list,
total: res.data.total,
data: res.data.items.map((item: any) => {
return {
...item,
key: item.id,
}
}),
})
setSelectedRowKeys([])
}
})
}
const getRoleDpList = async (callBack: Function): Promise<void> => {
await GetRoleDpList().then(res => {
if (res.code === 200) {
setRoleList(res.data.map((item: any) => {
return {
...item,
value: item.id,
label: item.roleName
}
}))
callBack(true)
}
})
}
const fileUpLoad = async (data: { url: string, content: string, fileName: string }): Promise<void> => {
const setting = await JSON.parse(storage.getItem('setting') as string)
try {
const response = await fetch(data.url);
const arrayBuffer = await response.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
await fs.writeFile(`${setting.shareFilesPath}\\${data.fileName}`, buffer, {});
setChangeImportModal(false)
confirm({
title: '提示',
icon: <ExclamationCircleFilled />,
content: data.content,
centered: true,
okText: '打开文件夹',
cancelText: '关闭',
async onOk() {
await fs.access(setting.shareFilesPath, fs.constants.F_OK);
if (process.platform === 'win32') {
exec(`explorer "${setting.shareFilesPath}"`);
} else if (process.platform === 'darwin') {
exec(`open "${setting.shareFilesPath}"`);
}
},
onCancel() {
}
})
} catch (error: any) {
if (error.code === 'ENOENT') {
message.error({
content: <div> <span style={{ color: '#606fc7', cursor: 'pointer' }} onClick={() => {
stupWizardRef.current.changeModal(4)
}}></span></div>
})
return
} else {
message.error(error)
}
}
}
const getSubDpList = async (): Promise<void> => {
await GetSubDpList().then(res => {
if (res.code === 200) {
setSubjectList(res.data.map((item: any) => { return { value: item.value, label: item.name } }))
}
})
}
return (
<>
<div className={styles.user}>
<div className={styles.userOperation}>
<Operation></Operation>
</div>
<div className={styles.userBtns}>
<div className={`${styles.userBtnsLeft} drag`}>
<Button type="primary"
onClick={() => {
getRoleDpList((bool: boolean) => {
if (bool) {
setIsCreateUser('add')
setAddUserFrom({
Id: "",
Account: "",
RoleId: null,
Pwd: "",
UserName: "",
subject: null,
year: "",
})
setAddUserModal(true)
}
})
}}
icon={<img src={ImageUrl.icon8} alt="" />}
className='m-ant-btn'>
</Button>
<Button type="primary"
onClick={() => {
setChangeImportModal(true)
}}
className='m-ant-btn'>
</Button>
<Button type="primary"
onClick={() => {
if (selectedRowKeys.length) {
getRoleDpList((bool: boolean) => {
if (bool) {
setIsCreateUser('batch')
setAddUserFrom({
Id: "",
Account: "",
RoleId: null,
Pwd: "",
UserName: "",
subject: null,
year: "",
})
setAddUserModal(true)
}
})
} else {
message.error('请选择需要修改的用户!')
}
}}
className='m-ant-btn'>
</Button>
<Button type="primary"
icon={<img src={ImageUrl.icon21} alt="" />}
className={styles.userBtnsDel}
onClick={() => {
if (selectedRowKeys.length) {
setDeleteUserPawModal(true)
} else {
message.error('请选择需要删除的用户!')
}
}}
>
</Button>
</div>
<div className={`${styles.userBtnsRight} drag`}>
<Input
placeholder="请输入用户名或账号"
prefix={<SearchOutlined style={{ color: 'white' }} />}
value={list.searchKeywod}
onChange={(e) => {
setList({
...list,
searchKeywod: e.target.value,
})
}}
/>
<Button className='m-border-ant-button' onClick={() => {
if (list.pageIndex === 1) {
getUserList()
} else {
setList({
...list,
pageIndex: 1
})
}
}}></Button>
</div>
</div>
<div className={`${styles.userContent} drag`}>
<Table
size={'small'}
rowSelection={{
selectedRowKeys,
onChange: (newSelectedRowKeys: React.Key[]) => {
setSelectedRowKeys(newSelectedRowKeys);
}
}}
dataSource={list.data}
pagination={false}
scroll={{ y: '70vh' }}
className={styles.userContentTable}
>
<Column title="姓名" dataIndex="userName" key="userName" />
<Column title="账号" dataIndex="account" key="account" />
<Column title="角色" dataIndex="roleName" key="roleName" />
<Column title="在线状态" render={(item) => (
<>
<div style={{ color: item.isOnline ? '#02B188' : 'rgb(221 11 11)' }}>{item.isOnline ? '在线' : '离线'}</div>
</>
)} />
<Column title="届" dataIndex="year" key="year" />
<Column title="学科" render={(item) => (
<>
<div>{subjectList.find((subject: any) => subject.value === item.subject)?.label}</div>
</>
)} />
<Column title="操作" width={200} render={(item) => (
<>
<Button
type="primary"
style={{ backgroundColor: '#0085FF30', marginRight: '14px' }}
size={'small'}
onClick={() => {
getRoleDpList((bool: boolean) => {
if (bool) {
setIsCreateUser('edit')
setAddUserFrom({
...addUserFrom,
Id: item.id,
Account: item.account,
RoleId: item.roleId,
UserName: item.userName,
subject: item.subject,
year: item.year,
})
setAddUserModal(true)
}
})
}}></Button>
<Button
type="primary"
style={{ backgroundColor: '#715AFF40', marginRight: '14px' }}
size={'small'}
onClick={() => {
setChangeUserPawFrom({
Pwd: "",
newPwd: '',
})
setAddUserFrom({
...addUserFrom,
Id: item.id,
Account: item.account,
RoleId: item.roleId,
UserName: item.userName,
})
setChangeUserPawModal(true)
}}></Button>
</>
)} />
</Table>
<div className={styles.userContentPagination}>
<span>{list.total}</span>
<Pagination size="small" total={list.total} onChange={(page, pageSize) => {
setList({
...list,
pageIndex: page,
pageSize: pageSize
})
}} showSizeChanger pageSizeOptions={[10, 14, 20, 30, 40, 50, 100]} pageSize={list.pageSize} current={list.pageIndex} />
</div>
</div>
</div>
<Modal title={isCreateUser === 'add' ? '添加用户' : isCreateUser === 'edit' ? '编辑用户' : '批量修改用户信息'} open={addUserModal} footer={null} closable={false} centered width={'500px'}>
<div>
<div className={styles.addUserModal}>
{isCreateUser !== 'batch' ? <div>
<span></span>
<Input
style={{ flexGrow: 1 }}
placeholder="请输入账号"
maxLength={30}
showCount={true}
value={addUserFrom.Account}
onChange={(e) => {
setAddUserFrom({
...addUserFrom,
Account: e.target.value,
});
}}
/>
</div> : null}
{isCreateUser !== 'batch' ? <div>
<span></span>
<Select
placeholder='请选择角色'
options={roleList}
style={{ flexGrow: 1 }}
value={addUserFrom.RoleId} onChange={(e) => {
setAddUserFrom({
...addUserFrom,
RoleId: e
});
}} />;
</div> : null}
{isCreateUser === 'add' ? <div>
<span></span>
<Input.Password
placeholder="请输入密码"
style={{ flexGrow: 1 }}
value={addUserFrom.Pwd}
onChange={(e) => {
setAddUserFrom({
...addUserFrom,
Pwd: e.target.value,
});
}}
/>
</div> : null}
{isCreateUser !== 'batch' ? <div>
<span></span>
<Input
placeholder="请输入用户名称"
style={{ flexGrow: 1 }}
value={addUserFrom.UserName}
onChange={(e) => {
setAddUserFrom({
...addUserFrom,
UserName: e.target.value,
});
}}
/>
</div> : null}
<div>
<span></span>
<Input
placeholder="请输入届"
value={addUserFrom.year}
onChange={(e) => {
const regex = /^[0-9]*$/;
if (regex.test(e.target.value)) {
setAddUserFrom({
...addUserFrom,
year: e.target.value
});
}
}}
/>
</div>
<div>
<span></span>
<Select
placeholder='请选择学科'
style={{ flexGrow: 1 }}
options={subjectList}
value={addUserFrom.subject} onChange={(e) => {
setAddUserFrom({
...addUserFrom,
subject: e
});
}} />
</div>
</div>
<div style={{
display: 'flex', justifyContent: 'center'
}}>
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setAddUserModal(false)}></Button>
<Button type="primary" className='m-ant-btn' onClick={async () => {
if (!addUserFrom.Account && isCreateUser !== 'batch') {
return message.error('请输入账号!')
}
if (!addUserFrom.RoleId && isCreateUser !== 'batch') {
return message.error('请选择角色!')
}
if (!addUserFrom.Pwd && isCreateUser === 'add') {
return message.error('请输入密码!')
}
if (!addUserFrom.UserName && isCreateUser !== 'batch') {
return message.error('请输入用户名称!')
}
if (!addUserFrom.year) {
return message.error('请输入届!')
}
if (addUserFrom.subject === null) {
return message.error('请选择学科!')
}
if (isCreateUser === 'add') {
await PostUser({
...addUserFrom,
Pwd: CryptoJS.MD5(addUserFrom.Pwd).toString(CryptoJS.enc.Hex)
}).then(res => {
if (res.code === 200) {
setAddUserModal(false)
res.data ? message.success('添加成功!') : message.error('添加失败!')
}
})
} else if (isCreateUser === 'edit') {
await PutUser({
Id: addUserFrom.Id,
Account: addUserFrom.Account,
RoleId: addUserFrom.RoleId,
UserName: addUserFrom.UserName,
subject: addUserFrom.subject,
year: addUserFrom.year,
}).then(res => {
if (res.code === 200) {
setAddUserModal(false)
res.data ? message.success('修改成功!') : message.error('修改失败!')
}
})
} else {
const param = selectedRowKeys.map((item: any) => {
return {
id: item,
subject: addUserFrom.subject,
year: addUserFrom.year
}
})
await PutUserBth(param).then(res => {
if (res.code === 200) {
setAddUserModal(false)
res.data ? message.success('修改成功!') : message.error('修改失败!')
}
})
}
await getUserList()
}}>{isCreateUser === 'add' ? '添加' : '修改'}</Button>
</div>
</div>
</Modal>
<Modal title='更改密码' open={changeUserPawModal} footer={null} closable={false} centered width={'500px'}>
<div>
<div className={styles.addUserModal}>
<div>
<span></span>
<Input.Password
placeholder="请输入新密码"
style={{ flexGrow: 1 }}
value={changeUserPawFrom.Pwd}
onChange={(e) => {
setChangeUserPawFrom({
...changeUserPawFrom,
Pwd: e.target.value,
});
}}
/>
</div>
<div>
<span></span>
<Input.Password
placeholder="再次输入密码"
style={{ flexGrow: 1 }}
value={changeUserPawFrom.newPwd}
onChange={(e) => {
setChangeUserPawFrom({
...changeUserPawFrom,
newPwd: e.target.value,
});
}}
/>
</div>
</div>
<div style={{
display: 'flex', justifyContent: 'center'
}}>
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }} onClick={() => setChangeUserPawModal(false)}></Button>
<Button type="primary" className='m-ant-btn' onClick={async () => {
if (!changeUserPawFrom.Pwd || !changeUserPawFrom.newPwd) {
return message.error('请输入密码!')
}
if (changeUserPawFrom.Pwd !== changeUserPawFrom.newPwd) {
return message.error('新密码与确认密码不一致!')
}
await PutUserPwd({ id: addUserFrom.Id, pwd: CryptoJS.MD5(changeUserPawFrom.Pwd).toString(CryptoJS.enc.Hex) }).then(res => {
if (res.code === 200) {
setChangeUserPawModal(false)
message.success('修改成功')
}
})
await getUserList()
}}></Button>
</div>
</div>
</Modal>
<Modal title='' open={deleteUserPawModal} footer={null} centered width={'300px'} closable={false}>
<div>
<div style={{ color: 'white', fontSize: '18px', textAlign: 'center', marginBottom: '20px' }}>
</div>
<div style={{
display: 'flex', justifyContent: 'center'
}}>
<Button type="primary" style={{ backgroundColor: '#31353A', marginRight: '14px' }}
onClick={() => setDeleteUserPawModal(false)}></Button>
<Button type="primary" className='m-ant-btn' onClick={() => {
DeleteUser(selectedRowKeys).then(res => {
if (res.code === 200) {
setDeleteUserPawModal(false)
message.success('删除成功!')
getUserList()
}
})
}}></Button>
</div>
</div>
</Modal>
<Modal title='批量导入用户' open={changeImportModal} onCancel={() => setChangeImportModal(false)} footer={null} centered width={'300px'}>
<div>
<div>
<Button type="primary" className='m-ant-btn' style={{ width: '100%', marginBottom: '10px' }}
onClick={async () => {
const setting = await JSON.parse(storage.getItem('setting') as string)
await fileUpLoad({
url: 'https://wgshare.oss-cn-chengdu.aliyuncs.com/%E7%94%A8%E6%88%B7%E6%89%B9%E9%87%8F%E5%AF%BC%E5%85%A5%E6%A8%A1%E6%9D%BF%E8%A1%A8.xlsx',
content: `下载导入模板成功!文件已保存至:${setting.shareFilesPath}`,
fileName: `用户批量导入模板表_${+new Date()}.xlsx`
})
}}
>
</Button>
</div>
<div>
<Button type="primary" className='m-ant-btn' style={{ width: '100%' }}
onClick={() => {
const file = document.createElement("input") as any;
file.type = "file";
// file.accept = ".xls,.xlsx";
file.onchange = async () => {
const setting = await JSON.parse(storage.getItem('setting') as string)
const fileInfo = file.files[0];
const formData = new FormData();
formData.append("file", fileInfo);
await PostUserImport(formData).then(res => {
if (res.code === 200) {
if (res.data.item1) {
if (list.pageIndex === 1) {
getUserList()
} else {
setList({
...list,
pageIndex: 1
})
}
message.success(res.data.item3)
} else {
if (res.data.item2) {
const fileName = res.data.item2.split('/').pop().split('?')[0];
fileUpLoad({
url: res.data.item2,
content: `导入模板失败!失败文件已保存至:${setting.shareFilesPath}`,
fileName
})
}
message.error(res.data.item3)
}
}
})
setChangeImportModal(false)
};
file.click();
}}
>
</Button>
</div>
</div>
</Modal>
<StupWizard ref={stupWizardRef} />
</>
)
}
export default User