企业用户账号管理功能开发
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled

This commit is contained in:
francis-fh
2026-07-12 13:59:52 +08:00
parent 9f5c3c2c10
commit 6311f5a051
3 changed files with 360 additions and 0 deletions

View File

@@ -0,0 +1,254 @@
import React, { useEffect, useRef, useState } from 'react';
import { Form, Input, Modal, Switch, Tag, message } from 'antd';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { changeLcCompanyStatus, getAdminCompanyList, resetLcPsw } from '@/services/cms/company';
import { getDictValueEnum } from '@/services/system/dict';
import DictTag from '@/components/DictTag';
function CompanyUserList() {
const actionRef = useRef<ActionType>();
const [scaleEnum, setScaleEnum] = useState<Record<string, any>>({});
const [natureEnum, setNatureEnum] = useState<Record<string, any>>({});
const [passwordModalOpen, setPasswordModalOpen] = useState(false);
const [currentRecord, setCurrentRecord] = useState<API.CmsCompany.CompanyUser | null>(null);
const [passwordForm] = Form.useForm();
useEffect(() => {
getDictValueEnum('scale', true, true).then(setScaleEnum);
getDictValueEnum('company_nature', true, true).then(setNatureEnum);
}, []);
const columns: ProColumns<API.CmsCompany.CompanyUser>[] = [
{
title: '企业名称',
dataIndex: 'name',
valueType: 'text',
align: 'center',
width: 200,
},
{
title: '企业编号',
dataIndex: 'code',
valueType: 'text',
align: 'center',
width: 160,
},
{
title: '企业性质',
dataIndex: 'nature',
valueType: 'select',
align: 'center',
width: 100,
valueEnum: natureEnum,
render: (_, record) => <DictTag enums={natureEnum} value={record.nature} />,
},
{
title: '企业规模',
dataIndex: 'scale',
valueType: 'select',
align: 'center',
width: 100,
valueEnum: scaleEnum,
render: (_, record) => <DictTag enums={scaleEnum} value={record.scale} />,
},
{
title: '注册地址',
dataIndex: 'registeredAddress',
valueType: 'text',
hideInSearch: true,
align: 'center',
width: 200,
ellipsis: true,
},
{
title: '法定代表人',
dataIndex: 'legalPerson',
valueType: 'text',
align: 'center',
width: 100,
},
{
title: '联系人',
dataIndex: 'contactPerson',
valueType: 'text',
align: 'center',
width: 100,
render: (_, record) => record.contactPerson || '-',
},
{
title: '联系电话',
dataIndex: 'contactPersonPhone',
valueType: 'text',
align: 'center',
width: 130,
render: (_, record) => record.contactPersonPhone || '-',
},
{
title: '状态',
dataIndex: 'status',
valueType: 'select',
align: 'center',
width: 90,
valueEnum: {
0: { text: '待审核', status: 'Processing' },
1: { text: '通过', status: 'Success' },
2: { text: '驳回', status: 'Error' },
},
render: (_, record) => {
if (record.status === 1) return <Tag color="success"></Tag>;
if (record.status === 2) return <Tag color="error"></Tag>;
return <Tag color="orange"></Tag>;
},
},
{
title: '创建时间',
dataIndex: 'createTime',
valueType: 'dateTime',
hideInSearch: true,
align: 'center',
width: 160,
},
{
title: '更新时间',
dataIndex: 'updateTime',
valueType: 'dateTime',
hideInSearch: true,
align: 'center',
width: 160,
},
{
title: '是否启用',
dataIndex: 'enableStatus',
align: 'center',
width: 100,
fixed: 'right',
hideInSearch: true,
render: (_, record) => (
<Switch
checked={record.status === 0}
onChange={async (checked) => {
try {
await changeLcCompanyStatus({
userId: record.lcUserid,
status: checked ? '0' : '1',
});
message.success(checked ? '已启用' : '已停用');
actionRef.current?.reload();
} catch {
message.error('操作失败');
}
}}
/>
),
},
{
title: '操作',
align: 'center',
width: 120,
fixed: 'right',
hideInSearch: true,
render: (_, record) => (
<a
onClick={() => {
setCurrentRecord(record);
passwordForm.resetFields();
setPasswordModalOpen(true);
}}
>
</a>
),
},
];
return (
<div style={{ width: '100%' }}>
<ProTable<API.CmsCompany.CompanyUser>
actionRef={actionRef}
rowKey="companyId"
columns={columns}
request={(params) =>
getAdminCompanyList({ ...params } as API.CmsCompany.Params).then((res) => ({
data: res.rows || [],
total: res.total,
success: true,
}))
}
search={{ labelWidth: 'auto' }}
scroll={{ x: 'max-content' }}
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
headerTitle="企业用户管理"
/>
<Modal
title="修改密码"
open={passwordModalOpen}
onCancel={() => setPasswordModalOpen(false)}
onOk={() => passwordForm.submit()}
destroyOnHidden
>
<Form
form={passwordForm}
layout="vertical"
onFinish={async (values) => {
try {
await resetLcPsw({
userId: currentRecord!.lcUserid,
password: values.password,
});
message.success('密码修改成功');
setPasswordModalOpen(false);
} catch {
message.error('密码修改失败');
}
}}
>
<Form.Item
label="新密码"
name="password"
rules={[
{ required: true, message: '请输入新密码' },
{ min: 8, max: 20, message: '密码长度在 8 到 20 个字符' },
{
validator: (_, value) => {
if (!value) return Promise.resolve();
const hasUpper = /[A-Z]/.test(value);
const hasLower = /[a-z]/.test(value);
const hasDigit = /\d/.test(value);
const specialChars = value.match(/[^a-zA-Z0-9]/g);
const hasTwoSpecial = specialChars && specialChars.length >= 2;
if (!hasUpper) return Promise.reject(new Error('密码需包含大写字母'));
if (!hasLower) return Promise.reject(new Error('密码需包含小写字母'));
if (!hasDigit) return Promise.reject(new Error('密码需包含数字'));
if (!hasTwoSpecial) return Promise.reject(new Error('密码需包含至少2个特殊字符'));
return Promise.resolve();
},
},
]}
>
<Input.Password placeholder="请输入新密码" />
</Form.Item>
<Form.Item
label="确认密码"
name="confirmPassword"
dependencies={['password']}
rules={[
{ required: true, message: '请确认新密码' },
({ getFieldValue }) => ({
validator(_, value) {
if (!value || getFieldValue('password') === value) {
return Promise.resolve();
}
return Promise.reject(new Error('两次输入的密码不一致'));
},
}),
]}
>
<Input.Password placeholder="请再次输入新密码" />
</Form.Item>
</Form>
</Modal>
</div>
);
}
export default CompanyUserList;

View File

@@ -0,0 +1,48 @@
import { request } from '@umijs/max';
/**
* 分页查询企业用户管理列表
* GET /cms/company/adminCompanyList
*/
export async function getAdminCompanyList(
params?: API.CmsCompany.Params & {
current?: number;
pageSize?: number;
},
) {
return request<API.CmsCompany.CompanyUserResult>(
'/api/cms/company/adminCompanyList',
{
method: 'GET',
params,
},
);
}
/**
* 切换企业用户启用/停用状态
* POST /cms/appUser/changeLcCompanyStatus
*/
export async function changeLcCompanyStatus(data: {
userId: number;
status: string;
}) {
return request('/api/cms/appUser/changeLcCompanyStatus', {
method: 'POST',
data,
});
}
/**
* 浪潮修改密码
* POST /cms/appUser/resetLcPsw
*/
export async function resetLcPsw(data: {
userId: number;
password: string;
}) {
return request('/api/cms/appUser/resetLcPsw', {
method: 'POST',
data,
});
}

58
src/types/cms/company.d.ts vendored Normal file
View File

@@ -0,0 +1,58 @@
declare namespace API.CmsCompany {
export interface CompanyUserResult {
total: number;
rows: CompanyUser[];
code: number;
msg: string;
data?: any;
}
export interface CompanyUser {
createTime: string;
updateTime: string;
companyId: number;
name: string;
location?: string | null;
industry: string;
scale?: string | null;
code: string;
description?: string | null;
nature: string;
totalRecruitment?: string | null;
isCollection?: any;
userId?: number | null;
businessLicenseUrl?: string | null;
idCardPictureUrl?: string | null;
idCardPictureBackUrl?: string | null;
powerOfAttorneyUrl?: string | null;
contactPerson?: string | null;
contactPersonPhone?: string | null;
status: number; // 0 待审核, 1 通过, 2 驳回
notPassReason?: string | null;
companyContactList?: any;
registeredAddress: string;
isAbnormal?: any;
rejectTime?: string | null;
isImpCompany?: any;
impCompanyType?: any;
enterpriseType?: string | null;
legalPerson: string;
legalIdCard: string;
legalPhone: string;
companyStatus?: any;
isHrs: string;
jobList?: any;
lcUserid: number;
}
export interface Params {
pageNum?: number;
pageSize?: number;
name?: string;
status?: number;
code?: string;
legalPerson?: string;
contactPerson?: string;
contactPersonPhone?: string;
}
}