更新需求

This commit is contained in:
xx
2026-02-05 11:25:03 +08:00
parent 513e113ea9
commit abc0a6051d
12 changed files with 81 additions and 28 deletions

15
package-lock.json generated
View File

@@ -76,6 +76,7 @@
"integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.5", "@babel/generator": "^7.28.5",
@@ -1835,6 +1836,7 @@
"integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"undici-types": "~7.16.0" "undici-types": "~7.16.0"
} }
@@ -1845,6 +1847,7 @@
"integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"csstype": "^3.2.2" "csstype": "^3.2.2"
} }
@@ -1905,6 +1908,7 @@
"integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==", "integrity": "sha512-lJi3PfxVmo0AkEY93ecfN+r8SofEqZNGByvHAI3GBLrvt1Cw6H5k1IM02nSzu0RfUafr2EvFSw0wAsZgubNplQ==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@typescript-eslint/scope-manager": "8.47.0", "@typescript-eslint/scope-manager": "8.47.0",
"@typescript-eslint/types": "8.47.0", "@typescript-eslint/types": "8.47.0",
@@ -2153,6 +2157,7 @@
"integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"bin": { "bin": {
"acorn": "bin/acorn" "acorn": "bin/acorn"
}, },
@@ -2367,6 +2372,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"baseline-browser-mapping": "^2.8.25", "baseline-browser-mapping": "^2.8.25",
"caniuse-lite": "^1.0.30001754", "caniuse-lite": "^1.0.30001754",
@@ -2775,6 +2781,7 @@
"integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/eslint-utils": "^4.8.0",
"@eslint-community/regexpp": "^4.12.1", "@eslint-community/regexpp": "^4.12.1",
@@ -3888,6 +3895,7 @@
} }
], ],
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"nanoid": "^3.3.11", "nanoid": "^3.3.11",
"picocolors": "^1.1.1", "picocolors": "^1.1.1",
@@ -4089,6 +4097,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz",
"integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -4098,6 +4107,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz",
"integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"scheduler": "^0.27.0" "scheduler": "^0.27.0"
}, },
@@ -4493,6 +4503,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -4552,6 +4563,7 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"dev": true, "dev": true,
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -4645,6 +4657,7 @@
"integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==", "integrity": "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"esbuild": "^0.25.0", "esbuild": "^0.25.0",
"fdir": "^6.5.0", "fdir": "^6.5.0",
@@ -4738,6 +4751,7 @@
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=12" "node": ">=12"
}, },
@@ -4810,6 +4824,7 @@
"integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==",
"dev": true, "dev": true,
"license": "MIT", "license": "MIT",
"peer": true,
"funding": { "funding": {
"url": "https://github.com/sponsors/colinhacks" "url": "https://github.com/sponsors/colinhacks"
} }

View File

@@ -4,7 +4,7 @@
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "export NODE_ENV=development && vite --host 0.0.0.0", "dev": "export NODE_ENV=development && vite --host 0.0.0.0 --port 5777",
"build": "tsc -b && vite build", "build": "tsc -b && vite build",
"lint": "eslint .", "lint": "eslint .",
"preview": "vite preview" "preview": "vite preview"

View File

@@ -4,7 +4,11 @@ import { RouterProvider } from 'react-router-dom';
import { router } from './router'; import { router } from './router';
function App() { function App() {
return <RouterProvider router={router} />; return (
<div className='h-screen max-h-screen overflow-hidden'>
<RouterProvider router={router} />
</div>
);
} }
export default App; export default App;

View File

@@ -11,7 +11,7 @@ const API_CONFIG = {
// 开发环境使用内网,生产环境使用外网 // 开发环境使用内网,生产环境使用外网
BASE_URL: import.meta.env.NODE_ENV === 'development' BASE_URL: import.meta.env.NODE_ENV === 'development'
? 'http://10.1.5.118:8077/platform-api' ? 'http://10.1.5.118:8077/platform-api'
: 'http://apihis.circleharmonyhospital.cn:8982/platform-api', : '/platform-api',
// 请求超时时间120秒 // 请求超时时间120秒
TIMEOUT: 120000, TIMEOUT: 120000,
}; };

View File

@@ -16,6 +16,7 @@ interface ExamDetailPanelProps {
addItemInfoList: CustomerExamAddItem[] | null; addItemInfoList: CustomerExamAddItem[] | null;
progressList: PhysicalExamProgressItem[] | null; progressList: PhysicalExamProgressItem[] | null;
loading: boolean; loading: boolean;
onCustomerUpdated?: () => void;
} }
const getMaritalCodeFromText = (text: string): number => { const getMaritalCodeFromText = (text: string): number => {
@@ -33,6 +34,7 @@ export const ExamDetailPanel = ({
addItemInfoList, addItemInfoList,
progressList, progressList,
loading, loading,
onCustomerUpdated,
}: ExamDetailPanelProps) => { }: ExamDetailPanelProps) => {
const basePhone = customerInfo?.phone || (client['mobile' as keyof ExamClient] as string | undefined) || ''; const basePhone = customerInfo?.phone || (client['mobile' as keyof ExamClient] as string | undefined) || '';
const baseMaritalText = const baseMaritalText =
@@ -108,6 +110,7 @@ export const ExamDetailPanel = ({
if (res.Status === 200) { if (res.Status === 200) {
setEditMessage('保存成功'); setEditMessage('保存成功');
setPhoneEditing(false); setPhoneEditing(false);
onCustomerUpdated?.();
setTimeout(() => setEditMessage(null), 2000); setTimeout(() => setEditMessage(null), 2000);
} else { } else {
setEditMessage(res.Message || '保存失败'); setEditMessage(res.Message || '保存失败');
@@ -140,6 +143,7 @@ export const ExamDetailPanel = ({
if (res.Status === 200) { if (res.Status === 200) {
setEditMessage('保存成功'); setEditMessage('保存成功');
setMaritalEditing(false); setMaritalEditing(false);
onCustomerUpdated?.();
setTimeout(() => setEditMessage(null), 2000); setTimeout(() => setEditMessage(null), 2000);
} else { } else {
setEditMessage(res.Message || '保存失败'); setEditMessage(res.Message || '保存失败');

View File

@@ -76,6 +76,16 @@ export const ExamModal = ({ client, tab, onTabChange, onClose }: ExamModalProps)
.finally(() => setDetailLoading(false)); .finally(() => setDetailLoading(false));
}, [client.id]); }, [client.id]);
const refetchDetail = () => {
const physical_exam_id = Number(client.id);
if (!physical_exam_id) return;
getCustomerDetail({ physical_exam_id }).then((detailRes) => {
setCustomerInfo(detailRes.Data?.customerInfo ?? null);
setAppointmentInfo(detailRes.Data?.appointmentInfo ?? null);
setAddItemInfoList(detailRes.Data?.addItemInfoList ?? null);
});
};
return ( return (
<div <div
className='fixed inset-0 z-40 flex items-center justify-center bg-black/50' className='fixed inset-0 z-40 flex items-center justify-center bg-black/50'
@@ -153,6 +163,7 @@ export const ExamModal = ({ client, tab, onTabChange, onClose }: ExamModalProps)
addItemInfoList={addItemInfoList} addItemInfoList={addItemInfoList}
progressList={progressList} progressList={progressList}
loading={detailLoading} loading={detailLoading}
onCustomerUpdated={refetchDetail}
/> />
)} )}
{tab === 'sign' && <ExamSignPanel examId={Number(client.id)} onBusyChange={setSignBusy} />} {tab === 'sign' && <ExamSignPanel examId={Number(client.id)} onBusyChange={setSignBusy} />}

View File

@@ -22,10 +22,18 @@ const NAV_ITEMS = [
{ key: 'support', icon: IconSupport, label: '客服咨询' }, { key: 'support', icon: IconSupport, label: '客服咨询' },
] as const; ] as const;
const toggleFullscreen = () => {
if (!document.fullscreenElement) {
document.documentElement.requestFullscreen?.();
} else {
document.exitFullscreen?.();
}
};
export const Sidebar = ({ active, onNavigate, onQuickAction }: SidebarProps) => ( export const Sidebar = ({ active, onNavigate, onQuickAction }: SidebarProps) => (
<aside className='bg-white border-r p-4 flex flex-col gap-4'> <aside className='h-screen max-h-screen bg-white border-r p-4 flex flex-col gap-4 overflow-hidden'>
<div> <div>
<div className='text-base font-semibold'> · </div> <button type='button' onClick={toggleFullscreen} className='text-base font-semibold cursor-pointer hover:opacity-80 text-left'> · </button>
<div className='text-xs text-gray-500 mt-1'></div> <div className='text-xs text-gray-500 mt-1'></div>
</div> </div>
@@ -73,13 +81,13 @@ export const Sidebar = ({ active, onNavigate, onQuickAction }: SidebarProps) =>
</div> </div>
</section> </section>
<section className='mt-auto p-3 rounded-2xl border bg-gray-50/70 text-xs flex flex-col gap-2'> {/* <section className='mt-auto p-3 rounded-2xl border bg-gray-50/70 text-xs flex flex-col gap-2'>
<div className='text-sm font-medium flex items-center gap-2'> <div className='text-sm font-medium flex items-center gap-2'>
<span>💻</span> <span>💻</span>
<span>客服 / IT 支持</span> <span>客服 / IT 支持</span>
</div> </div>
<div className='text-gray-600'>遇到系统问题可一键联系 IT / 运营支持。</div> <div className='text-gray-600'>遇到系统问题可一键联系 IT / 运营支持。</div>
</section> </section> */}
</aside> </aside>
); );

View File

@@ -28,18 +28,18 @@ export const TopBar = ({ enableSearch = true, operatorName, onLoginClick, onLogo
return ( return (
<header className='flex items-center gap-3 p-2 border-b bg-white'> <header className='flex items-center gap-3 p-2 border-b bg-white'>
<div className='flex-1 flex items-center gap-3'> <div className='flex-1 flex items-center gap-3'>
{enableSearch ? ( {/* {enableSearch ? (
<div className='w-[420px] max-w-[60vw] h-[36px] flex items-center'> <div className='w-[420px] max-w-[60vw] h-[36px] flex items-center'>
{/* <Input <Input
placeholder='搜索 姓名 / 证件号 / 手机号' placeholder='搜索 姓名 / 证件号 / 手机号'
value={search} value={search}
onChange={(e) => onSearch(e.target.value)} onChange={(e) => onSearch(e.target.value)}
className='text-sm' className='text-sm'
/> */} />
</div> </div>
) : ( ) : (
<div className='text-sm text-gray-500 flex items-center p-[9px] pl-[14px]'>圆和医疗 · 体检驾驶舱</div> <div className='text-sm text-gray-500 flex items-center p-[9px] pl-[14px]'>圆和医疗 · 体检驾驶舱</div>
)} )} */}
</div> </div>
<div className='flex items-center gap-3 text-xs relative'> <div className='flex items-center gap-3 text-xs relative'>
<button <button

View File

@@ -95,9 +95,9 @@ export const NoteModal = ({ noteText, onNoteChange, onClose }: NoteModalProps) =
{saving ? '保存中...' : '保存'} {saving ? '保存中...' : '保存'}
</button> </button>
</div> </div>
<div className='text-right text-[11px] text-gray-500'> {/* <div className='text-right text-[11px] text-gray-500'>
备注内容会同步至客户详情页,供前台和导检护士查看。 备注内容会同步至客户详情页,供前台和导检护士查看。
</div> </div> */}
</div> </div>
</div> </div>
</div> </div>

View File

@@ -2,10 +2,10 @@ import { Card, CardContent, CardHeader } from '../ui';
export const SupportSection = () => ( export const SupportSection = () => (
<Card> <Card>
<CardHeader> · </CardHeader> {/* <CardHeader>客服咨询 · 圆圆客服台卡</CardHeader> */}
<CardContent> <CardContent>
<div className='grid grid-cols-[1.2fr_1fr] gap-6 items-center'> <div className='items-center'>
<div className='space-y-3 text-sm text-gray-700'> {/* <div className='space-y-3 text-sm text-gray-700'>
<p>通过「圆圆客服」二维码,客户可获得一站式健康服务:包含体检预约、报告查询、报告解读等。</p> <p>通过「圆圆客服」二维码,客户可获得一站式健康服务:包含体检预约、报告查询、报告解读等。</p>
<ul className='list-disc ml-5 space-y-1 text-xs text-gray-600'> <ul className='list-disc ml-5 space-y-1 text-xs text-gray-600'>
<li>支持体检当天现场扫码添加,绑定客户信息</li> <li>支持体检当天现场扫码添加,绑定客户信息</li>
@@ -13,19 +13,19 @@ export const SupportSection = () => (
<li>提供一对一健康咨询与报告解读服务</li> <li>提供一对一健康咨询与报告解读服务</li>
</ul> </ul>
<div className='text-xs text-gray-500'>注:实际系统中可上传设计好的「圆圆客服二维码台卡」图片,用于前台展示与打印。</div> <div className='text-xs text-gray-500'>注:实际系统中可上传设计好的「圆圆客服二维码台卡」图片,用于前台展示与打印。</div>
</div> </div> */}
<div className='h-64 rounded-3xl overflow-hidden shadow-inner flex items-center justify-center bg-gradient-to-b from-[#152749] to-[#c73545]'> <div className='h-[70vh] rounded-3xl overflow-hidden shadow-inner flex items-center justify-center bg-gradient-to-b from-[#152749] to-[#c73545]'>
<div className='flex flex-col items-center gap-3 text-white'> <div className='flex flex-col items-center gap-5 text-white'>
<div className='text-[11px] tracking-[0.2em] opacity-80'>CIRCLE HARMONY · </div> <div className='text-base tracking-[0.2em] opacity-80'>CIRCLE HARMONY · </div>
<div className='text-sm font-medium'> · </div> <div className='text-lg font-medium'> · </div>
<div className='w-28 h-28 bg-none flex items-center justify-center'> <div className='w-72 h-72 bg-none flex items-center justify-center'>
<div className='w-30 h-30 rounded-md overflow-hidden'> <div className='w-72 h-72 rounded-md overflow-hidden'>
<img src="https://datacenter-open.oss-cn-hangzhou.aliyuncs.com/his/kefu-zixun.png" alt='圆圆客服二维码' className='w-full h-full object-cover' /> <img src="https://datacenter-open.oss-cn-hangzhou.aliyuncs.com/his/kefu-zixun.png" alt='圆圆客服二维码' className='w-full h-full object-cover' />
</div> </div>
</div> </div>
<div className='text-sm font-semibold'></div> <div className='text-lg font-semibold'></div>
<div className='px-4 py-1.5 rounded-full border border-white/70 text-[11px] flex gap-2'> <div className='px-6 py-2 rounded-full border border-white/70 text-sm flex gap-2'>
<span></span> <span></span>
<span>/</span> <span>/</span>
<span></span> <span></span>

View File

@@ -7,17 +7,21 @@
scrollbar-width: none; scrollbar-width: none;
scrollbar-color: #cbd5e1 #f8fafc; scrollbar-color: #cbd5e1 #f8fafc;
} }
.custom-scroll::-webkit-scrollbar { .custom-scroll::-webkit-scrollbar {
width: 8px; width: 8px;
} }
.custom-scroll::-webkit-scrollbar-track { .custom-scroll::-webkit-scrollbar-track {
background: #f8fafc; background: #f8fafc;
border-radius: 9999px; border-radius: 9999px;
} }
.custom-scroll::-webkit-scrollbar-thumb { .custom-scroll::-webkit-scrollbar-thumb {
background: #cbd5e1; background: #cbd5e1;
border-radius: 9999px; border-radius: 9999px;
} }
.custom-scroll::-webkit-scrollbar-thumb:hover { .custom-scroll::-webkit-scrollbar-thumb:hover {
background: #94a3b8; background: #94a3b8;
} }
@@ -30,9 +34,13 @@
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
} }
body { html,
body,
#root {
margin: 0; margin: 0;
min-height: 100vh; height: 100%;
max-height: 100%;
overflow: hidden;
background-color: #f8fafc; background-color: #f8fafc;
} }

View File

@@ -4,4 +4,7 @@ import react from '@vitejs/plugin-react-swc'
// https://vite.dev/config/ // https://vite.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], plugins: [react()],
server: {
allowedHosts: ['ipad.shenynet.com'],
},
}) })