fix(web): 清零前端 TS 构建错误 — 31 文件类型修复 + 面包屑 + 超时配置
- 修复 verbatimModuleSyntax 要求的 import type 声明 - 修复未使用导入(Badge/EditOutlined/Space/Input/Switch 等) - 修复 mock.calls 类型注解([string,unknown] → any[]) - 修复 vitest 全局超时和 poolTimeout 配置 - 修复 PageContainer 缺少 onBack prop、MenuInfo children 可选 - 修复 CopilotAlert Badge status info→processing、useCopilotRisk 二次解包 - 修复 articles/doctors 测试 delete 调用缺少 version 参数 - 添加排班管理/预约管理面包屑标题 fallback
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import { createListPageTests } from '../../test/factories/listPageTests';
|
||||
import { createFixtureList, createAlertRuleFixture } from '../../test/fixtures';
|
||||
import { renderWithProviders } from '../../test/utils/renderWithProviders';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { screen, waitFor } from '@testing-library/react';
|
||||
import { waitFor } from '@testing-library/react';
|
||||
import { createListPageTests } from '../../test/factories/listPageTests';
|
||||
import { createFixtureList, createArticleFixture } from '../../test/fixtures';
|
||||
import { renderWithProviders } from '../../test/utils/renderWithProviders';
|
||||
|
||||
@@ -430,7 +430,7 @@ export default function BannerManage() {
|
||||
rowClassName={(record) =>
|
||||
record.status === 'inactive'
|
||||
? 'ant-table-row-inactive'
|
||||
: undefined
|
||||
: ''
|
||||
}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import {
|
||||
Button, Descriptions, Form, Input, message, Modal, Popconfirm, Select, Space, Table, Tag, Tabs,
|
||||
Button, Descriptions, Form, Input, message, Modal, Popconfirm, Select, Table, Tag, Tabs,
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback, useEffect } from 'react';
|
||||
import {
|
||||
Button, Form, Input, InputNumber, message, Modal, Popconfirm, Result, Select, Space, Switch, Table, Tag,
|
||||
Button, Form, Input, InputNumber, message, Modal, Popconfirm, Result, Select, Space, Table, Tag,
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import { Button, Input, message, Popconfirm, Result, Select, Space, Table, Tag, Badge } from 'antd';
|
||||
import { Button, message, Popconfirm, Result, Select, Space, Table, Tag, Badge } from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
|
||||
@@ -191,9 +191,9 @@ export default function DoctorList() {
|
||||
};
|
||||
|
||||
// ---- 删除 ----
|
||||
const handleDelete = async (id: string) => {
|
||||
const handleDelete = async (id: string, version: number) => {
|
||||
try {
|
||||
await doctorApi.delete(id);
|
||||
await doctorApi.delete(id, version);
|
||||
message.success('删除成功');
|
||||
refresh();
|
||||
} catch {
|
||||
@@ -286,7 +286,7 @@ export default function DoctorList() {
|
||||
</Button>
|
||||
<Popconfirm
|
||||
title="确定删除该医护?"
|
||||
onConfirm={() => handleDelete(record.id)}
|
||||
onConfirm={() => handleDelete(record.id, record.version)}
|
||||
okText="确定"
|
||||
cancelText="取消"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback } from 'react';
|
||||
import {
|
||||
Button, Card, Descriptions, Form, Input, message, Modal, Popconfirm, Result, Select, Space, Table, Tag,
|
||||
Button, Card, Descriptions, Form, message, Modal, Popconfirm, Result, Select, Space, Table, Tag,
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
Popconfirm, InputNumber, Switch, Card, Typography,
|
||||
} from 'antd';
|
||||
import {
|
||||
PlusOutlined, DeleteOutlined, EditOutlined,
|
||||
PlusOutlined, DeleteOutlined,
|
||||
} from '@ant-design/icons';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
import {
|
||||
@@ -35,9 +35,9 @@ const FIELD_TYPE_OPTIONS = [
|
||||
{ value: 'scale', label: '量表' },
|
||||
];
|
||||
|
||||
function FieldEditor({ value, onChange }: {
|
||||
value: TemplateFieldReq[];
|
||||
onChange: (v: TemplateFieldReq[]) => void;
|
||||
function FieldEditor({ value = [], onChange = () => {} }: {
|
||||
value?: TemplateFieldReq[];
|
||||
onChange?: (v: TemplateFieldReq[]) => void;
|
||||
}) {
|
||||
const add = () => {
|
||||
onChange([...value, {
|
||||
|
||||
@@ -194,9 +194,9 @@ export default function MediaLibrary() {
|
||||
</div>
|
||||
<div style={{ flex: 1, overflow: 'auto', padding: '8px 4px' }}>
|
||||
{foldersLoading ? <div style={{ textAlign: 'center', padding: 20 }}><Spin size="small" /></div> : (
|
||||
<Tree defaultExpandAll selectedKeys={folderId ? [folderId] : ['__all__']} treeData={treeData}
|
||||
<Tree defaultExpandAll selectedKeys={folderId ? [folderId] : ['__all__']} treeData={treeData as any}
|
||||
fieldNames={{ title: 'name', key: 'id', children: 'children' }} onSelect={handleFolderSelect}
|
||||
titleRender={(node: TreeNode) => {
|
||||
titleRender={(node: any) => {
|
||||
if (node.id === '__all__') return <span>{node.name}</span>;
|
||||
const matched = folders.find((f) => f.id === node.id);
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useState, useCallback, useEffect, useMemo } from 'react';
|
||||
import { useState, useCallback, useMemo } from 'react';
|
||||
import {
|
||||
Button, DatePicker, Form, Input, message, Modal, Popconfirm,
|
||||
Result, Select, Space, Switch, Table, Tag,
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { server } from '../../test/mocks/server';
|
||||
import { createListPageTests } from '../../test/factories/listPageTests';
|
||||
import { createFixtureList, createPatientFixture } from '../../test/fixtures';
|
||||
import PatientList from './PatientList';
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useVitalSSE } from '../../hooks/useVitalSSE';
|
||||
import { usePermission } from '../../hooks/usePermission';
|
||||
import { alertApi, type Alert } from '../../api/health/alerts';
|
||||
import { PageContainer } from '../../components/PageContainer';
|
||||
import { SEVERITY_COLOR, SEVERITY_LABEL, VITAL_CARD_METRICS } from '../../constants/health';
|
||||
import { VITAL_CARD_METRICS } from '../../constants/health';
|
||||
|
||||
interface PatientAlertSummary {
|
||||
patient_id: string;
|
||||
@@ -22,7 +22,7 @@ interface PatientAlertSummary {
|
||||
*/
|
||||
export default function RealtimeMonitor() {
|
||||
const { hasPermission } = usePermission('health.alerts.list');
|
||||
const [alerts, setAlerts] = useState<Alert[]>([]);
|
||||
const [_alerts, setAlerts] = useState<Alert[]>([]);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [selectedPatientId, setSelectedPatientId] = useState<string | null>(null);
|
||||
const [alertSummary, setAlertSummary] = useState<PatientAlertSummary[]>([]);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState, useCallback, useEffect, useMemo } from 'react';
|
||||
import {
|
||||
Badge, Button, DatePicker, Form, Input, message, Modal, Popconfirm,
|
||||
Button, DatePicker, Form, Input, message, Modal, Popconfirm,
|
||||
Result, Select, Space, Table, Tag,
|
||||
} from 'antd';
|
||||
import type { ColumnsType } from 'antd/es/table';
|
||||
|
||||
@@ -14,7 +14,7 @@ interface ArticleStyleLibraryProps {
|
||||
onThemeChange: (themeId: string) => void;
|
||||
}
|
||||
|
||||
const sectionLabel = (text: string, isDark: boolean) => ({
|
||||
const sectionLabel = (_text: string, isDark: boolean) => ({
|
||||
fontSize: 12,
|
||||
fontWeight: 600,
|
||||
color: isDark ? '#64748b' : '#86868b',
|
||||
|
||||
@@ -19,7 +19,7 @@ function parseStyleStr(str: string): Record<string, string> {
|
||||
const renderElemConf = {
|
||||
type: TYPE,
|
||||
renderElem(elemNode: SlateElement): VNode {
|
||||
const node = elemNode as Record<string, unknown>;
|
||||
const node = elemNode as unknown as Record<string, unknown>;
|
||||
const style = (node.style as string) || '';
|
||||
const innerHtml = (node.innerHtml as string) || '';
|
||||
return h(
|
||||
@@ -44,7 +44,7 @@ const renderElemConf = {
|
||||
const elemToHtmlConf = {
|
||||
type: TYPE,
|
||||
elemToHtml(elemNode: SlateElement): string {
|
||||
const node = elemNode as Record<string, unknown>;
|
||||
const node = elemNode as unknown as Record<string, unknown>;
|
||||
const style = (node.style as string) || '';
|
||||
const innerHtml = (node.innerHtml as string) || '';
|
||||
return `<div data-w-e-type="${TYPE}" style="${style}">${innerHtml}</div>`;
|
||||
@@ -53,7 +53,7 @@ const elemToHtmlConf = {
|
||||
|
||||
const parseElemHtmlConf = {
|
||||
selector: `div[data-w-e-type="${TYPE}"]`,
|
||||
parseElemHtml($elem: HTMLElement): SlateElement {
|
||||
parseElemHtml($elem: Element): SlateElement {
|
||||
return {
|
||||
type: TYPE,
|
||||
style: $elem.getAttribute('style') || '',
|
||||
|
||||
@@ -38,6 +38,7 @@ interface ActionDetailDrawerProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
onActionComplete?: () => void;
|
||||
onRefresh?: () => void;
|
||||
}
|
||||
|
||||
export default function ActionDetailDrawer({
|
||||
@@ -45,6 +46,7 @@ export default function ActionDetailDrawer({
|
||||
open,
|
||||
onClose,
|
||||
onActionComplete,
|
||||
onRefresh: _onRefresh,
|
||||
}: ActionDetailDrawerProps) {
|
||||
const [thread, setThread] = useState<ThreadResponse | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
Reference in New Issue
Block a user