mirror of
https://gitee.com/JavaLionLi/plus-ui.git
synced 2026-09-13 07:43:43 +08:00
update 升级 全部依赖版本与适配性代码修改
This commit is contained in:
parent
830eacbf02
commit
b1661081d6
18
package.json
18
package.json
@ -22,11 +22,11 @@
|
||||
"@ant-design/x": "^2.8.0",
|
||||
"@iconify/react": "^6.0.2",
|
||||
"@tanstack/react-query": "^5.101.2",
|
||||
"@umijs/max": "^4.6.68",
|
||||
"@wangeditor-next/editor": "^5.7.13",
|
||||
"@umijs/max": "^4.6.78",
|
||||
"@wangeditor-next/editor": "^5.7.16",
|
||||
"@wangeditor-next/editor-for-react": "^2.0.3",
|
||||
"ahooks": "^3.9.7",
|
||||
"antd": "^6.5.0",
|
||||
"antd": "^6.5.1",
|
||||
"antd-style": "^4.1.0",
|
||||
"axios": "1.18.1",
|
||||
"browser-image-compression": "^2.0.2",
|
||||
@ -39,7 +39,7 @@
|
||||
"nprogress": "0.2.0",
|
||||
"react": "^19.2.7",
|
||||
"react-dom": "^19.2.7",
|
||||
"react-easy-crop": "^6.0.2",
|
||||
"react-easy-crop": "^6.2.2",
|
||||
"react-json-view-lite": "^2.5.0",
|
||||
"react-syntax-highlighter": "^16.1.1",
|
||||
"screenfull": "^6.0.2",
|
||||
@ -47,20 +47,20 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/crypto-js": "4.2.2",
|
||||
"@types/node": "^26.0.1",
|
||||
"@types/node": "^26.1.1",
|
||||
"@types/nprogress": "0.2.3",
|
||||
"@types/react": "^19.2.17",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@types/react-syntax-highlighter": "^15.5.13",
|
||||
"@umijs/lint": "^4.6.68",
|
||||
"@umijs/lint": "^4.6.78",
|
||||
"@umijs/max-plugin-openapi": "^2.0.3",
|
||||
"cross-env": "^10.1.0",
|
||||
"oxfmt": "^0.56.0",
|
||||
"oxlint": "^1.71.0",
|
||||
"oxfmt": "^0.59.0",
|
||||
"oxlint": "^1.74.0",
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20.0.0",
|
||||
"node": ">=20.19.0",
|
||||
"pnpm": ">=10.0.0"
|
||||
}
|
||||
}
|
||||
|
||||
1905
pnpm-lock.yaml
generated
1905
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@ -173,7 +173,7 @@ export default function UserSelect({
|
||||
];
|
||||
|
||||
return (
|
||||
<Modal title={title} open={open} width="80%" onOk={confirm} onCancel={() => onOpenChange(false)} destroyOnHidden>
|
||||
<Modal title={title} open={open} width="80%" onOk={confirm} onCancel={() => onOpenChange(false)} forceRender>
|
||||
<div className={`user-select-react${treeCollapsed ? ' is-tree-collapsed' : ''}`}>
|
||||
<div className="user-select-tree-react">
|
||||
<div className="user-select-tree-head">
|
||||
|
||||
@ -55,7 +55,7 @@ export default function LayoutSettings({ open, value, onChange, onOpenChange }:
|
||||
<Drawer
|
||||
title="布局设置"
|
||||
open={open}
|
||||
width={320}
|
||||
size={320}
|
||||
onClose={() => onOpenChange(false)}
|
||||
className="layout-settings-drawer"
|
||||
>
|
||||
|
||||
@ -130,6 +130,7 @@ export default function MessageBox({ userId }: MessageBoxProps) {
|
||||
{currentItems.length ? (
|
||||
<List
|
||||
dataSource={currentItems}
|
||||
rowKey={item => String(item.messageId)}
|
||||
renderItem={item => (
|
||||
<List.Item className="message-box-item" onClick={() => readMessage(item)}>
|
||||
<div className="message-box-item-main">
|
||||
@ -162,7 +163,7 @@ export default function MessageBox({ userId }: MessageBoxProps) {
|
||||
trigger="click"
|
||||
content={content}
|
||||
arrow={false}
|
||||
overlayInnerStyle={{ width: 340 }}
|
||||
styles={{ container: { width: 340 } }}
|
||||
>
|
||||
<Tooltip title="消息盒子" open={tooltipOpen && !open} onOpenChange={setTooltipOpen}>
|
||||
<Badge className="message-box-badge" count={unreadCount} size="small" overflowCount={99} offset={[-5, 5]}>
|
||||
|
||||
@ -166,7 +166,7 @@ export default function SystemConfigPage() {
|
||||
<div className="system-config-page">
|
||||
<Tabs
|
||||
activeKey={activeConfigType}
|
||||
tabPosition="left"
|
||||
tabPlacement="start"
|
||||
className="system-config-page__tabs"
|
||||
items={configTypeTabs}
|
||||
onChange={changeConfigType}
|
||||
@ -211,7 +211,7 @@ export default function SystemConfigPage() {
|
||||
form={form}
|
||||
layout="vertical"
|
||||
initialValues={{ configType: 'Y' }}
|
||||
modalProps={{ destroyOnHidden: true, onCancel: closeModal }}
|
||||
modalProps={{ forceRender: true, onCancel: closeModal }}
|
||||
onOpenChange={open => !open && closeModal()}
|
||||
onFinish={submit}
|
||||
>
|
||||
|
||||
@ -40,7 +40,7 @@ export default function UserDetailDrawer({ open, userId, genderOptions, onClose
|
||||
};
|
||||
|
||||
return (
|
||||
<Drawer title="用户信息详情" open={open} width={680} onClose={closeDrawer} destroyOnHidden>
|
||||
<Drawer title="用户信息详情" open={open} size={680} onClose={closeDrawer} destroyOnHidden>
|
||||
<ProDescriptions
|
||||
loading={loading}
|
||||
column={2}
|
||||
|
||||
@ -19,8 +19,8 @@ import {
|
||||
Upload,
|
||||
type UploadProps
|
||||
} from 'antd';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import Cropper, { type Area, type Point } from 'react-easy-crop';
|
||||
import { useCallback, useEffect, useMemo, useState, type ComponentType } from 'react';
|
||||
import CropperModule, { type Area, type CropperProps, type Point } from 'react-easy-crop';
|
||||
import type { OnlineVO } from '@/api/monitor/online/types';
|
||||
import type { SocialAuthVO } from '@/api/system/social/types';
|
||||
import type { UserInfoVO, UserProfileForm } from '@/api/system/user/types';
|
||||
@ -37,10 +37,14 @@ import defaultAvatar from '@/assets/images/profile.jpg';
|
||||
import DictTag from '@/components/common/DictTag';
|
||||
import { useDict } from '@/hooks/useDict';
|
||||
import { useLoading } from '@/hooks/useLoading';
|
||||
import { dictOptions } from '@/utils/dict';
|
||||
import { usePermissionStore } from '@/stores/permissionStore';
|
||||
import { dictOptions } from '@/utils/dict';
|
||||
import { getUploadErrorMessage, validateUploadFile } from '@/utils/upload';
|
||||
|
||||
// react-easy-crop 6.2.x 的 CommonJS 类型声明遗漏了默认导出,运行时仍为默认组件。
|
||||
type CropperComponentProps = Partial<CropperProps> & Pick<CropperProps, 'crop' | 'onCropChange'>;
|
||||
const Cropper = CropperModule as unknown as ComponentType<CropperComponentProps>;
|
||||
|
||||
const socialProviders = [
|
||||
{ source: 'wechat', label: '微信', icon: wechatIcon },
|
||||
{ source: 'maxkey', label: 'MaxKey', icon: maxkeyIcon },
|
||||
|
||||
@ -43,7 +43,6 @@ import { toPageQuery, toTableData } from '@/utils/ruoyi';
|
||||
|
||||
type InstanceTab = 'running' | 'finish';
|
||||
|
||||
|
||||
function requestInstanceList(tab: InstanceTab, query: FlowInstanceQuery): Promise<R<PageResult<FlowInstanceVO>>> {
|
||||
if (tab === 'running') return pageByRunning(query);
|
||||
return pageByFinish(query);
|
||||
@ -152,7 +151,7 @@ export default function WorkflowProcessInstancePage() {
|
||||
const openVariable = async (row: FlowInstanceVO) => {
|
||||
setVariableRow(row);
|
||||
openVariableModal();
|
||||
variableForm.resetFields();
|
||||
if (canVariable) variableForm.resetFields();
|
||||
await withVariableLoading(async () => {
|
||||
const res = await instanceVariable(row.id);
|
||||
setVariableText(res.data.variable || '');
|
||||
@ -207,6 +206,7 @@ export default function WorkflowProcessInstancePage() {
|
||||
{
|
||||
title: '任务名称',
|
||||
dataIndex: 'nodeName',
|
||||
fieldProps: { id: 'workflow-process-instance-node-name' },
|
||||
width: 150,
|
||||
render: (_, row) => <EllipsisText value={row.nodeName} maxWidth={130} />
|
||||
},
|
||||
@ -367,7 +367,7 @@ export default function WorkflowProcessInstancePage() {
|
||||
open={invalidOpen}
|
||||
form={invalidForm}
|
||||
layout="vertical"
|
||||
modalProps={{ destroyOnHidden: true, onCancel: closeInvalidModal }}
|
||||
modalProps={{ forceRender: true, onCancel: closeInvalidModal }}
|
||||
onOpenChange={open => !open && closeInvalidModal()}
|
||||
onFinish={submitInvalid}
|
||||
>
|
||||
@ -379,14 +379,7 @@ export default function WorkflowProcessInstancePage() {
|
||||
/>
|
||||
</ModalForm>
|
||||
|
||||
<Modal
|
||||
title="流程变量"
|
||||
open={variableOpen}
|
||||
width={800}
|
||||
onCancel={closeVariableModal}
|
||||
footer={null}
|
||||
destroyOnHidden
|
||||
>
|
||||
<Modal title="流程变量" open={variableOpen} width={800} forceRender onCancel={closeVariableModal} footer={null}>
|
||||
<Card
|
||||
loading={variableLoading}
|
||||
title={variableRow?.flowName ? `流程定义名称:${variableRow.flowName}` : '流程变量'}
|
||||
|
||||
@ -2,7 +2,7 @@ import { BellOutlined, EyeOutlined, SettingOutlined, SwapOutlined, UserAddOutlin
|
||||
import { ModalForm, PageContainer, ProTable, type ActionType, type ProColumns } from '@ant-design/pro-components';
|
||||
import { useBoolean } from 'ahooks';
|
||||
import { Badge, Button, Form, message, Tabs } from 'antd';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useMemo, useRef, useState, type Key } from 'react';
|
||||
import type { UserVO } from '@/api/system/user/types';
|
||||
import type { PageResult, R } from '@/api/types';
|
||||
import type { FlowTaskVO, TaskQuery } from '@/api/workflow/task/types';
|
||||
@ -23,7 +23,9 @@ import { confirmTitleSafe } from '@/utils/modal';
|
||||
import { toPageQuery, toTableData } from '@/utils/ruoyi';
|
||||
type AllTaskTab = 'waiting' | 'finish';
|
||||
type UserSelectMode = 'applicant' | 'assignee';
|
||||
|
||||
type TaskTableRow = FlowTaskVO & {
|
||||
tableRowKey: string;
|
||||
};
|
||||
|
||||
function requestAllTaskList(tab: AllTaskTab, query: TaskQuery): Promise<R<PageResult<FlowTaskVO>>> {
|
||||
if (tab === 'waiting') return pageByAllTaskWait(query);
|
||||
@ -46,7 +48,8 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
const [urgeForm] = Form.useForm<{ message: string; messageType: string[] }>();
|
||||
const dicts = useDict('wf_business_status', 'wf_task_status', 'sys_normal_disable');
|
||||
const [activeTab, setActiveTab] = useState<AllTaskTab>('waiting');
|
||||
const [selectedRows, setSelectedRows] = useState<FlowTaskVO[]>([]);
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<Key[]>([]);
|
||||
const [selectedRows, setSelectedRows] = useState<TaskTableRow[]>([]);
|
||||
const [selectedApplicants, setSelectedApplicants] = useState<UserVO[]>([]);
|
||||
const [userModalOpen, { setTrue: openUserModal, setFalse: closeUserModal }] = useBoolean(false);
|
||||
const [userSelectMode, setUserSelectMode] = useState<UserSelectMode>('applicant');
|
||||
@ -56,7 +59,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
|
||||
const businessStatusOptions = useMemo(() => dictOptions(dicts.wf_business_status), [dicts.wf_business_status]);
|
||||
const taskStatusOptions = useMemo(() => dictOptions(dicts.wf_task_status), [dicts.wf_task_status]);
|
||||
const selectedTaskIds = selectedRows.map(item => item.id).filter(Boolean);
|
||||
const selectedTaskIds = [...new Set(selectedRows.map(item => item.id).filter(Boolean))];
|
||||
const selectedApplicantIds = selectedApplicants.map(item => item.userId).filter(Boolean) as Array<string | number>;
|
||||
const resetSearch = useSearchReset(
|
||||
actionRef,
|
||||
@ -65,6 +68,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
|
||||
const changeTab = (key: string) => {
|
||||
setActiveTab(key as AllTaskTab);
|
||||
setSelectedRowKeys([]);
|
||||
setSelectedRows([]);
|
||||
setTimeout(() => actionRef.current?.reloadAndRest?.(), 0);
|
||||
};
|
||||
@ -102,6 +106,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
await updateAssignee(selectedTaskIds, userId);
|
||||
message.success('操作成功');
|
||||
closeUserModal();
|
||||
setSelectedRowKeys([]);
|
||||
setSelectedRows([]);
|
||||
actionRef.current?.reload();
|
||||
return;
|
||||
@ -118,6 +123,8 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
await urgeTask({ ...values, taskIdList: selectedTaskIds });
|
||||
message.success('操作成功');
|
||||
urgeForm.resetFields();
|
||||
setSelectedRowKeys([]);
|
||||
setSelectedRows([]);
|
||||
actionRef.current?.reload();
|
||||
return true;
|
||||
};
|
||||
@ -127,7 +134,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
openMeddleModal();
|
||||
};
|
||||
|
||||
const columns: ProColumns<FlowTaskVO>[] = [
|
||||
const columns: ProColumns<TaskTableRow>[] = [
|
||||
{
|
||||
title: '业务编码',
|
||||
dataIndex: 'businessCode',
|
||||
@ -172,6 +179,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
{
|
||||
title: '任务名称',
|
||||
dataIndex: 'nodeName',
|
||||
fieldProps: { id: 'workflow-all-task-node-name' },
|
||||
width: 150,
|
||||
render: (_, row) => <EllipsisText value={row.nodeName} maxWidth={130} />
|
||||
},
|
||||
@ -208,7 +216,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
search: false,
|
||||
width: 120,
|
||||
fieldProps: { options: taskStatusOptions },
|
||||
render: (_: unknown, row: FlowTaskVO) => (
|
||||
render: (_: unknown, row: TaskTableRow) => (
|
||||
<DictTag options={dicts.wf_task_status} value={row.flowTaskStatus} />
|
||||
)
|
||||
}
|
||||
@ -246,17 +254,20 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
{ key: 'finish', label: '已办任务' }
|
||||
]}
|
||||
/>
|
||||
<ProTable<FlowTaskVO, TaskQuery>
|
||||
<ProTable<TaskTableRow, TaskQuery>
|
||||
actionRef={actionRef}
|
||||
rowKey="id"
|
||||
rowKey="tableRowKey"
|
||||
columns={columns}
|
||||
scroll={tableScroll}
|
||||
search={{ labelWidth: 100 }}
|
||||
form={{ onReset: resetSearch }}
|
||||
pagination={{ defaultPageSize: 10, showSizeChanger: true }}
|
||||
rowSelection={{
|
||||
selectedRowKeys: selectedTaskIds,
|
||||
onChange: (_, rows) => setSelectedRows(rows)
|
||||
selectedRowKeys,
|
||||
onChange: (keys, rows) => {
|
||||
setSelectedRowKeys(keys);
|
||||
setSelectedRows(rows);
|
||||
}
|
||||
}}
|
||||
request={async params => {
|
||||
const query = toPageQuery(params);
|
||||
@ -264,7 +275,14 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
...query,
|
||||
createByIds: selectedApplicantIds
|
||||
});
|
||||
return toTableData(res);
|
||||
const tableData = toTableData(res);
|
||||
return {
|
||||
...tableData,
|
||||
data: tableData.data.map((row, index) => ({
|
||||
...row,
|
||||
tableRowKey: `${activeTab}:${query.pageNum || 1}:${index}`
|
||||
}))
|
||||
};
|
||||
}}
|
||||
toolbar={{ title: activeTab === 'waiting' ? '全部待办任务' : '全部已办任务' }}
|
||||
toolBarRender={() => [
|
||||
@ -319,7 +337,7 @@ export default function WorkflowAllTaskWaitingPage() {
|
||||
form={urgeForm}
|
||||
layout="vertical"
|
||||
initialValues={{ messageType: ['1'] }}
|
||||
modalProps={{ destroyOnHidden: true, onCancel: closeUrgeModal }}
|
||||
modalProps={{ forceRender: true, onCancel: closeUrgeModal }}
|
||||
onOpenChange={open => !open && closeUrgeModal()}
|
||||
onFinish={submitUrge}
|
||||
>
|
||||
|
||||
@ -30,7 +30,6 @@ const pageTitle: Record<TaskListType, string> = {
|
||||
copy: '抄送任务'
|
||||
};
|
||||
|
||||
|
||||
function requestTaskList(type: TaskListType, query: TaskQuery): Promise<R<PageResult<FlowTaskVO>>> {
|
||||
if (type === 'wait') return pageByTaskWait(query);
|
||||
if (type === 'finish') return pageByTaskFinish(query);
|
||||
@ -98,6 +97,7 @@ export default function WorkflowTaskListPage({ type }: WorkflowTaskListPageProps
|
||||
{
|
||||
title: '任务名称',
|
||||
dataIndex: 'nodeName',
|
||||
fieldProps: { id: `workflow-task-${type}-node-name` },
|
||||
width: 150,
|
||||
render: (_, row) => <EllipsisText value={row.nodeName} maxWidth={130} />
|
||||
},
|
||||
|
||||
@ -31,9 +31,19 @@ function sortNotices(notices: NoticeItem[]) {
|
||||
return [...notices].sort((a, b) => Number(b.timestamp || 0) - Number(a.timestamp || 0));
|
||||
}
|
||||
|
||||
function dedupeNotices(notices: NoticeItem[]) {
|
||||
const messageIds = new Set<string>();
|
||||
return notices.filter(notice => {
|
||||
const messageId = String(notice.messageId);
|
||||
if (messageIds.has(messageId)) return false;
|
||||
messageIds.add(messageId);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
export const useNoticeStore = create<NoticeState>(set => ({
|
||||
notices: [],
|
||||
setNotices: notices => set({ notices: sortNotices(notices) }),
|
||||
setNotices: notices => set({ notices: sortNotices(dedupeNotices(notices)) }),
|
||||
addNotice: notice =>
|
||||
set(state => {
|
||||
const key = noticeKey(notice);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user