fix:更新

This commit is contained in:
Your Name 2026-02-04 12:32:17 +08:00
parent 3255c9deb6
commit 96f0ac68de
26 changed files with 709 additions and 106 deletions

View File

@ -1,12 +1,13 @@
import { Apis } from '@/gen/Apis'; import { Apis } from '@/gen/Apis';
import { import {
DownOutlined,
LogoutOutlined, LogoutOutlined,
UnlockOutlined, UnlockOutlined,
UserOutlined, UserOutlined,
} from '@ant-design/icons'; } from '@ant-design/icons';
import { history } from '@umijs/max'; import { history } from '@umijs/max';
import { Avatar, Dropdown, MenuProps, Space } from 'antd'; import { Avatar, Dropdown, MenuProps, Space } from 'antd';
import { useState } from 'react'; import { useEffect, useState } from 'react';
import { stateActions } from '../../libs/valtio/actions'; import { stateActions } from '../../libs/valtio/actions';
import AvatarIcon from './AvatarIcon.png'; import AvatarIcon from './AvatarIcon.png';
import ChangePassword from './ChangePassword'; import ChangePassword from './ChangePassword';
@ -52,6 +53,15 @@ export default function AvatarProps({ user }: { user: any }) {
}, },
]; ];
useEffect(() => {
let loginUserInfo = sessionStorage.getItem('loginUserInfo');
console.log(loginUserInfo, 'loginUserInfo');
if (loginUserInfo === 'dW5kZWZpbmVkXzAx') {
setOpen(true);
console.log('登录成功');
}
}, []);
return ( return (
<> <>
<Dropdown menu={{ items }} trigger={['click']}> <Dropdown menu={{ items }} trigger={['click']}>
@ -59,6 +69,7 @@ export default function AvatarProps({ user }: { user: any }) {
<Space> <Space>
<Avatar icon={<UserOutlined />} src={AvatarIcon} size={28} /> <Avatar icon={<UserOutlined />} src={AvatarIcon} size={28} />
<span>{user?.name}</span> <span>{user?.name}</span>
<DownOutlined />
</Space> </Space>
</a> </a>
</Dropdown> </Dropdown>

View File

@ -1,7 +1,8 @@
import { Apis } from '@/gen/Apis'; import { Apis } from '@/gen/Apis';
import { ModalForm, ProFormText } from '@ant-design/pro-components'; import { ModalForm, ProFormText } from '@ant-design/pro-components';
import { history } from '@umijs/max';
import { message } from 'antd'; import { message } from 'antd';
import { stateActions } from '../../libs/valtio/actions';
export default function ChangePassword({ export default function ChangePassword({
open, open,
setOpen, setOpen,
@ -14,12 +15,17 @@ export default function ChangePassword({
open={open} open={open}
wrapperCol={{ span: 24 }} wrapperCol={{ span: 24 }}
width="500px" width="500px"
title="修改密码" title="修改初始密码"
onFinish={async (values) => { onFinish={async (values) => {
return Apis.Common.Auth.ChangePassword(values) return Apis.Common.Auth.ChangePassword(values)
.then(() => { .then(() => {
message.success('修改密码成功'); message.success('修改密码成功');
setOpen(false); Apis.Common.Auth.Logout().then(() => {
stateActions.setLogout();
sessionStorage.removeItem('loginUserInfo');
history.push('/login');
setOpen(false);
});
}) })
.catch(() => false); .catch(() => false);
}} }}

View File

@ -1,15 +1,16 @@
import { MyIcons, MyIconsType, PermissionsType, useMyState } from '@/common'; import { MyIcons, MyIconsType, PermissionsType, useMyState } from '@/common';
import AvatarProps from '@/common/components/layout/AvatarProps'; import AvatarProps from '@/common/components/layout/AvatarProps';
import { SettingOutlined } from '@ant-design/icons'; import { Apis } from '@/gen/Apis';
import { Link, RuntimeConfig, history, useNavigate } from '@umijs/max'; import { Link, RuntimeConfig, history, useNavigate } from '@umijs/max';
import { AutoComplete, Button, Input, Menu, MenuProps, Space } from 'antd'; import { AutoComplete, Input, Menu, MenuProps, Select, Space } from 'antd';
import { useState } from 'react'; import { useEffect, useState } from 'react';
import './allConfig.scss'; import './allConfig.scss';
// import Logo from './logo.png'; // import Logo from './logo.png';
interface LevelKeysProps { interface LevelKeysProps {
key?: string; key?: string;
children?: LevelKeysProps[]; children?: LevelKeysProps[];
} }
const loopMenu = (permissions: PermissionsType[] | undefined) => { const loopMenu = (permissions: PermissionsType[] | undefined) => {
let tree: PermissionsType[] = []; let tree: PermissionsType[] = [];
let map: Record<number, PermissionsType> = {}; let map: Record<number, PermissionsType> = {};
@ -57,6 +58,7 @@ const loopMenu = (permissions: PermissionsType[] | undefined) => {
}; };
export const LayoutConfig: RuntimeConfig['layout'] = () => { export const LayoutConfig: RuntimeConfig['layout'] = () => {
const [getSelectProject, setSelectProject] = useState<LevelKeysProps[]>([]);
const { snap } = useMyState(); const { snap } = useMyState();
const navigate = useNavigate(); const navigate = useNavigate();
const permissionsList = (snap.session.permissions || []) const permissionsList = (snap.session.permissions || [])
@ -69,12 +71,20 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
{ label: '收费Bi', path: '/charge/charge_bi' }, { label: '收费Bi', path: '/charge/charge_bi' },
{ label: '项目Bi', path: '/asset/asset_bi' }, { label: '项目Bi', path: '/asset/asset_bi' },
]; ];
const handleLoadProject = async () => {
let res = await Apis.Common.Auth.GetProjects();
setSelectProject(
res?.data?.map((item) => ({
value: item.id,
label: item.name,
})),
);
};
const [stateOpenKeys, setStateOpenKeys] = useState(['2', '23']); const [stateOpenKeys, setStateOpenKeys] = useState(['2', '23']);
const getLevelKeys: any = (items1: LevelKeysProps[]) => { const getLevelKeys: any = (items1: LevelKeysProps[]) => {
const key: Record<string, number> = {}; const key: Record<string, number> = {};
const func = (items2: LevelKeysProps[], level = 1) => { const func = (items2: LevelKeysProps[], level = 1) => {
console.log(items2, 'level');
items2?.forEach((item) => { items2?.forEach((item) => {
if (item.key) { if (item.key) {
key[item.key] = level; key[item.key] = level;
@ -88,18 +98,22 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
return key; return key;
}; };
useEffect(() => {
handleLoadProject('');
}, []);
return { return {
title: '', title: '',
// 首页 logo // 首页 logo
logo: ( logo: (
<div style={{ width: 181 }}> <div style={{ width: 136, display: 'flex', justifyContent: 'center' }}>
<img <img
src={ src={
snap.session?.company_configs?.config_value?.admin_logo snap.session?.company_configs?.config_value?.admin_logo
? snap.session?.company_configs?.config_value?.admin_logo[0]?.url ? snap.session?.company_configs?.config_value?.admin_logo[0]?.url
: '' : ''
} }
style={{ height: '42px' }} style={{ width: 'auto', height: '42px' }}
/> />
</div> </div>
), ),
@ -114,45 +128,29 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
<div className="headerContentRender"> <div className="headerContentRender">
<div style={{ display: 'flex', alignItems: 'center', gap: 20 }}> <div style={{ display: 'flex', alignItems: 'center', gap: 20 }}>
<HeaderSearch permissionsList={permissionsList} /> <HeaderSearch permissionsList={permissionsList} />
{/* <Space size={20} style={{ color: '#666' }}>
:
{quickLinks.map((q) => (
<a
key={q.path}
onClick={() => history.push(q.path)}
className="quick_link"
>
{q.label}
</a>
))}
</Space> */}
</div> </div>
<Space size={10}> <Space size={10}>
{/* <Popover {/* <Button
placement="bottom"
title="小程序二维码"
content={
<Space style={{ textAlign: 'center' }} size="large">
<div>
<Image src={ImgEmployeeWxApp} style={{ height: '120px' }} />
<div style={{ marginTop: 10 }}></div>
</div>
<div>
<Image src={ImgCustomerWxApp} style={{ height: '120px' }} />
<div style={{ marginTop: 10 }}></div>
</div>
</Space>
}
>
<Button type="default" shape="circle" icon={<TabletOutlined />} />
</Popover>
<Button type="default" shape="circle" icon={<BellOutlined />} /> */}
<Button
type="default" type="default"
shape="circle" shape="circle"
icon={<SettingOutlined />} icon={<SettingOutlined />}
onClick={() => history.push('/system/sys_permissions')} onClick={() => history.push('/system/sys_permissions')}
/> */}
<Select
onSearch={handleLoadProject}
options={getSelectProject}
allowClear
style={{ width: 160 }}
defaultValue={snap.session.current_project?.id}
onChange={(e: any) => {
Apis.Common.Auth.SwitchProject({
project_id: e ? e?.toString() : 'all',
}).then(() => {
window.location.reload();
});
console.log(e, 'e');
}}
placeholder="选择项目"
/> />
</Space> </Space>
</div> </div>
@ -202,7 +200,6 @@ export const LayoutConfig: RuntimeConfig['layout'] = () => {
const repeatIndex = openKeys const repeatIndex = openKeys
.filter((key) => key !== currentOpenKey) .filter((key) => key !== currentOpenKey)
.findIndex((key) => levelKeys[key] === levelKeys[currentOpenKey]); .findIndex((key) => levelKeys[key] === levelKeys[currentOpenKey]);
setStateOpenKeys( setStateOpenKeys(
openKeys openKeys
// remove repeat key // remove repeat key

View File

@ -41,7 +41,9 @@ export const requestConfig: RequestConfig = {
// 错误接收及处理 // 错误接收及处理
errorHandler: (error: any) => { errorHandler: (error: any) => {
if (error) { if (error) {
message.error(error.errorMessage); if (error.errorMessage !== '用户未登录') {
message.error(error.errorMessage);
}
switch (error.errorCode) { switch (error.errorCode) {
case 10000: case 10000:
if (history.location.pathname !== '/login') history.push('/login'); if (history.location.pathname !== '/login') history.push('/login');

View File

@ -17,6 +17,7 @@ export const stateActions = {
state.session.campus = res.data.campus; state.session.campus = res.data.campus;
state.session.company_configs = res.data.company_configs; state.session.company_configs = res.data.company_configs;
state.session.permissions = res.data.permissions; state.session.permissions = res.data.permissions;
state.session.current_project = res.data.current_project;
if (res.data?.token?.access_token) if (res.data?.token?.access_token)
state.storage.access_token = res.data?.token?.access_token; state.storage.access_token = res.data?.token?.access_token;
// 解析apis // 解析apis

View File

@ -48,6 +48,10 @@ type SessionType = {
permissions?: any; permissions?: any;
apiKeys: string[]; apiKeys: string[];
loading: number; loading: number;
current_project?: {
id: number;
name: string;
};
}; };
const session: SessionType = proxy({ const session: SessionType = proxy({
@ -58,6 +62,7 @@ const session: SessionType = proxy({
company_configs: {}, company_configs: {},
apiKeys: [], apiKeys: [],
loading: 0, loading: 0,
current_project: undefined,
}); });
export const state = proxy({ export const state = proxy({

View File

@ -59,7 +59,9 @@ export function MyLoginPage() {
...values, ...values,
...{ captcha_key: getCaptcha?.key }, ...{ captcha_key: getCaptcha?.key },
}) })
.then(async (res) => { .then(async (res: any) => {
let pass = btoa(`${res?.password}_01`);
sessionStorage.setItem('loginUserInfo', pass);
await stateActions.setLogin(res); await stateActions.setLogin(res);
navigate('/'); navigate('/');
}) })

View File

@ -34,6 +34,7 @@ export function MyModal(props?: any) {
type={props.type || 'primary'} type={props.type || 'primary'}
size={props.size || 'small'} size={props.size || 'small'}
onClick={() => setOpen(true)} onClick={() => setOpen(true)}
{...props?.modal?.btnProps}
/> />
) )
) : ( ) : (

157
src/gen/ApiTypes.d.ts vendored
View File

@ -667,6 +667,156 @@ declare namespace ApiTypes {
}; };
} }
} }
namespace Attendance {
namespace AttendanceConfigs {
type List = {
"page"?: number; // -
"per_page"?: number; // -
};
type Store = {
"asset_projects_id": number; // 项目ID
"check_in_range": number; // 打卡范围(米)
"require_photo": boolean; // 是否要求拍照打卡
"allow_out_range_checkin"?: boolean; // 是否允许范围外打卡
};
type UpdateConfig = {
"id": number; // id
"check_in_range": number; // 打卡范围(米)
"require_photo": boolean; // 是否要求拍照打卡
"allow_out_range_checkin"?: boolean; // 是否允许范围外打卡
};
type Enable = {
"id": number; // id
"is_enabled": boolean; // 是否启用: 1:启用 0:禁用
};
}
namespace AttendanceEmployeeTracks {
type List = {
"company_employees_id"?: number; // 员工ID
"asset_projects_id"?: number; // 项目ID
"start_date"?: Date; // 开始日期
"end_date"?: Date; // 结束日期
};
type Detail = {
"company_employees_id": number; // 员工ID
"start_date": Date; // 开始日期
"end_date": Date; // 结束日期
"asset_projects_id"?: number; // 项目ID
};
type Heatmap = {
"company_employees_id": number; // 员工ID
"date": Date; // 日期
};
}
namespace AttendanceRecords {
type List = {
"company_employees_id"?: number; // 员工ID
"asset_projects_id"?: number; // 项目ID
"status"?: string; // 状态
"checkin_type"?: string; // 打卡类型
"checkin_time"?: string[]; // 打卡时间
};
type Show = {
"id": number; // 记录ID
};
type Export = {
"company_employees_id"?: number; // 员工ID
"asset_projects_id"?: number; // 项目ID
"status"?: string; // 状态
"checkin_type"?: string; // 打卡类型
"checkin_time"?: string[]; // 打卡时间
};
}
namespace AttendanceSchedules {
type List = {
"company_employees_id"?: number; // 员工ID
"asset_projects_id"?: number; // 项目ID
"schedule_date"?: Date; // 排班日期
"status"?: string; // 状态,[enum:AttendanceSchedulesStatusEnum]
"project_name"?: string; // 项目名称
"employee_name"?: string; // -
};
type Store = {
"company_employees_id": number; // 员工ID
"attendance_shifts_id": number; // 班次ID
"asset_projects_id": number; // 项目ID
"schedule_date": Date; // 排班日期
"remark"?: string; // 备注
};
type BatchStore = {
"schedules": string[]; // 排班列表
};
type ShiftList = {
"organizations_id": number; // 组织ID
"schedule_date": Date; // 排班日期
};
type Update = {
"id": number; // id
"company_employees_id"?: number; // 员工ID
"attendance_shifts_id"?: number; // 班次ID
"asset_projects_id"?: number; // 项目ID
"schedule_date"?: Date; // 排班日期
"remark"?: string; // 备注
};
type ChangeStatus = {
"id": number; // id
"status": string; // 状态,[enum:AttendanceSchedulesStatusEnum]
};
type Cancel = {
"id": number; // id
};
type Show = {
"id": number; // id
};
type SoftDelete = {
"id": number; // id
};
type Restore = {
"id": number; // id
};
type Delete = {
"id": number; // id
};
}
namespace AttendanceShifts {
type List = {
"name"?: string; // 班次名称
"is_enabled"?: boolean; // 状态
"asset_projects_id"?: number; // 项目ID
"project_name"?: string; // 项目名称
};
type Store = {
"name": string; // 班次名称
"asset_projects_id": number; // 关联项目IDs
"allow_checkin_start": date_format:H:i:s; // 可打卡开始时间
"allow_checkin_end": date_format:H:i:s; // 可打卡结束时间
"is_enabled"?: boolean; // 状态
"remark"?: string; // 备注
"periods": string[]; // 时段列表
};
type Update = {
"id": number; // id
"name"?: string; // 班次名称
"asset_projects_id"?: number; // 关联项目IDs
"allow_checkin_start"?: date_format:H:i:s; // 可打卡开始时间
"allow_checkin_end"?: date_format:H:i:s; // 可打卡结束时间
"is_enabled"?: boolean; // 状态
"remark"?: string; // 备注
"periods"?: string[]; // 时段列表
};
type Show = {
"id": number; // id
};
type Delete = {
"id": number; // id
};
type Select = {
"name"?: string; // 班次名称
"asset_projects_id"?: number; // 项目ID
"project_name"?: string; // 项目名称
};
}
}
namespace Bill { namespace Bill {
namespace HouseBills { namespace HouseBills {
type List = { type List = {
@ -790,6 +940,9 @@ declare namespace ApiTypes {
type TemporaryUrl = { type TemporaryUrl = {
"filename": string; // 文件名称 "filename": string; // 文件名称
}; };
type SwitchProject = {
"project_id": string; // 项目ID all-查看所有
};
} }
namespace ConvenienceServices { namespace ConvenienceServices {
type List = { type List = {
@ -1784,6 +1937,10 @@ declare namespace ApiTypes {
}; };
} }
} }
namespace Statistics {
namespace IndexCount {
}
}
namespace Visitor { namespace Visitor {
namespace VisitorApplies { namespace VisitorApplies {
type List = { type List = {

View File

@ -315,6 +315,102 @@ export const Apis = {
}, },
}, },
}, },
Attendance: {
AttendanceConfigs: {
List(data?: ApiTypes.Attendance.AttendanceConfigs.List): Promise<MyResponseType> {
return request('company/attendance/attendance_configs/list', { data });
},
Store(data: ApiTypes.Attendance.AttendanceConfigs.Store): Promise<MyResponseType> {
return request('company/attendance/attendance_configs/store', { data });
},
UpdateConfig(data: ApiTypes.Attendance.AttendanceConfigs.UpdateConfig): Promise<MyResponseType> {
return request('company/attendance/attendance_configs/update_config', { data });
},
Enable(data: ApiTypes.Attendance.AttendanceConfigs.Enable): Promise<MyResponseType> {
return request('company/attendance/attendance_configs/enable', { data });
},
},
AttendanceEmployeeTracks: {
List(data?: ApiTypes.Attendance.AttendanceEmployeeTracks.List): Promise<MyResponseType> {
return request('company/attendance/attendance_employee_tracks/list', { data });
},
Detail(data: ApiTypes.Attendance.AttendanceEmployeeTracks.Detail): Promise<MyResponseType> {
return request('company/attendance/attendance_employee_tracks/detail', { data });
},
Heatmap(data: ApiTypes.Attendance.AttendanceEmployeeTracks.Heatmap): Promise<MyResponseType> {
return request('company/attendance/attendance_employee_tracks/heatmap', { data });
},
Cleanup(): Promise<MyResponseType> {
return request('company/attendance/attendance_employee_tracks/cleanup', {});
},
},
AttendanceRecords: {
List(data?: ApiTypes.Attendance.AttendanceRecords.List): Promise<MyResponseType> {
return request('company/attendance/attendance_records/list', { data });
},
Show(data: ApiTypes.Attendance.AttendanceRecords.Show): Promise<MyResponseType> {
return request('company/attendance/attendance_records/show', { data });
},
Export(data?: ApiTypes.Attendance.AttendanceRecords.Export): Promise<MyResponseType> {
return request('company/attendance/attendance_records/export', { responseType: 'blob',data });
},
},
AttendanceSchedules: {
List(data?: ApiTypes.Attendance.AttendanceSchedules.List): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/list', { data });
},
Store(data: ApiTypes.Attendance.AttendanceSchedules.Store): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/store', { data });
},
BatchStore(data: ApiTypes.Attendance.AttendanceSchedules.BatchStore): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/batch_store', { data });
},
ShiftList(data: ApiTypes.Attendance.AttendanceSchedules.ShiftList): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/shift_list', { data });
},
Update(data: ApiTypes.Attendance.AttendanceSchedules.Update): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/update', { data });
},
ChangeStatus(data: ApiTypes.Attendance.AttendanceSchedules.ChangeStatus): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/change_status', { data });
},
Cancel(data: ApiTypes.Attendance.AttendanceSchedules.Cancel): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/cancel', { data });
},
Show(data: ApiTypes.Attendance.AttendanceSchedules.Show): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/show', { data });
},
SoftDelete(data: ApiTypes.Attendance.AttendanceSchedules.SoftDelete): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/soft_delete', { data });
},
Restore(data: ApiTypes.Attendance.AttendanceSchedules.Restore): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/restore', { data });
},
Delete(data: ApiTypes.Attendance.AttendanceSchedules.Delete): Promise<MyResponseType> {
return request('company/attendance/attendance_schedules/delete', { data });
},
},
AttendanceShifts: {
List(data?: ApiTypes.Attendance.AttendanceShifts.List): Promise<MyResponseType> {
return request('company/attendance/attendance_shifts/list', { data });
},
Store(data: ApiTypes.Attendance.AttendanceShifts.Store): Promise<MyResponseType> {
return request('company/attendance/attendance_shifts/store', { data });
},
Update(data: ApiTypes.Attendance.AttendanceShifts.Update): Promise<MyResponseType> {
return request('company/attendance/attendance_shifts/update', { data });
},
Show(data: ApiTypes.Attendance.AttendanceShifts.Show): Promise<MyResponseType> {
return request('company/attendance/attendance_shifts/show', { data });
},
Delete(data: ApiTypes.Attendance.AttendanceShifts.Delete): Promise<MyResponseType> {
return request('company/attendance/attendance_shifts/delete', { data });
},
Select(data?: ApiTypes.Attendance.AttendanceShifts.Select): Promise<MyResponseType> {
return request('company/attendance/attendance_shifts/select', { data });
},
},
},
Bill: { Bill: {
HouseBills: { HouseBills: {
List(data?: ApiTypes.Bill.HouseBills.List): Promise<MyResponseType> { List(data?: ApiTypes.Bill.HouseBills.List): Promise<MyResponseType> {
@ -390,6 +486,12 @@ export const Apis = {
TemporaryUrl(data: ApiTypes.Common.Auth.TemporaryUrl): Promise<MyResponseType> { TemporaryUrl(data: ApiTypes.Common.Auth.TemporaryUrl): Promise<MyResponseType> {
return request('company/common/auth/temporary_url', { data }); return request('company/common/auth/temporary_url', { data });
}, },
SwitchProject(data: ApiTypes.Common.Auth.SwitchProject): Promise<MyResponseType> {
return request('company/common/auth/switch_project', { data });
},
GetProjects(): Promise<MyResponseType> {
return request('company/common/auth/get_projects', {});
},
}, },
ConvenienceServices: { ConvenienceServices: {
List(data?: ApiTypes.Common.ConvenienceServices.List): Promise<MyResponseType> { List(data?: ApiTypes.Common.ConvenienceServices.List): Promise<MyResponseType> {
@ -1019,6 +1121,13 @@ export const Apis = {
}, },
}, },
}, },
Statistics: {
IndexCount: {
FinancialAnalysis(): Promise<MyResponseType> {
return request('company/statistics/index_count/financial_analysis', {});
},
},
},
Visitor: { Visitor: {
VisitorApplies: { VisitorApplies: {
List(data?: ApiTypes.Visitor.VisitorApplies.List): Promise<MyResponseType> { List(data?: ApiTypes.Visitor.VisitorApplies.List): Promise<MyResponseType> {

View File

@ -227,6 +227,37 @@ export const AssetUnitsBuildingTypeEnum= {
'Tower': {"text":"塔楼","color":"#ffc107","value":"Tower"}, 'Tower': {"text":"塔楼","color":"#ffc107","value":"Tower"},
}; };
// AttendanceRecordsCheckinTypeEnum
export const AttendanceRecordsCheckinTypeEnum= {
'CheckIn': {"text":"上班","color":"#1890ff","value":"CheckIn"},
'CheckOut': {"text":"下班","color":"#52c41a","value":"CheckOut"},
};
// AttendanceRecordsStatusEnum
export const AttendanceRecordsStatusEnum= {
'Normal': {"text":"正常","color":"#52c41a","value":"Normal"},
'Late': {"text":"迟到","color":"#faad14","value":"Late"},
'EarlyLeave': {"text":"早退","color":"#fa8c16","value":"EarlyLeave"},
'OutOfRange': {"text":"范围外","color":"#ff4d4f","value":"OutOfRange"},
'Reissue': {"text":"补卡","color":"#1890ff","value":"Reissue"},
};
// AttendanceSchedulesStatusEnum
export const AttendanceSchedulesStatusEnum= {
'Pending': {"text":"待生效","color":"#faad14","value":"Pending"},
'Active': {"text":"生效中","color":"#52c41a","value":"Active"},
'Cancelled': {"text":"已取消","color":"#ff4d4f","value":"Cancelled"},
};
// 打卡状态枚举
export const AttendanceStatusEnum= {
'Normal': {"text":"正常","color":"#52c41a","value":"Normal"},
'Late': {"text":"迟到","color":"#faad14","value":"Late"},
'Early': {"text":"早退","color":"#faad14","value":"Early"},
'OutOfRange': {"text":"范围外","color":"#ff4d4f","value":"OutOfRange"},
'MakeUp': {"text":"补卡","color":"#722ed1","value":"MakeUp"},
};
// BannerSpacesTypeEnum // BannerSpacesTypeEnum
export const BannerSpacesTypeEnum= { export const BannerSpacesTypeEnum= {
'Popup': {"text":"弹窗","color":"#ff0000","value":"Popup"}, 'Popup': {"text":"弹窗","color":"#ff0000","value":"Popup"},
@ -251,7 +282,7 @@ export const BannersTypeEnum= {
// 缓存类型 // 缓存类型
export const CacheTypeEnum= { export const CacheTypeEnum= {
'MobilePhoneVerificationCode': {"text":"手机验证码","color":"#e482d3","value":"MobilePhoneVerificationCode"}, 'MobilePhoneVerificationCode': {"text":"手机验证码","color":"#ba2dfa","value":"MobilePhoneVerificationCode"},
}; };
// CompaniesMerchantTypeEnum // CompaniesMerchantTypeEnum
@ -297,6 +328,13 @@ export const CompanyEmployeeBacklogsTypeEnum= {
'MomentTask': {"text":"朋友圈任务","color":"#FF6600","value":"MomentTask"}, 'MomentTask': {"text":"朋友圈任务","color":"#FF6600","value":"MomentTask"},
}; };
// CompanyEmployeesTypeEnum
export const CompanyEmployeesTypeEnum= {
'Staff': {"text":"员工","color":"#1890ff","value":"Staff"},
'WeCom': {"text":"企微","color":"#2196f3","value":"WeCom"},
'External': {"text":"外部","color":"#4caf50","value":"External"},
};
// CompanyReceiptAccountsPayChannelEnum // CompanyReceiptAccountsPayChannelEnum
export const CompanyReceiptAccountsPayChannelEnum= { export const CompanyReceiptAccountsPayChannelEnum= {
'WeChat': {"text":"微信","color":"#07c160","value":"WeChat"}, 'WeChat': {"text":"微信","color":"#07c160","value":"WeChat"},
@ -762,6 +800,12 @@ export const HouseWorkOrdersTypeEnum= {
'Complaint': {"text":"投诉","color":"#aa00ff","value":"Complaint"}, 'Complaint': {"text":"投诉","color":"#aa00ff","value":"Complaint"},
}; };
// 公告阅读者类型
export const MsgPropertyAnnouncementReadsReaderTypeEnum= {
'Customer': {"text":"客户","color":"#3b82f6","value":"Customer"},
'Employee': {"text":"员工","color":"#10b981","value":"Employee"},
};
// 公告接收对象 // 公告接收对象
export const MsgPropertyAnnouncementsObjectEnum= { export const MsgPropertyAnnouncementsObjectEnum= {
'Customer': {"text":"客户","color":"#3b82f6","value":"Customer"}, 'Customer': {"text":"客户","color":"#3b82f6","value":"Customer"},

View File

@ -38,13 +38,7 @@ export default function Index({ title = '项目活动' }) {
// title={title} // title={title}
/> />
), ),
enrolls: ( enrolls: <EnrollsList item={item} title="报名" reload={action?.reload} />,
<>
{item.is_enroll === 1 && (
<EnrollsList item={item} title="报名" reload={action?.reload} />
)}
</>
),
publish: ( publish: (
<MyButtons.Default <MyButtons.Default
title={ title={
@ -199,7 +193,6 @@ export default function Index({ title = '项目活动' }) {
render: (_, item: any, index, action) => ( render: (_, item: any, index, action) => (
<Space key={index}> <Space key={index}>
<ActivityShow item={item} /> <ActivityShow item={item} />
<>{tableRender(item, action)}</> <>{tableRender(item, action)}</>
</Space> </Space>
), ),

View File

@ -16,6 +16,11 @@ export default function EnrollsList(props: MyBetaModalFormProps) {
title={props.title || '报名'} title={props.title || '报名'}
type={props.item?.type || 'primary'} type={props.item?.type || 'primary'}
width="800px" width="800px"
modal={{
btnProps: {
disabled: !props?.item.is_enroll,
},
}}
node={ node={
<ProTable <ProTable
{...MyProTableProps.props} {...MyProTableProps.props}

View File

@ -88,9 +88,7 @@ export default function Index({ title = '登记审核' }) {
MyColumns.Option({ MyColumns.Option({
render: (_, item: any, index, action) => ( render: (_, item: any, index, action) => (
<Space key={index}> <Space key={index}>
{item?.status === HouseRegistersStatusEnum.Pending.value && ( <Audit item={item} reload={action?.reload} title={title} />
<Audit item={item} reload={action?.reload} title={title} />
)}
</Space> </Space>
), ),
}), }),

View File

@ -32,7 +32,15 @@ export default function Update(props: MyBetaModalFormProps) {
<BetaSchemaForm<ApiTypes.Archive.HouseRegisters.Update> <BetaSchemaForm<ApiTypes.Archive.HouseRegisters.Update>
{...MyModalFormProps.props} {...MyModalFormProps.props}
title={props.title} title={props.title}
trigger={<MyButtons.Default title="审核" type="primary" />} trigger={
<MyButtons.Default
title="审核"
disabled={
props.item?.status !== HouseRegistersStatusEnum.Pending.value
}
type="primary"
/>
}
wrapperCol={{ span: 24 }} wrapperCol={{ span: 24 }}
width="800px" width="800px"
modalProps={{ modalProps={{

View File

@ -106,7 +106,7 @@ export default function Index({ title = '客户列表' }) {
search: false, search: false,
}), }),
MyColumns.Option({ MyColumns.Option({
render: (_, item: any, index, action) => ( render: (_, item: any, index) => (
<Space key={index}> <Space key={index}>
<MyButtons.View <MyButtons.View
title="查看" title="查看"

View File

@ -0,0 +1,68 @@
import { Line } from '@ant-design/plots';
import { useEffect, useState } from 'react';
export default function FinancialAnalysisLine() {
const [houseBillsCount, setHouseBillsCount] = useState<any>({});
const config = {
data: [
{
name: '收缴率',
: '01',
金额: 79.0,
},
{
name: '月收款(万元)',
: '01',
金额: 69.0,
},
{
name: '收缴率',
: '02',
金额: 89.0,
},
{
name: '月收款(万元)',
: '02',
金额: 62.0,
},
],
xField: '月份',
yField: '金额',
colorField: 'name',
point: {
size: 7,
},
legend: {
position: 'top',
},
tooltip: {},
style: {
// 矩形四个方向的内边距
inset: 5,
},
// 使用双Y轴因为两个指标数值范围差异大
yAxis: [
{
title: {
text: '月收款(万元)',
},
},
{
title: {
text: '收缴率(%)',
},
grid: null,
},
],
};
useEffect(() => {
setHouseBillsCount({ ...config, data: [] });
}, []);
return (
<div style={{ height: 290 }}>
<Line {...config} />
</div>
);
}

View File

@ -0,0 +1,174 @@
import { ProCard } from '@ant-design/pro-components';
import { Col, Row, Space } from 'antd';
import MyFinancialAnalysisLine from '../charts/FinancialAnalysisLine';
export default function LayoutLeft() {
return (
<div style={{ display: 'flex', flexDirection: 'column', height: '100%' }}>
<Space>
<ProCard title="财务分析" style={{ width: '450px', color: '#fff' }}>
<Space direction="vertical" style={{ width: '100%' }}>
<div
style={{
background:
'linear-gradient(115deg, #6499FF 45%, #95B8FF 100%)',
padding: '20px 0',
borderRadius: '10px',
}}
>
<Row>
<Col span={8}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: 'white',
}}
>
<div
style={{
fontSize: '18px',
fontWeight: 'bold',
marginBottom: '5px',
}}
>
79.00
</div>
<div style={{ fontSize: '14px' }}></div>
</div>
</Col>
<Col span={8}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: 'white',
}}
>
<div
style={{
fontSize: '18px',
fontWeight: 'bold',
marginBottom: '5px',
}}
>
79.00
</div>
<div style={{ fontSize: '14px' }}></div>
</div>
</Col>
<Col span={8}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: 'white',
}}
>
<div
style={{
fontSize: '18px',
fontWeight: 'bold',
marginBottom: '5px',
}}
>
79.00%
</div>
<div style={{ fontSize: '14px' }}></div>
</div>
</Col>
</Row>
</div>
<div
style={{
background:
'linear-gradient(115deg, #6499FF 45%, #95B8FF 100%)',
padding: '20px 0',
borderRadius: '10px',
}}
>
<Row>
<Col span={8}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: 'white',
}}
>
<div
style={{
fontSize: '18px',
fontWeight: 'bold',
marginBottom: '5px',
}}
>
79.00
</div>
<div style={{ fontSize: '14px' }}></div>
</div>
</Col>
<Col span={8}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: 'white',
}}
>
<div
style={{
fontSize: '18px',
fontWeight: 'bold',
marginBottom: '5px',
}}
>
79.00
</div>
<div style={{ fontSize: '14px' }}></div>
</div>
</Col>
<Col span={8}>
<div
style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
color: 'white',
}}
>
<div
style={{
fontSize: '18px',
fontWeight: 'bold',
marginBottom: '5px',
}}
>
79.00%
</div>
<div style={{ fontSize: '14px' }}></div>
</div>
</Col>
</Row>
</div>
<MyFinancialAnalysisLine />
</Space>
</ProCard>
</Space>
<div
style={{
flex: 1,
padding: '15px',
backgroundColor: '#f0f0f0',
borderRadius: '4px',
}}
>
</div>
</div>
);
}

View File

@ -0,0 +1,3 @@
export default function LayoutRight() {
return <div>LayoutRight</div>;
}

View File

@ -1,5 +1,16 @@
// import MyModalsMapLeaflet from '@/components/ModalsMapLeaflet'; // import MyModalsMapLeaflet from '@/components/ModalsMapLeaflet';
import LayoutLeft from './components/LayoutLeft';
import LayoutRight from './components/LayoutRight';
import './style.scss'; import './style.scss';
export default function Index() { export default function Index() {
return <div className="overview_content">2</div>; return (
<div className="overview_content">
<div className="overview_left">
<LayoutLeft />
</div>
<div className="overview_right">
<LayoutRight />
</div>
</div>
);
} }

View File

@ -6,9 +6,11 @@
justify-content: space-between; justify-content: space-between;
gap: 15px; gap: 15px;
} }
.overview_left, .overview_left {
flex: 3;
}
.overview_right { .overview_right {
width: 500px; flex: 1;
} }
.overview_center { .overview_center {
flex: 1; flex: 1;

View File

@ -197,7 +197,6 @@ export default function Create(props: MyBetaModalFormProps) {
value: 'value', value: 'value',
}, },
labelRender: (res: any) => { labelRender: (res: any) => {
console.log(res, '222');
if (res?.label) { if (res?.label) {
return res?.label; return res?.label;
} else { } else {

View File

@ -16,7 +16,7 @@ import {
} from '@/gen/Enums'; } from '@/gen/Enums';
import { ProTable } from '@ant-design/pro-components'; import { ProTable } from '@ant-design/pro-components';
import { useSearchParams } from '@umijs/max'; import { useSearchParams } from '@umijs/max';
import { Space, Tooltip } from 'antd'; import { Dropdown, Space, Tooltip } from 'antd';
import WorkOrderAssign from './modals/WorkOrderAssign'; import WorkOrderAssign from './modals/WorkOrderAssign';
import WorkOrderCreate from './modals/WorkOrderCreate'; import WorkOrderCreate from './modals/WorkOrderCreate';
import WorkOrderShow from './modals/WorkOrderShow'; import WorkOrderShow from './modals/WorkOrderShow';
@ -52,49 +52,48 @@ export default function Index({ title = '报修报事' }) {
}); });
}; };
let tableRender = (item: any, action: any) => { let tableRender = (item: any, action: any) => {
return getCurrentPermissions({ let permissions = getCurrentPermissions({
show: <WorkOrderShow item={item} title="详情" reload={action?.reload} />,
update: (
<>
{item.status === 'Pending' && (
<WorkOrderUpdate
item={item}
reload={action?.reload}
title={title}
/>
)}
</>
),
assign: ( assign: (
<> <WorkOrderAssign item={item} reload={action?.reload} title="指派" />
{item.assign_status === 'Unassigned' &&
item.type !== 'SecurityInspection' &&
item.status !== 'Closed' && (
<WorkOrderAssign
item={item}
reload={action?.reload}
title="指派"
/>
)}
</>
), ),
completed: ( completed: (
<> <WorkOrderShow item={item} title="回访" reload={action?.reload} />
{item.status === 'Completed' && item.is_visited === 0 && (
<WorkOrderShow item={item} title="回访" reload={action?.reload} />
)}
</>
),
delete: (
<MyButtons.Delete
onConfirm={() =>
Apis.WorkOrder.HouseWorkOrders.Delete({
id: item.id,
}).then(() => action?.reload())
}
/>
), ),
}); });
let permissionsSpace = getCurrentPermissions({
show: {
key: '1',
label: (
<WorkOrderShow item={item} title="详情" reload={action?.reload} />
),
},
update: {
key: '2',
label: (
<WorkOrderUpdate item={item} reload={action?.reload} title={title} />
),
},
delete: {
key: '3',
label: (
<MyButtons.Delete
onConfirm={() =>
Apis.WorkOrder.HouseWorkOrders.Delete({
id: item.id,
}).then(() => action?.reload())
}
/>
),
},
});
let Others = (
<Dropdown menu={{ items: permissionsSpace }} trigger={['click']}>
<MyButtons.Default title="更多" />
</Dropdown>
);
return [...permissions, ...[Others]];
}; };
return ( return (

View File

@ -33,7 +33,15 @@ export default function WorkOrderAssign(
labelCol={{ span: 5 }} labelCol={{ span: 5 }}
labelAlign="left" labelAlign="left"
trigger={ trigger={
<MyButtons.Default title={props.title || '指派'} type="primary" /> <MyButtons.Default
title={props.title || '指派'}
disabled={
props?.item.assign_status !== 'Unassigned' ||
props?.item.type === 'SecurityInspection' ||
props?.item.status === 'Closed'
}
type="primary"
/>
} }
key={new Date().getTime()} key={new Date().getTime()}
form={form} form={form}

View File

@ -41,7 +41,7 @@ export default function WorkOrderShow({
<> <>
<MyButtons.Default <MyButtons.Default
onClick={handleOpen} onClick={handleOpen}
disabled={item?.is_visited} disabled={item?.is_visited || item.status !== 'Completed'}
type={'primary'} type={'primary'}
title={title} title={title}
/> />

View File

@ -27,7 +27,7 @@ export default function WorkOrderUpdate(
width="600px" width="600px"
layout="horizontal" layout="horizontal"
key={new Date().getTime()} key={new Date().getTime()}
trigger={<MyButtons.Edit title={`编辑`} />} trigger={<MyButtons.Edit title={`编辑`} disabled={props.item?.status !== 'Pending'} />}
onOpenChange={(open: any) => { onOpenChange={(open: any) => {
if (open && props.item) { if (open && props.item) {
const formValues = { const formValues = {