add
This commit is contained in:
307
2026届网络工程毕业设计论文撰写规范-(应用开发类).md
Normal file
307
2026届网络工程毕业设计论文撰写规范-(应用开发类).md
Normal file
@@ -0,0 +1,307 @@
|
||||
# 2026届网络工程毕业设计
|
||||
|
||||
# 论文撰写规范(应用开发类)
|
||||
|
||||
中文摘要 (3-5 个关键词)
|
||||
|
||||
# 英文摘要
|
||||
|
||||
# 目录
|
||||
|
||||
# 第1章绪论
|
||||
|
||||
1.1 课题来源及意义
|
||||
|
||||
1.2 课题研究现状
|
||||
|
||||
1.3当前存在的问题
|
||||
|
||||
1.4 课题研究目标
|
||||
|
||||
# 第2章主要技术和框架
|
||||
|
||||
2.1 主要技术 (开发系统或平台所需相关技术的介绍)
|
||||
|
||||
# 2.2 框架和开发模式(开发系统或平台所使用的框架和开发模式的介绍)
|
||||
|
||||
# 第3章XXXXX的系统分析
|
||||
|
||||
# 3.1需求分析(包括功能需求分析和性能需求分析)
|
||||
|
||||
3.2可行性分析(包括技术可行性、操作可行性、经济可行性,社会可行性等)
|
||||
|
||||
3.3 用例图(根据系统角色划分用例图,若有两个角色就有两个用例图)
|
||||
|
||||
3.3.1 用户用例图(需先对用例图进行描述,其实也就是对该系统的用户角色进行权限分析,再画出具体用户用例图,用例图如下所示)
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图3.1用户用例图
|
||||
|
||||
|
||||
3.3.2 管理员用例图(需先对用例图进行描述,其实也就是对该系统的用户角色进行权限分析,再画出具体用户用例图,用例图如下所示)
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图3.2管理员用例图
|
||||
|
||||
|
||||
3.4 用例描述(用例描述是对用例图中用例的详细说明,它详细阐述了用例的功
|
||||
|
||||
能实现过程、输入输出、前置条件、后置条件以及可能的异常情况等,是对用例图
|
||||
|
||||
的补充和细化,使系统功能更加清晰具体。需分别对每个用例列举3个左右的用
|
||||
|
||||
例描述。)
|
||||
|
||||
例:(1)用户管理地址用例描述如下表3.1所示。
|
||||
|
||||
|
||||
表 3.1 用户管理地址用例描述
|
||||
|
||||
|
||||
<table><tr><td>用例名称:管理地址</td></tr><tr><td>执行者:用户</td></tr><tr><td>简要说明:用户对收货地址进行添加、修改、删除等管理操作</td></tr><tr><td>基本事件流:
|
||||
1.用户登录平台,进入地址管理界面
|
||||
2.系统显示已有地址列表
|
||||
3.用户选择添加新地址,输入详细地址信息,验证通过后存储地址
|
||||
4.若修改地址,系统更新后提示成功,若删除地址,确认操作后数据库移除该地址记录</td></tr><tr><td>(2)用户查看商品用例描述如下表3.2所示。
|
||||
表3.2用户查看商品用例</td></tr><tr><td>用例名称:查看商品</td></tr><tr><td>执行者:用户</td></tr><tr><td>简要说明:用户分类浏览平台上的闲置商品</td></tr><tr><td>基本事件流:
|
||||
1.用户登录平台,进入查看商品界面
|
||||
2.选择商品分类,如闲置书籍、衣服、手机等;
|
||||
3.系统加载并显示该分类下的商品列表
|
||||
4.用户可点击具体商品,查看详细信息,如介绍、图片、价格等</td></tr></table>
|
||||
|
||||
# 3.5 系统性能分析
|
||||
|
||||
# 第4章XXXXX的系统设计
|
||||
|
||||
4.1系统功能设计(先总体概述一段该系统的主要角色有哪几个,分别包含什么主
|
||||
|
||||
要功能,再给出功能结构图。)
|
||||
|
||||
具体如图4.1和图4.2所示。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.1用户功能结构图
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.2管理员功能结构图
|
||||
|
||||
|
||||
4.2 类图(根据给定的初步类图,详细描述每个类的属性、方法以及类之间的具体关系。)
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.3系统类图
|
||||
|
||||
|
||||
4.3 序列图(展示了对象之间随时间顺序发生的消息传递,通常用于描述用例的实现过程或系统中某个功能的动态行为。至少需列举系统角色各一个序列图,在给出序列图之前还需将过程的详细步骤写出。如:用户登录序列图、管理员删除账号序列图。)
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.4用户购买商品功能序列图
|
||||
|
||||
|
||||
4.4 活动图(活动图可以清晰地描述系统的动态行为和工作流程。例如,在描述一个在线购物系统的订单处理流程时,可以通过活动图展示从用户下单到订单完成的各个步骤。论文中至少需描述各个角色各一个活动的活动图,如用户更新个人信息活动图,管理员删除用户信息活动图。)
|
||||
|
||||
# 4.4.1 用户填写个人信息活动图
|
||||
|
||||
用户填写个人信息过程可分为以下几步:
|
||||
|
||||
(1) 用户输入验证账号密码。
|
||||
|
||||
(2) 数据库查询用户数据,并判断用户是否存在。
|
||||
|
||||
(3) 登录成功后,用户填写个人信息并提交。
|
||||
|
||||
(4) 系统接收提交的个人信息后,将其发送至数据库进行更新保存。
|
||||
|
||||
(5) 用户确认信息更新无误后,更新界面。
|
||||
|
||||
用户填写个人信息活动图如下图4.7所示。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.7 用户填写个人信息活动图
|
||||
|
||||
|
||||
# 4.5 数据库设计
|
||||
|
||||
撰写说明:
|
||||
|
||||
本章是重点章节,很多同学搞不清概念设计、逻辑设计和物理设计的关系,请参见另外一个文档《2026届网络工程毕业论文第4章-数据库设计撰写规范(应用开发类补充说明).docx》:
|
||||
|
||||
4.5.1 概念设计(概念设计包括两部分:实体属性图(不少于8个实体,每个实体
|
||||
|
||||
标明属性图的主码)和总体E-R图)
|
||||
|
||||
# (1) 管理员实体
|
||||
|
||||
管理员实体属性图如图4.9所示。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.9管理员实体属性图
|
||||
|
||||
|
||||
# (2)用户实体
|
||||
|
||||
用户实体属性图如图4.10所示。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.10用户实体属性图
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4.系统E-R图(标明各个实体之间的关联)
|
||||
|
||||
|
||||
4.5.2 逻辑设计(将E-R图中的实体关系转换为逻辑结构设计,即关系模式。
|
||||
|
||||
其中,一个实体转换为 1 个单独的关系模式。
|
||||
|
||||
实体间联系有3种,1:1,1:n,n:m。
|
||||
|
||||
1:n 联系要将 1 端实体如用户的主码加入到 n 端如评论实体的关系模式中。
|
||||
|
||||
n:m 联系要将联系如上图中的购买转换成一个单独的关系模式,并将两端的主
|
||||
|
||||
码放入该关系模式作为属性。)关系模式中需标明主外码
|
||||
|
||||
上图转换为逻辑结构如下所示:
|
||||
|
||||
(1) 用户表:(用户 id, 用户账号, 密码, 用户姓名, 性别, 联系电话, 头像, 积分,余额)
|
||||
|
||||
(2) 管理员表: (管理员 id, 创建时间, 管理员名称, 密码, 管理员类型)
|
||||
|
||||
(3) 收货地址表:(收货地址id,用户id,地址,收货人,电话,是否为默认地址)
|
||||
|
||||
(4) 购物车表:(购物车id,商品表名,商品,商品名称,图片,购买数量,单价,会员价,商品类型)
|
||||
|
||||
(5) 订单表:(订单id,订单编号,用户id,规格,上架时间,商品详情,团购价,拼团人数)
|
||||
|
||||
(6) 团购商品表:(团购商品id,购买数量,价格,折扣价,总价,商品类型id,支付类型,物流,购物车id)
|
||||
|
||||
(7) 商品类型表:(商品类型 id,创建时间,类型数量)
|
||||
|
||||
(8) 评论表:(评论id,用户id,头像,用户名,评论内容,回复内容)
|
||||
|
||||
(9) 公告表:(公告id,创建时间,标题,简介,图片,内容,管理员id)
|
||||
|
||||
(10) 购买表:(用户 id,团购商品 id,购买日期,购买时间)(购买表的外键为:
|
||||
|
||||
用户id,团购商品id)
|
||||
|
||||
4.5.3 物理设计(将上述关系模式转换为一个个物理表结构,一个关系模式转换为一个物理表,至少包含8张物理表)
|
||||
|
||||
如:(1)系统根据MySQL数据库数据存储的特性设计数据库关系表:
|
||||
|
||||
|
||||
表 4.1 管理员表 (admin 表)
|
||||
|
||||
|
||||
<table><tr><td>字段名称</td><td>字段意义</td><td>数据类型</td><td>长度</td><td>完整性约束</td></tr><tr><td>admin_id</td><td>管理员 id</td><td>int</td><td>10</td><td>主键</td></tr><tr><td>admin_name</td><td>管理员姓名</td><td>varchar</td><td>10</td><td>非空</td></tr><tr><td>admin_password</td><td>管理员密码</td><td>varchar</td><td>20</td><td>非空</td></tr><tr><td>admin_email</td><td>管理员邮箱</td><td>varchar</td><td>20</td><td>非空</td></tr><tr><td>admin_phone</td><td>管理员手机号</td><td>varchar</td><td>11</td><td>非空</td></tr></table>
|
||||
|
||||
|
||||
表 4.2 用户表 (user 表)
|
||||
|
||||
|
||||
<table><tr><td>字段名称</td><td>字段意义</td><td>数据类型</td><td>长度</td><td>完整性约束</td></tr><tr><td>user_id</td><td>用户id</td><td>int</td><td>10</td><td>主键</td></tr><tr><td>user_name</td><td>用户昵称</td><td>varchar</td><td>10</td><td>非空</td></tr><tr><td>user_password</td><td>用户密码</td><td>varchar</td><td>20</td><td>非空</td></tr><tr><td>user/mobile</td><td>用户电话</td><td>varchar</td><td>11</td><td>非空</td></tr><tr><td>user_realname</td><td>用户真实姓名</td><td>varchar</td><td>10</td><td>非空</td></tr><tr><td>user_score</td><td>信誉分</td><td>int</td><td>4</td><td>非空</td></tr></table>
|
||||
|
||||
|
||||
表4.3商品表 (product表)
|
||||
|
||||
|
||||
<table><tr><td>字段名称</td><td>字段意义</td><td>数据类型</td><td>长度</td><td>完整性约束</td></tr><tr><td>product_id</td><td>商品id</td><td>int</td><td>10</td><td>主键</td></tr><tr><td>product_name</td><td>商品名称</td><td>varchar</td><td>10</td><td>非空</td></tr><tr><td>product_title</td><td>商品概要</td><td>varchar</td><td>50</td><td>非空</td></tr><tr><td>product_intro</td><td>商品详情</td><td>varchar</td><td>100</td><td>非空</td></tr></table>
|
||||
|
||||
4.6图形界面设计(实现某一个具体功能的界面设计,至少系统中各角色各列举1
|
||||
|
||||
# 个功能界面设计)
|
||||
|
||||
如:删除购物车界面设计
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
图4. 删除购物车界面设计图
|
||||
|
||||
|
||||
# 第5章XXXXX的系统实现
|
||||
|
||||
只写出主要功能的实现结果即可,并给出运行截图(不写用户注册、登录),
|
||||
|
||||
运行截图中需输入数据的地方要有数据输入,且输入的数据必须真实,不可输入
|
||||
|
||||
类似 1111 类数据。可按系统角色进行实现,再进行角色详细功能实现。如:
|
||||
|
||||
# 5.1 用户功能模块
|
||||
|
||||
# 5.1.1 购物车
|
||||
|
||||
# 5.1.2 我的订单
|
||||
|
||||
··
|
||||
|
||||
# 5.2 管理员功能模块
|
||||
|
||||
# 5.2.1 账号管理
|
||||
|
||||
# 5.2.2 订单管理
|
||||
|
||||
··
|
||||
|
||||
# 第6章XXXXX的系统测试
|
||||
|
||||
# 6.1 系统测试概述
|
||||
|
||||
6.1.1 测试的背景
|
||||
|
||||
6.1.2 测试的意义
|
||||
|
||||
6.1.3 测试的环境
|
||||
|
||||
# 6.2 系统测试用例设计
|
||||
|
||||
6.2.1XXXX功能测试
|
||||
|
||||
6.2.2XXXX功能测试
|
||||
|
||||
6.2.3XXXX功能测试
|
||||
|
||||
6.2.4 安全性测试
|
||||
|
||||
6.2.5 兼容性测试
|
||||
|
||||
# 第7章结论
|
||||
|
||||
参考文献
|
||||
|
||||
致谢
|
||||
|
||||
附录
|
||||
43
AGENTS.md
Normal file
43
AGENTS.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# Repository Guidelines
|
||||
|
||||
## Project Structure & Module Organization
|
||||
- `backend/` is a Spring Boot 2.7 (Java 17) service with MyBatis-Plus and JWT security.
|
||||
- Main code: `backend/src/main/java/com/gpf/pethospital`
|
||||
- Config: `backend/src/main/resources/application.yml` and `application-dev.yml`
|
||||
- `frontend/` is a Vue 3 + Vite app with Pinia and TDesign.
|
||||
- Source: `frontend/src/` (pages, router, store, layouts, styles)
|
||||
- Static assets: `frontend/src/assets/`
|
||||
- `docs/` and `*.drawio` contain documentation and UML/ER diagrams.
|
||||
- `frp/` and `start_frp.sh` include FRP configuration/scripts.
|
||||
|
||||
## Build, Test, and Development Commands
|
||||
Backend (from `backend/`):
|
||||
- `mvn spring-boot:run` — run the API locally.
|
||||
- `mvn clean package` — build a runnable jar.
|
||||
- `mvn test` — run Spring Boot tests (if present).
|
||||
|
||||
Frontend (from `frontend/`):
|
||||
- `npm install` — install dependencies.
|
||||
- `npm run dev` — start Vite dev server.
|
||||
- `npm run build` — production build.
|
||||
- `npm run preview` — preview the production build.
|
||||
|
||||
## Coding Style & Naming Conventions
|
||||
- Java: 4-space indentation, standard Spring Boot conventions, packages under `com.gpf.pethospital`.
|
||||
- Vue/TypeScript: ES module syntax, semicolons used; follow existing file structure.
|
||||
- Use descriptive, domain-specific names (e.g., `AppointmentController`, `appointmentService`).
|
||||
|
||||
## Testing Guidelines
|
||||
- No dedicated test directories are present yet.
|
||||
- Backend tests should go in `backend/src/test/java` using Spring Boot Test.
|
||||
- Frontend has no test runner configured; if adding, include a script in `frontend/package.json`.
|
||||
|
||||
## Commit & Pull Request Guidelines
|
||||
- Current commit history uses short Chinese descriptions like “添加…” and “将…更改为…”.
|
||||
- Keep messages short, imperative, and meaningful; avoid placeholder commits like “1”.
|
||||
- PRs should include: a clear summary, testing performed (or “not run”), and screenshots for UI changes.
|
||||
|
||||
## Configuration & Security Notes
|
||||
- `application-dev.yml` contains local MySQL defaults (user `root`, password `password`).
|
||||
Update credentials via environment or local overrides; do not commit real secrets.
|
||||
- JWT secrets are currently hardcoded in config; rotate for real deployments.
|
||||
195
admin_activity_diagram.drawio
Normal file
195
admin_activity_diagram.drawio
Normal file
@@ -0,0 +1,195 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T13:55:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="admin activity diagram"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<!-- 开始节点 -->
|
||||
<mxCell id="2" value="" style="ellipse;html=1;shape=startState;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="40" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="3" value="管理员登录系统" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="110" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 状态节点 -->
|
||||
<mxCell id="4" value="系统验证管理员身份" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="180" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 判断节点 -->
|
||||
<mxCell id="5" value="" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="250" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="6" value="显示错误信息" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="245" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="7" value="进入用户管理模块" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="320" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="8" value="查看用户列表" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="390" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="9" value="选择操作用户" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="460" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="10" value="选择操作类型" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="530" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 判断节点 -->
|
||||
<mxCell id="11" value="" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="600" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="12" value="编辑用户信息" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="595" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="13" value="禁用/启用用户" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="665" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="14" value="删除用户" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="735" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="15" value="保存更改" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="735" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="16" value="确认操作" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="805" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="17" value="退出系统" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="875" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 结束节点 -->
|
||||
<mxCell id="18" value="" style="ellipse;html=1;shape=endState;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="945" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 结束节点 -->
|
||||
<mxCell id="19" value="" style="ellipse;html=1;shape=endState;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="500" y="315" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 连接线 -->
|
||||
<mxCell id="20" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;exitPerimeter=0;entryX=0.5;entryY=0;" edge="1" parent="1" source="2" target="3">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="210" y="140" as="sourcePoint"/>
|
||||
<mxPoint x="260" y="90" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="3" target="4">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="220" y="150" as="sourcePoint"/>
|
||||
<mxPoint x="270" y="100" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="4" target="5">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="230" y="160" as="sourcePoint"/>
|
||||
<mxPoint x="280" y="110" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="23" value="是" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="5" target="7">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="240" y="170" as="sourcePoint"/>
|
||||
<mxPoint x="290" y="120" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="否" style="endArrow=classic;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="5" target="6">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="250" y="180" as="sourcePoint"/>
|
||||
<mxPoint x="300" y="130" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="7" target="8">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="290" as="sourcePoint"/>
|
||||
<mxPoint x="310" y="240" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="26" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="8" target="9">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="270" y="300" as="sourcePoint"/>
|
||||
<mxPoint x="320" y="250" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="9" target="10">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="280" y="310" as="sourcePoint"/>
|
||||
<mxPoint x="330" y="260" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="28" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="10" target="11">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="290" y="320" as="sourcePoint"/>
|
||||
<mxPoint x="340" y="270" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="29" value="编辑信息" style="endArrow=classic;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="11" target="12">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="300" y="330" as="sourcePoint"/>
|
||||
<mxPoint x="350" y="280" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="30" value="禁用/启用" style="endArrow=classic;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="11" target="13">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="310" y="340" as="sourcePoint"/>
|
||||
<mxPoint x="360" y="290" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="31" value="删除用户" style="endArrow=classic;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="11" target="14">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="350" as="sourcePoint"/>
|
||||
<mxPoint x="370" y="300" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="32" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="12" target="15">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="330" y="360" as="sourcePoint"/>
|
||||
<mxPoint x="380" y="310" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="33" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="13" target="15">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="340" y="370" as="sourcePoint"/>
|
||||
<mxPoint x="390" y="320" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="34" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="14" target="15">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="350" y="380" as="sourcePoint"/>
|
||||
<mxPoint x="400" y="330" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="35" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="15" target="16">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="360" y="390" as="sourcePoint"/>
|
||||
<mxPoint x="410" y="340" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="36" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="16" target="17">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="400" as="sourcePoint"/>
|
||||
<mxPoint x="420" y="350" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="37" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="17" target="18">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="380" y="410" as="sourcePoint"/>
|
||||
<mxPoint x="430" y="360" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="38" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="6" target="19">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="500" y="430" as="sourcePoint"/>
|
||||
<mxPoint x="550" y="380" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
14
admin_entity.drawio
Normal file
14
admin_entity.drawio
Normal file
@@ -0,0 +1,14 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T13:55:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="????????"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="???(Admin)" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="200" y="120" width="240" height="260" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="+ admin_id: BIGINT
+ admin_name: VARCHAR(50)
+ admin_username: VARCHAR(50)
+ admin_password: VARCHAR(255)
+ phone: VARCHAR(20)
+ role: VARCHAR(20)
+ status: INT
+ create_time: TIMESTAMP
+ update_time: TIMESTAMP" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="2">
|
||||
<mxGeometry y="26" width="240" height="234" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
107
admin_function_structure.drawio
Normal file
107
admin_function_structure.drawio
Normal file
@@ -0,0 +1,107 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T14:00:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="管理员功能结构图"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="管理员功能结构" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="310" y="40" width="180" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="10" value="账号管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="140" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="100" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="10">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="11" value="员工账号管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="130" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="101" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="10" target="11">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="顾客账号管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="176" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="102" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="11" target="12">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="药品库存" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="230" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="103" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="13">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="14" value="药品入库/出库" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="220" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="104" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="13" target="14">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="库存查询" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="266" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="105" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="14" target="15">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="预约管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="320" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="106" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="16">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="17" value="预约审核" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="310" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="107" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="16" target="17">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="预约调整" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="356" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="108" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="17" target="18">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="19" value="门诊与病历" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="410" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="109" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="19">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="20" value="门诊管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="400" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="110" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="19" target="20">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="病历管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="446" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="111" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="20" target="21">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="处方管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="492" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="112" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="21" target="22">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="23" value="公告与统计" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="500" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="113" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="23">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="公告管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="490" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="114" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="23" target="24">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="统计报表" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="536" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="115" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="24" target="25">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
152
admin_sequence_diagram.drawio
Normal file
152
admin_sequence_diagram.drawio
Normal file
@@ -0,0 +1,152 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T14:02:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="admin sequence diagram"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<mxCell id="2" value="管理员" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="80" width="100" height="520" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="3" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="2">
|
||||
<mxGeometry x="45" y="70" width="10" height="450" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4" value="系统" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="270" y="80" width="100" height="520" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="5" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="4">
|
||||
<mxGeometry x="45" y="80" width="10" height="440" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="6" value="药品管理模块" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="440" y="80" width="100" height="520" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="7" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="6">
|
||||
<mxGeometry x="45" y="100" width="10" height="420" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8" value="数据库" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="610" y="80" width="100" height="520" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="9" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="8">
|
||||
<mxGeometry x="45" y="110" width="10" height="410" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="10" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="1">
|
||||
<mxGeometry x="155" y="170" width="10" height="40" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="11" value="登录系统" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="10">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="160" y="150" as="sourcePoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="验证管理员身份" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="320" y="200" as="sourcePoint" />
|
||||
<mxPoint x="470" y="200" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="返回验证结果" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.16" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="230" as="targetPoint" />
|
||||
<mxPoint x="320" y="230" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="14" value="登录成功" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="160" y="260" as="targetPoint" />
|
||||
<mxPoint x="160" y="260" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="进入药品管理" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="160" y="290" as="sourcePoint" />
|
||||
<mxPoint x="470" y="290" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="调用药品管理模块" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="320" y="320" as="sourcePoint" />
|
||||
<mxPoint x="470" y="320" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="17" value="获取药品列表" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="9">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="490" y="350" as="sourcePoint" />
|
||||
<mxPoint x="470" y="350" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="返回药品列表" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="490" y="380" as="targetPoint" />
|
||||
<mxPoint x="490" y="380" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="19" value="返回药品列表" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="410" as="targetPoint" />
|
||||
<mxPoint x="320" y="410" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="20" value="显示药品列表" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="160" y="440" as="targetPoint" />
|
||||
<mxPoint x="160" y="440" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="选择添加药品" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="160" y="470" as="sourcePoint" />
|
||||
<mxPoint x="470" y="470" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="调用添加药品功能" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="320" y="500" as="sourcePoint" />
|
||||
<mxPoint x="470" y="500" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="23" value="输入药品信息" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="160" y="530" as="sourcePoint" />
|
||||
<mxPoint x="470" y="530" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="验证药品信息" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="490" y="560" as="sourcePoint" />
|
||||
<mxPoint x="470" y="560" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="保存药品信息" style="html=1;verticalAlign=bottom;endArrow=block;entryX=0;entryY=0;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1" target="9">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="490" y="590" as="sourcePoint" />
|
||||
<mxPoint x="470" y="590" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="26" value="保存成功" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="490" y="620" as="targetPoint" />
|
||||
<mxPoint x="490" y="620" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="返回添加结果" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="650" as="targetPoint" />
|
||||
<mxPoint x="320" y="650" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="28" value="药品添加成功" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;" edge="1" parent="1">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="160" y="680" as="targetPoint" />
|
||||
<mxPoint x="160" y="680" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
68
admin_use_case.drawio
Normal file
68
admin_use_case.drawio
Normal file
@@ -0,0 +1,68 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T14:00:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="管理员用例图"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="爱维宠物医院管理系统" style="html=1;fontStyle=1;verticalAlign=top;align=left;spacingTop=8;spacingLeft=6;spacingRight=12;shape=cube;size=10;direction=south;fontSize=14;" vertex="1" parent="1">
|
||||
<mxGeometry x="20" y="20" width="760" height="520" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="管理员" style="shape=umlActor;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="220" width="30" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="20" value="管理员工账号" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="80" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="管理顾客账号" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="150" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="药品库存管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="220" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="23" value="公告管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="290" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="统计报表" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="80" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="预约管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="150" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="26" value="门诊管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="220" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="病历管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="290" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="28" value="处方管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="360" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="100" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="20">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="101" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="21">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="102" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="22">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="103" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="23">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="104" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="24">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="105" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="25">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="106" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="26">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="107" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="27">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="108" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="28">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
@@ -26,6 +26,8 @@ public class AppointmentController {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
appointment.setCustomerId(user.getId());
|
||||
} else if (appointment.getCustomerId() == null) {
|
||||
return ApiResponse.error(400, "customerId required");
|
||||
}
|
||||
if (appointment.getStatus() == null) {
|
||||
appointment.setStatus("PENDING");
|
||||
|
||||
@@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.gpf.pethospital.common.ApiResponse;
|
||||
import com.gpf.pethospital.entity.Notice;
|
||||
import com.gpf.pethospital.security.AuthUser;
|
||||
import com.gpf.pethospital.service.NoticeService;
|
||||
import com.gpf.pethospital.util.SecurityUtils;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@@ -42,6 +44,15 @@ public class NoticeController {
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
@PostMapping("/notices")
|
||||
public ApiResponse<?> create(@RequestBody Notice notice) {
|
||||
if (notice.getPublisherId() == null) {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null) {
|
||||
notice.setPublisherId(user.getId());
|
||||
}
|
||||
}
|
||||
if (notice.getPublisherId() == null) {
|
||||
return ApiResponse.error(400, "publisherId required");
|
||||
}
|
||||
if (notice.getStatus() == null) {
|
||||
notice.setStatus(1);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,8 @@ public class PetController {
|
||||
AuthUser user = SecurityUtils.currentUser();
|
||||
if (user != null && "CUSTOMER".equals(user.getRole())) {
|
||||
pet.setOwnerId(user.getId());
|
||||
} else if (pet.getOwnerId() == null) {
|
||||
return ApiResponse.error(400, "ownerId required");
|
||||
}
|
||||
petService.save(pet);
|
||||
return ApiResponse.success("created", null);
|
||||
|
||||
@@ -55,8 +55,11 @@ public class StatsController {
|
||||
wrapper.select("SUM(amount) AS total");
|
||||
List<Map<String, Object>> result = orderService.listMaps(wrapper);
|
||||
BigDecimal total = BigDecimal.ZERO;
|
||||
if (!result.isEmpty() && result.get(0).get("total") != null) {
|
||||
total = new BigDecimal(result.get(0).get("total").toString());
|
||||
if (!result.isEmpty()) {
|
||||
Map<String, Object> row = result.get(0);
|
||||
if (row != null && row.get("total") != null) {
|
||||
total = new BigDecimal(row.get("total").toString());
|
||||
}
|
||||
}
|
||||
data.put("orderAmountTotal", total);
|
||||
return ApiResponse.success(data);
|
||||
|
||||
@@ -46,7 +46,8 @@ public class PrescriptionItem {
|
||||
/**
|
||||
* 用法用量
|
||||
*/
|
||||
private String usage;
|
||||
@TableField("usage_desc")
|
||||
private String usageDesc;
|
||||
|
||||
/**
|
||||
* 用药天数
|
||||
|
||||
@@ -9,9 +9,9 @@ spring:
|
||||
|
||||
datasource:
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3306/pet_hospital_dev?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
|
||||
url: jdbc:mysql://localhost:3307/pet_hospital_dev?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: password
|
||||
password: qq5211314
|
||||
hikari:
|
||||
maximum-pool-size: 20
|
||||
minimum-idle: 10
|
||||
@@ -30,7 +30,7 @@ spring:
|
||||
|
||||
sql:
|
||||
init:
|
||||
mode: always
|
||||
mode: never
|
||||
schema-locations: classpath*:schema.sql
|
||||
data-locations: classpath*:data.sql
|
||||
|
||||
|
||||
@@ -58,7 +58,13 @@ CREATE TABLE IF NOT EXISTS prescription_item (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
prescription_id BIGINT NOT NULL,
|
||||
drug_id BIGINT NOT NULL,
|
||||
drug_name VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
quantity INT NOT NULL,
|
||||
usage_desc VARCHAR(200),
|
||||
days INT,
|
||||
unit_price DECIMAL(10,2),
|
||||
subtotal DECIMAL(10,2),
|
||||
dosage VARCHAR(100),
|
||||
frequency VARCHAR(50),
|
||||
duration VARCHAR(50),
|
||||
@@ -92,6 +98,12 @@ CREATE TABLE IF NOT EXISTS drug (
|
||||
specification VARCHAR(100),
|
||||
unit_price DECIMAL(10,2),
|
||||
stock_quantity INT DEFAULT 0,
|
||||
stock INT DEFAULT 0,
|
||||
alert_threshold INT,
|
||||
purchase_price DECIMAL(10,2),
|
||||
sale_price DECIMAL(10,2),
|
||||
approval_number VARCHAR(100),
|
||||
expiry_date TIMESTAMP NULL,
|
||||
unit VARCHAR(20),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
@@ -150,6 +162,14 @@ CREATE TABLE IF NOT EXISTS `user` (
|
||||
CREATE TABLE IF NOT EXISTS medical_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
chief_complaint TEXT,
|
||||
present_illness TEXT,
|
||||
physical_examination TEXT,
|
||||
examination_results TEXT,
|
||||
diagnosis TEXT,
|
||||
treatment_plan TEXT,
|
||||
advice TEXT,
|
||||
status VARCHAR(20),
|
||||
record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗
|
||||
content TEXT,
|
||||
attachment_urls TEXT,
|
||||
@@ -162,11 +182,18 @@ CREATE TABLE IF NOT EXISTS medical_record (
|
||||
-- 检查并创建message表
|
||||
CREATE TABLE IF NOT EXISTS message (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT,
|
||||
user_name VARCHAR(100),
|
||||
contact VARCHAR(100),
|
||||
title VARCHAR(200),
|
||||
sender_id BIGINT,
|
||||
receiver_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天
|
||||
status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读
|
||||
reply TEXT,
|
||||
reply_time TIMESTAMP NULL,
|
||||
reply_user_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
@@ -177,6 +204,7 @@ CREATE TABLE IF NOT EXISTS notice (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
is_top INT DEFAULT 0,
|
||||
publisher_id BIGINT NOT NULL,
|
||||
publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status INT DEFAULT 1,
|
||||
@@ -188,6 +216,13 @@ CREATE TABLE IF NOT EXISTS notice (
|
||||
-- 检查并创建report表
|
||||
CREATE TABLE IF NOT EXISTS report (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
pet_id BIGINT,
|
||||
type VARCHAR(50),
|
||||
title VARCHAR(200),
|
||||
summary TEXT,
|
||||
attachment_url VARCHAR(255),
|
||||
doctor_id BIGINT,
|
||||
report_type VARCHAR(50) NOT NULL, -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品
|
||||
report_data JSON,
|
||||
period_start DATE,
|
||||
@@ -206,6 +241,7 @@ CREATE TABLE IF NOT EXISTS stock_in (
|
||||
unit_price DECIMAL(10,2),
|
||||
supplier VARCHAR(100),
|
||||
operator_id BIGINT,
|
||||
stock_in_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
@@ -216,10 +252,12 @@ CREATE TABLE IF NOT EXISTS stock_in (
|
||||
CREATE TABLE IF NOT EXISTS stock_out (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
prescription_id BIGINT,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
purpose VARCHAR(100), -- 用途:销售、损耗等
|
||||
operator_id BIGINT,
|
||||
stock_out_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
@@ -230,6 +268,10 @@ CREATE TABLE IF NOT EXISTS stock_out (
|
||||
CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
type VARCHAR(20), -- VACCINE疫苗, DEWORMING驱虫
|
||||
item_name VARCHAR(100),
|
||||
execute_date DATE,
|
||||
next_reminder_date DATE,
|
||||
vaccine_name VARCHAR(100) NOT NULL,
|
||||
dose_number INT,
|
||||
injection_date DATE,
|
||||
@@ -239,4 +281,4 @@ CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
);
|
||||
|
||||
@@ -8,33 +8,30 @@ spring:
|
||||
name: pet-hospital
|
||||
|
||||
datasource:
|
||||
driver-class-name: org.h2.Driver
|
||||
url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;MODE=MYSQL;
|
||||
username: sa
|
||||
password: password
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
url: jdbc:mysql://localhost:3307/pet_hospital_dev?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8
|
||||
username: root
|
||||
password: qq5211314
|
||||
hikari:
|
||||
maximum-pool-size: 10
|
||||
minimum-idle: 5
|
||||
maximum-pool-size: 20
|
||||
minimum-idle: 10
|
||||
connection-timeout: 30000
|
||||
idle-timeout: 600000
|
||||
max-lifetime: 1800000
|
||||
|
||||
jackson:
|
||||
time-zone: GMT+8
|
||||
date-format: yyyy-MM-dd HH:mm:ss
|
||||
|
||||
h2:
|
||||
console:
|
||||
enabled: true
|
||||
path: /h2-console
|
||||
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: create-drop
|
||||
ddl-auto: update
|
||||
show-sql: true
|
||||
|
||||
sql:
|
||||
init:
|
||||
mode: always
|
||||
schema-locations: classpath*:schema-h2.sql
|
||||
mode: never
|
||||
schema-locations: classpath*:schema.sql
|
||||
data-locations: classpath*:data.sql
|
||||
|
||||
mybatis-plus:
|
||||
|
||||
@@ -25,6 +25,10 @@ mybatis-plus:
|
||||
logic-not-delete-value: 0
|
||||
mapper-locations: classpath*:mapper/**/*.xml
|
||||
|
||||
# 数据库配置
|
||||
database:
|
||||
type: mysql
|
||||
|
||||
# JWT配置
|
||||
jwt:
|
||||
secret: pet-hospital-secret-key-2024-guanpengfei-graduate-design
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,242 +0,0 @@
|
||||
-- 如果表不存在则创建表,如果存在则添加缺失的列
|
||||
|
||||
-- 检查并创建appointment表或添加缺失列
|
||||
CREATE TABLE IF NOT EXISTS appointment (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
customer_id BIGINT NOT NULL,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT,
|
||||
department VARCHAR(50),
|
||||
appointment_date DATE,
|
||||
time_slot VARCHAR(20), -- 添加这个缺失的列
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
remark TEXT,
|
||||
cancel_time TIMESTAMP NULL,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建visit表
|
||||
CREATE TABLE IF NOT EXISTS visit (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
appointment_id BIGINT,
|
||||
customer_id BIGINT NOT NULL,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
symptoms TEXT,
|
||||
diagnosis TEXT,
|
||||
treatment_plan TEXT,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
total_amount DECIMAL(10,2),
|
||||
payment_status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
payment_method VARCHAR(20),
|
||||
payment_time TIMESTAMP NULL,
|
||||
start_time TIMESTAMP,
|
||||
end_time TIMESTAMP,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建prescription表
|
||||
CREATE TABLE IF NOT EXISTS prescription (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
doctor_id BIGINT,
|
||||
customer_id BIGINT,
|
||||
total_amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'DRAFT',
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建prescription_item表
|
||||
CREATE TABLE IF NOT EXISTS prescription_item (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
prescription_id BIGINT NOT NULL,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
dosage VARCHAR(100),
|
||||
frequency VARCHAR(50),
|
||||
duration VARCHAR(50),
|
||||
usage_instructions TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建order_info表
|
||||
CREATE TABLE IF NOT EXISTS order_info (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
customer_id BIGINT NOT NULL,
|
||||
amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
payment_method VARCHAR(20),
|
||||
payment_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建drug表
|
||||
CREATE TABLE IF NOT EXISTS drug (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
category VARCHAR(50),
|
||||
manufacturer VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
unit_price DECIMAL(10,2),
|
||||
stock_quantity INT DEFAULT 0,
|
||||
unit VARCHAR(20),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建pet表
|
||||
CREATE TABLE IF NOT EXISTS pet (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
owner_id BIGINT NOT NULL,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
species VARCHAR(50),
|
||||
breed VARCHAR(100),
|
||||
gender VARCHAR(10), -- 修改为VARCHAR以支持MALE/FEMALE
|
||||
birthday DATE, -- 添加birthday字段而不是age
|
||||
weight DOUBLE, -- 添加weight字段
|
||||
photo VARCHAR(255), -- 添加photo字段
|
||||
remark TEXT, -- 添加remark字段
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建doctor表
|
||||
CREATE TABLE IF NOT EXISTS doctor (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
department VARCHAR(50),
|
||||
title VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建user表
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) DEFAULT 'CUSTOMER',
|
||||
status INT DEFAULT 1,
|
||||
avatar VARCHAR(255),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建medical_record表
|
||||
CREATE TABLE IF NOT EXISTS medical_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗
|
||||
content TEXT,
|
||||
attachment_urls TEXT,
|
||||
doctor_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建message表
|
||||
CREATE TABLE IF NOT EXISTS message (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
sender_id BIGINT,
|
||||
receiver_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天
|
||||
status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建notice表
|
||||
CREATE TABLE IF NOT EXISTS notice (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
publisher_id BIGINT NOT NULL,
|
||||
publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建report表
|
||||
CREATE TABLE IF NOT EXISTS report (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
report_type VARCHAR(50) NOT NULL, -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品
|
||||
report_data JSON,
|
||||
period_start DATE,
|
||||
period_end DATE,
|
||||
generated_by BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建stock_in表
|
||||
CREATE TABLE IF NOT EXISTS stock_in (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
supplier VARCHAR(100),
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建stock_out表
|
||||
CREATE TABLE IF NOT EXISTS stock_out (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
purpose VARCHAR(100), -- 用途:销售、损耗等
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建vaccine_record表
|
||||
CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
vaccine_name VARCHAR(100) NOT NULL,
|
||||
dose_number INT,
|
||||
injection_date DATE,
|
||||
next_appointment_date DATE,
|
||||
doctor_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
@@ -1,84 +1,70 @@
|
||||
-- 用户表
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) DEFAULT 'CUSTOMER',
|
||||
status INT DEFAULT 1,
|
||||
avatar VARCHAR(255),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
-- 如果表不存在则创建表,如果存在则添加缺失的列
|
||||
|
||||
-- 宠物表
|
||||
CREATE TABLE IF NOT EXISTS pet (
|
||||
-- 检查并创建appointment表或添加缺失列
|
||||
CREATE TABLE IF NOT EXISTS appointment (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
species VARCHAR(50),
|
||||
breed VARCHAR(100),
|
||||
gender CHAR(1),
|
||||
age INT,
|
||||
owner_id BIGINT NOT NULL,
|
||||
health_status VARCHAR(100),
|
||||
vaccination_status VARCHAR(100),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 医生表
|
||||
CREATE TABLE IF NOT EXISTS doctor (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT,
|
||||
department VARCHAR(50),
|
||||
title VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
status INT DEFAULT 1,
|
||||
appointment_date DATE,
|
||||
time_slot VARCHAR(20), -- 添加这个缺失的列
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
remark TEXT,
|
||||
cancel_time TIMESTAMP NULL,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 就诊记录表
|
||||
-- 检查并创建visit表
|
||||
CREATE TABLE IF NOT EXISTS visit (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
appointment_id BIGINT,
|
||||
customer_id BIGINT NOT NULL,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
symptoms TEXT,
|
||||
diagnosis TEXT,
|
||||
treatment_plan TEXT,
|
||||
visit_date DATE,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
total_amount DECIMAL(10,2),
|
||||
payment_status VARCHAR(20) DEFAULT 'UNPAID',
|
||||
payment_method VARCHAR(20),
|
||||
payment_time TIMESTAMP NULL,
|
||||
start_time TIMESTAMP,
|
||||
end_time TIMESTAMP,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 处方表
|
||||
-- 检查并创建prescription表
|
||||
CREATE TABLE IF NOT EXISTS prescription (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
visit_id BIGINT,
|
||||
doctor_id BIGINT,
|
||||
customer_id BIGINT,
|
||||
total_amount DECIMAL(10,2),
|
||||
status VARCHAR(20) DEFAULT 'ACTIVE',
|
||||
status VARCHAR(20) DEFAULT 'DRAFT',
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 处方明细表
|
||||
-- 检查并创建prescription_item表
|
||||
CREATE TABLE IF NOT EXISTS prescription_item (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
prescription_id BIGINT NOT NULL,
|
||||
drug_id BIGINT NOT NULL,
|
||||
drug_name VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
quantity INT NOT NULL,
|
||||
usage_desc VARCHAR(200),
|
||||
days INT,
|
||||
unit_price DECIMAL(10,2),
|
||||
subtotal DECIMAL(10,2),
|
||||
dosage VARCHAR(100),
|
||||
frequency VARCHAR(50),
|
||||
duration VARCHAR(50),
|
||||
@@ -88,23 +74,7 @@ CREATE TABLE IF NOT EXISTS prescription_item (
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 药品表
|
||||
CREATE TABLE IF NOT EXISTS drug (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
category VARCHAR(50),
|
||||
manufacturer VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
unit_price DECIMAL(10,2),
|
||||
stock_quantity INT DEFAULT 0,
|
||||
unit VARCHAR(20),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 订单表
|
||||
-- 检查并创建order_info表
|
||||
CREATE TABLE IF NOT EXISTS order_info (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
@@ -119,25 +89,189 @@ CREATE TABLE IF NOT EXISTS order_info (
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 预约表
|
||||
CREATE TABLE IF NOT EXISTS appointment (
|
||||
-- 检查并创建drug表
|
||||
CREATE TABLE IF NOT EXISTS drug (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
doctor_id BIGINT NOT NULL,
|
||||
customer_id BIGINT NOT NULL,
|
||||
appointment_date DATE NOT NULL,
|
||||
appointment_time TIME NOT NULL,
|
||||
reason TEXT,
|
||||
status VARCHAR(20) DEFAULT 'PENDING',
|
||||
name VARCHAR(100) NOT NULL,
|
||||
category VARCHAR(50),
|
||||
manufacturer VARCHAR(100),
|
||||
specification VARCHAR(100),
|
||||
unit_price DECIMAL(10,2),
|
||||
stock_quantity INT DEFAULT 0,
|
||||
stock INT DEFAULT 0,
|
||||
alert_threshold INT,
|
||||
purchase_price DECIMAL(10,2),
|
||||
sale_price DECIMAL(10,2),
|
||||
approval_number VARCHAR(100),
|
||||
expiry_date TIMESTAMP NULL,
|
||||
unit VARCHAR(20),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 疫苗接种记录表
|
||||
-- 检查并创建pet表
|
||||
CREATE TABLE IF NOT EXISTS pet (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
owner_id BIGINT NOT NULL,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
species VARCHAR(50),
|
||||
breed VARCHAR(100),
|
||||
gender VARCHAR(10), -- 修改为VARCHAR以支持MALE/FEMALE
|
||||
birthday DATE, -- 添加birthday字段而不是age
|
||||
weight DOUBLE, -- 添加weight字段
|
||||
photo VARCHAR(255), -- 添加photo字段
|
||||
remark TEXT, -- 添加remark字段
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建doctor表
|
||||
CREATE TABLE IF NOT EXISTS doctor (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(50) NOT NULL,
|
||||
department VARCHAR(50),
|
||||
title VARCHAR(50),
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
avatar VARCHAR(255),
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建user表
|
||||
CREATE TABLE IF NOT EXISTS `user` (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL UNIQUE,
|
||||
phone VARCHAR(20),
|
||||
email VARCHAR(100),
|
||||
password VARCHAR(255) NOT NULL,
|
||||
role VARCHAR(20) DEFAULT 'CUSTOMER',
|
||||
status INT DEFAULT 1,
|
||||
avatar VARCHAR(255),
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建medical_record表
|
||||
CREATE TABLE IF NOT EXISTS medical_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
chief_complaint TEXT,
|
||||
present_illness TEXT,
|
||||
physical_examination TEXT,
|
||||
examination_results TEXT,
|
||||
diagnosis TEXT,
|
||||
treatment_plan TEXT,
|
||||
advice TEXT,
|
||||
status VARCHAR(20),
|
||||
record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗
|
||||
content TEXT,
|
||||
attachment_urls TEXT,
|
||||
doctor_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建message表
|
||||
CREATE TABLE IF NOT EXISTS message (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id BIGINT,
|
||||
user_name VARCHAR(100),
|
||||
contact VARCHAR(100),
|
||||
title VARCHAR(200),
|
||||
sender_id BIGINT,
|
||||
receiver_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天
|
||||
status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读
|
||||
reply TEXT,
|
||||
reply_time TIMESTAMP NULL,
|
||||
reply_user_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建notice表
|
||||
CREATE TABLE IF NOT EXISTS notice (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
is_top INT DEFAULT 0,
|
||||
publisher_id BIGINT NOT NULL,
|
||||
publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建report表
|
||||
CREATE TABLE IF NOT EXISTS report (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT,
|
||||
pet_id BIGINT,
|
||||
type VARCHAR(50),
|
||||
title VARCHAR(200),
|
||||
summary TEXT,
|
||||
attachment_url VARCHAR(255),
|
||||
doctor_id BIGINT,
|
||||
report_type VARCHAR(50) NOT NULL, -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品
|
||||
report_data JSON,
|
||||
period_start DATE,
|
||||
period_end DATE,
|
||||
generated_by BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建stock_in表
|
||||
CREATE TABLE IF NOT EXISTS stock_in (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
supplier VARCHAR(100),
|
||||
operator_id BIGINT,
|
||||
stock_in_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建stock_out表
|
||||
CREATE TABLE IF NOT EXISTS stock_out (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
prescription_id BIGINT,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
purpose VARCHAR(100), -- 用途:销售、损耗等
|
||||
operator_id BIGINT,
|
||||
stock_out_time TIMESTAMP NULL,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 检查并创建vaccine_record表
|
||||
CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
pet_id BIGINT NOT NULL,
|
||||
type VARCHAR(20), -- VACCINE疫苗, DEWORMING驱虫
|
||||
item_name VARCHAR(100),
|
||||
execute_date DATE,
|
||||
next_reminder_date DATE,
|
||||
vaccine_name VARCHAR(100) NOT NULL,
|
||||
dose_number INT,
|
||||
injection_date DATE,
|
||||
@@ -148,83 +282,3 @@ CREATE TABLE IF NOT EXISTS vaccine_record (
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 库存入库表
|
||||
CREATE TABLE IF NOT EXISTS stock_in (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
supplier VARCHAR(100),
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 库存出库表
|
||||
CREATE TABLE IF NOT EXISTS stock_out (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
drug_id BIGINT NOT NULL,
|
||||
quantity INT NOT NULL,
|
||||
unit_price DECIMAL(10,2),
|
||||
purpose VARCHAR(100), -- 用途:销售、损耗等
|
||||
operator_id BIGINT,
|
||||
remark TEXT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 消息表
|
||||
CREATE TABLE IF NOT EXISTS message (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
sender_id BIGINT,
|
||||
receiver_id BIGINT NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
type VARCHAR(20) DEFAULT 'NOTICE', -- NOTICE通知, CHAT聊天
|
||||
status VARCHAR(20) DEFAULT 'UNREAD', -- UNREAD未读, READ已读
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 公告表
|
||||
CREATE TABLE IF NOT EXISTS notice (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
title VARCHAR(200) NOT NULL,
|
||||
content TEXT NOT NULL,
|
||||
publisher_id BIGINT NOT NULL,
|
||||
publish_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
status INT DEFAULT 1,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 医疗记录表
|
||||
CREATE TABLE IF NOT EXISTS medical_record (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
visit_id BIGINT NOT NULL,
|
||||
record_type VARCHAR(50), -- CHECKUP体检, DIAGNOSIS诊断, TREATMENT治疗
|
||||
content TEXT,
|
||||
attachment_urls TEXT,
|
||||
doctor_id BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
|
||||
-- 报表统计表
|
||||
CREATE TABLE IF NOT EXISTS report (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
report_type VARCHAR(50) NOT NULL, -- REVENUE收入, CUSTOMER客户, PET宠物, DRUG药品
|
||||
report_data JSON,
|
||||
period_start DATE,
|
||||
period_end DATE,
|
||||
generated_by BIGINT,
|
||||
create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
update_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
deleted INT DEFAULT 0
|
||||
);
|
||||
67
class_diagram.drawio
Normal file
67
class_diagram.drawio
Normal file
@@ -0,0 +1,67 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T13:55:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="class diagram"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="40" value="User" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="40" y="80" width="180" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="+ id: Long
|
||||
+ username: String
|
||||
+ phone: String
|
||||
+ email: String
|
||||
+ password: String
|
||||
+ role: String
|
||||
+ status: Integer" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="40">
|
||||
<mxGeometry y="26" width="180" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="Doctor" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="260" y="80" width="180" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="+ id: Long
|
||||
+ name: String
|
||||
+ department: String
|
||||
+ title: String
|
||||
+ phone: String" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="43">
|
||||
<mxGeometry y="26" width="180" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="Pet" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="480" y="80" width="180" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="+ id: Long
|
||||
+ ownerId: Long
|
||||
+ name: String
|
||||
+ species: String
|
||||
+ breed: String
|
||||
+ gender: String
|
||||
+ birthday: Date" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="46">
|
||||
<mxGeometry y="26" width="180" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="Appointment" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="720" y="80" width="180" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="+ id: Long
|
||||
+ customerId: Long
|
||||
+ petId: Long
|
||||
+ doctorId: Long
|
||||
+ appointmentDate: Date
|
||||
+ timeSlot: String
|
||||
+ status: String" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="49">
|
||||
<mxGeometry y="26" width="180" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="52" value="owns" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="40" target="46">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="53" value="makes" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="40" target="49">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="54" value="handles" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="43" target="49">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="55" value="involves" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="46" target="49">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
3
frontend/package-lock.json
generated
3
frontend/package-lock.json
generated
@@ -1429,6 +1429,7 @@
|
||||
"version": "5.9.3",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -1448,6 +1449,7 @@
|
||||
"version": "5.4.21",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
@@ -1520,6 +1522,7 @@
|
||||
"node_modules/vue": {
|
||||
"version": "3.5.27",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.5.27",
|
||||
"@vue/compiler-sfc": "3.5.27",
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id" bordered stripe hover>
|
||||
<template #petId="{ row }">
|
||||
{{ getPetName(row.petId) }}
|
||||
</template>
|
||||
<template #statusSlot="{ row }">
|
||||
<span class="status-badge" :class="getStatusClass(row.status)">
|
||||
{{ getStatusText(row.status) }}
|
||||
@@ -33,6 +36,9 @@
|
||||
|
||||
<t-dialog v-model:visible="dialogVisible" header="新增预约" :on-confirm="submitCreate" width="500">
|
||||
<t-form :data="form" layout="vertical">
|
||||
<t-form-item v-if="!isCustomer" label="顾客" required>
|
||||
<t-select v-model="form.customerId" :options="customerOptions" placeholder="请选择顾客" clearable />
|
||||
</t-form-item>
|
||||
<t-form-item label="宠物" required>
|
||||
<t-select v-model="form.petId" :options="petOptions" placeholder="请选择宠物" clearable />
|
||||
</t-form-item>
|
||||
@@ -40,7 +46,7 @@
|
||||
<t-date-picker v-model="form.appointmentDate" placeholder="请选择预约日期" />
|
||||
</t-form-item>
|
||||
<t-form-item label="时间段" required>
|
||||
<t-input v-model="form.timeSlot" placeholder="请输入时间段,如:09:00-10:00" />
|
||||
<t-select v-model="form.timeSlot" :options="timeSlotOptions" placeholder="请选择时间段" />
|
||||
</t-form-item>
|
||||
<t-form-item label="备注">
|
||||
<t-textarea v-model="form.remark" placeholder="请输入备注信息" :maxlength="200" />
|
||||
@@ -54,12 +60,17 @@
|
||||
import { onMounted, reactive, ref, computed } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const pets = ref([] as any[]);
|
||||
const customers = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const query = reactive({ status: '' });
|
||||
const form = reactive({ petId: '', appointmentDate: '', timeSlot: '' });
|
||||
const form = reactive({ customerId: '', petId: '', appointmentDate: '', timeSlot: '' });
|
||||
const auth = useAuthStore();
|
||||
|
||||
const isCustomer = computed(() => auth.user?.role === 'CUSTOMER');
|
||||
|
||||
const statusOptions = [
|
||||
{ label: '待确认', value: 'PENDING' },
|
||||
@@ -69,8 +80,29 @@ const statusOptions = [
|
||||
{ label: '爽约', value: 'NO_SHOW' },
|
||||
];
|
||||
|
||||
const timeSlotOptions = [
|
||||
{ label: '09:00-10:00', value: '09:00-10:00' },
|
||||
{ label: '10:00-11:00', value: '10:00-11:00' },
|
||||
{ label: '11:00-12:00', value: '11:00-12:00' },
|
||||
{ label: '14:00-15:00', value: '14:00-15:00' },
|
||||
{ label: '15:00-16:00', value: '15:00-16:00' },
|
||||
{ label: '16:00-17:00', value: '16:00-17:00' },
|
||||
{ label: '17:00-18:00', value: '17:00-18:00' },
|
||||
];
|
||||
|
||||
const customerOptions = computed(() => {
|
||||
return customers.value.map((customer: any) => ({
|
||||
label: customer.username || `顾客${customer.id}`,
|
||||
value: customer.id,
|
||||
}));
|
||||
});
|
||||
|
||||
const petOptions = computed(() => {
|
||||
return pets.value.map((pet: any) => ({
|
||||
const activeCustomerId = isCustomer.value ? auth.user?.userId : form.customerId;
|
||||
const filtered = activeCustomerId
|
||||
? pets.value.filter((pet: any) => pet.ownerId === activeCustomerId)
|
||||
: pets.value;
|
||||
return filtered.map((pet: any) => ({
|
||||
label: `${pet.name} (${pet.breed})`,
|
||||
value: pet.id
|
||||
}));
|
||||
@@ -87,6 +119,12 @@ const getStatusText = (status: string) => {
|
||||
return statusMap[status] || status;
|
||||
};
|
||||
|
||||
const getPetName = (petId: number) => {
|
||||
const pet = pets.value.find((item: any) => item.id === petId);
|
||||
if (!pet) return petId ? `宠物ID ${petId}` : '-';
|
||||
return `${pet.name}${pet.breed ? ` (${pet.breed})` : ''}`;
|
||||
};
|
||||
|
||||
const getStatusClass = (status: string) => {
|
||||
const classMap: Record<string, string> = {
|
||||
'PENDING': 'status-pending',
|
||||
@@ -100,7 +138,7 @@ const getStatusClass = (status: string) => {
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'petId', title: '宠物ID' },
|
||||
{ colKey: 'petId', title: '宠物' },
|
||||
{ colKey: 'appointmentDate', title: '预约日期' },
|
||||
{ colKey: 'timeSlot', title: '时段' },
|
||||
{ colKey: 'statusSlot', title: '状态' },
|
||||
@@ -132,6 +170,7 @@ const updateStatus = async (id: number, status: string) => {
|
||||
};
|
||||
|
||||
const openCreate = () => {
|
||||
form.customerId = isCustomer.value ? auth.user?.userId || '' : '';
|
||||
form.petId = '';
|
||||
form.appointmentDate = '';
|
||||
form.timeSlot = '';
|
||||
@@ -152,8 +191,26 @@ const loadPets = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
const loadCustomers = async () => {
|
||||
try {
|
||||
const res = await api.users({ page: 1, size: 100, role: 'CUSTOMER' });
|
||||
if (res.code === 0) {
|
||||
customers.value = res.data?.records || [];
|
||||
} else {
|
||||
MessagePlugin.error(res.message || '获取顾客列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取顾客列表失败:', error);
|
||||
MessagePlugin.error('获取顾客列表失败');
|
||||
}
|
||||
};
|
||||
|
||||
const submitCreate = async () => {
|
||||
const res = await api.createAppointment({ ...form });
|
||||
const payload = { ...form } as any;
|
||||
if (isCustomer.value) {
|
||||
payload.customerId = auth.user?.userId || payload.customerId;
|
||||
}
|
||||
const res = await api.createAppointment(payload);
|
||||
if (res.code === 0) {
|
||||
MessagePlugin.success('创建成功');
|
||||
dialogVisible.value = false;
|
||||
@@ -166,5 +223,8 @@ const submitCreate = async () => {
|
||||
onMounted(() => {
|
||||
load();
|
||||
loadPets(); // 加载宠物列表
|
||||
if (!isCustomer.value) {
|
||||
loadCustomers();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
<t-button variant="outline" @click="openCreate">新增病历</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #visitId="{ row }">
|
||||
{{ getVisitLabel(row.visitId) }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
{{ getStatusText(row.status) }}
|
||||
</template>
|
||||
<template #op="{ row }">
|
||||
<div class="table-actions">
|
||||
<t-button size="small" variant="text" @click="openEdit(row)">编辑</t-button>
|
||||
@@ -21,7 +27,14 @@
|
||||
|
||||
<t-dialog v-model:visible="dialogVisible" :header="dialogTitle" :on-confirm="submit">
|
||||
<t-form :data="form">
|
||||
<t-form-item label="就诊ID"><t-input v-model="form.visitId" /></t-form-item>
|
||||
<t-form-item label="就诊ID">
|
||||
<t-select
|
||||
v-model="form.visitId"
|
||||
:options="visitOptions"
|
||||
placeholder="请选择就诊记录"
|
||||
clearable
|
||||
/>
|
||||
</t-form-item>
|
||||
<t-form-item label="主诉"><t-input v-model="form.chiefComplaint" /></t-form-item>
|
||||
<t-form-item label="诊断"><t-input v-model="form.diagnosis" /></t-form-item>
|
||||
<t-form-item label="状态"><t-select v-model="form.status" :options="statusOptions" /></t-form-item>
|
||||
@@ -31,11 +44,14 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const visits = ref([] as any[]);
|
||||
const pets = ref([] as any[]);
|
||||
const doctors = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增病历');
|
||||
const editingId = ref<number | null>(null);
|
||||
@@ -47,9 +63,37 @@ const statusOptions = [
|
||||
{ label: '已完成', value: 'COMPLETED' },
|
||||
];
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
const map: Record<string, string> = {
|
||||
DRAFT: '草稿',
|
||||
COMPLETED: '已完成',
|
||||
};
|
||||
return map[status] || status || '-';
|
||||
};
|
||||
|
||||
const visitOptions = computed(() => {
|
||||
return visits.value.map((visit: any) => {
|
||||
const pet = pets.value.find((item: any) => item.id === visit.petId);
|
||||
const doctor = doctors.value.find((item: any) => item.id === visit.doctorId);
|
||||
const labelParts: string[] = [];
|
||||
if (pet) labelParts.push(`宠物 ${pet.name || '未命名'}`);
|
||||
if (doctor) labelParts.push(`医生 ${doctor.name || '未知'}`);
|
||||
return {
|
||||
label: labelParts.length ? labelParts.join(' / ') : '就诊记录',
|
||||
value: visit.id,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const getVisitLabel = (visitId: number) => {
|
||||
const visit = visits.value.find((item: any) => item.id === visitId);
|
||||
if (!visit) return visitId ? `就诊ID ${visitId}` : '-';
|
||||
return `就诊#${visit.id}`;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'visitId', title: '就诊ID' },
|
||||
{ colKey: 'visitId', title: '就诊' },
|
||||
{ colKey: 'chiefComplaint', title: '主诉' },
|
||||
{ colKey: 'diagnosis', title: '诊断' },
|
||||
{ colKey: 'status', title: '状态' },
|
||||
@@ -65,7 +109,7 @@ const load = async () => {
|
||||
const openCreate = () => {
|
||||
dialogTitle.value = '新增病历';
|
||||
editingId.value = null;
|
||||
form.visitId = query.visitId;
|
||||
form.visitId = query.visitId ? Number(query.visitId) : '';
|
||||
form.chiefComplaint = '';
|
||||
form.diagnosis = '';
|
||||
form.status = 'DRAFT';
|
||||
@@ -82,6 +126,23 @@ const openEdit = (row: any) => {
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const loadVisits = async () => {
|
||||
const res = await api.visits({ page: 1, size: 100 });
|
||||
if (res.code === 0) {
|
||||
visits.value = res.data?.records || res.data || [];
|
||||
}
|
||||
};
|
||||
|
||||
const loadPets = async () => {
|
||||
const res = await api.pets({ page: 1, size: 200 });
|
||||
if (res.code === 0) pets.value = res.data?.records || [];
|
||||
};
|
||||
|
||||
const loadDoctors = async () => {
|
||||
const res = await api.users({ page: 1, size: 200, role: 'DOCTOR' });
|
||||
if (res.code === 0) doctors.value = res.data?.records || [];
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
const payload = { ...form };
|
||||
const res = editingId.value
|
||||
@@ -105,4 +166,10 @@ const remove = async (id: number) => {
|
||||
MessagePlugin.error(res.message || '删除失败');
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadVisits();
|
||||
loadPets();
|
||||
loadDoctors();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
<t-button theme="primary" @click="load">查询</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #status="{ row }">
|
||||
{{ getStatusText(row.status) }}
|
||||
</template>
|
||||
<template #op="{ row }">
|
||||
<t-button size="small" variant="text" @click="openReply(row)">回复</t-button>
|
||||
</template>
|
||||
@@ -39,6 +42,14 @@ const statusOptions = [
|
||||
{ label: '已处理', value: 'PROCESSED' },
|
||||
];
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
const map: Record<string, string> = {
|
||||
PENDING: '待处理',
|
||||
PROCESSED: '已处理',
|
||||
};
|
||||
return map[status] || status || '-';
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'title', title: '标题' },
|
||||
|
||||
@@ -7,12 +7,15 @@
|
||||
<template #icon><t-icon name="refresh" /></template>
|
||||
刷新
|
||||
</t-button>
|
||||
<t-button variant="outline" @click="openCreate">
|
||||
<t-button v-if="canEdit" variant="outline" @click="openCreate">
|
||||
<template #icon><t-icon name="add" /></template>
|
||||
新增订单
|
||||
</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id" bordered stripe hover>
|
||||
<template #visitId="{ row }">
|
||||
{{ getVisitLabel(row.visitId) }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<span class="status-badge" :class="getStatusClass(row.status)">
|
||||
{{ getStatusText(row.status) }}
|
||||
@@ -23,7 +26,7 @@
|
||||
</template>
|
||||
<template #op="{ row }">
|
||||
<div class="table-actions">
|
||||
<t-button size="small" variant="outline" @click="openEdit(row)">
|
||||
<t-button v-if="canEdit" size="small" variant="outline" @click="openEdit(row)">
|
||||
<template #icon><t-icon name="edit" /></template>
|
||||
编辑
|
||||
</t-button>
|
||||
@@ -65,6 +68,7 @@
|
||||
import { onMounted, reactive, ref, computed } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const visits = ref([] as any[]);
|
||||
@@ -72,6 +76,9 @@ const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增订单');
|
||||
const editingId = ref<number | null>(null);
|
||||
const form = reactive({ visitId: '', amount: '', paymentMethod: 'OFFLINE', status: 'UNPAID' });
|
||||
const auth = useAuthStore();
|
||||
|
||||
const canEdit = computed(() => auth.user?.role === 'ADMIN');
|
||||
|
||||
const visitOptions = computed(() => {
|
||||
return visits.value.map((visit: any) => ({
|
||||
@@ -80,6 +87,12 @@ const visitOptions = computed(() => {
|
||||
}));
|
||||
});
|
||||
|
||||
const getVisitLabel = (visitId: number) => {
|
||||
const visit = visits.value.find((item: any) => item.id === visitId);
|
||||
if (!visit) return visitId ? `就诊ID ${visitId}` : '-';
|
||||
return `就诊#${visit.id}`;
|
||||
};
|
||||
|
||||
const getStatusText = (status: string) => {
|
||||
const statusMap: Record<string, string> = {
|
||||
'UNPAID': '未支付',
|
||||
@@ -127,7 +140,7 @@ const statusOptions = [
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'visitId', title: '就诊ID' },
|
||||
{ colKey: 'visitId', title: '就诊' },
|
||||
{ colKey: 'amount', title: '金额' },
|
||||
{ colKey: 'status', title: '状态' },
|
||||
{ colKey: 'paymentMethod', title: '支付方式' },
|
||||
@@ -140,6 +153,7 @@ const load = async () => {
|
||||
};
|
||||
|
||||
const openCreate = () => {
|
||||
if (!canEdit.value) return;
|
||||
dialogTitle.value = '新增订单';
|
||||
editingId.value = null;
|
||||
form.visitId = '';
|
||||
@@ -150,6 +164,7 @@ const openCreate = () => {
|
||||
};
|
||||
|
||||
const openEdit = (row: any) => {
|
||||
if (!canEdit.value) return;
|
||||
dialogTitle.value = '编辑订单';
|
||||
editingId.value = row.id;
|
||||
form.visitId = row.visitId || '';
|
||||
@@ -174,6 +189,7 @@ const loadVisits = async () => {
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
if (!canEdit.value) return;
|
||||
const payload = { ...form };
|
||||
const res = editingId.value
|
||||
? await api.updateOrder(editingId.value, payload)
|
||||
|
||||
@@ -3,11 +3,14 @@
|
||||
<h2 class="page-title">宠物档案</h2>
|
||||
<div class="panel">
|
||||
<div class="inline-form">
|
||||
<t-input v-model="query.ownerId" placeholder="主人ID" style="width: 160px" />
|
||||
<t-input v-if="!isCustomer" v-model="query.ownerId" placeholder="主人ID" style="width: 160px" />
|
||||
<t-button theme="primary" @click="load">查询</t-button>
|
||||
<t-button variant="outline" @click="openCreate">新增宠物</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #gender="{ row }">
|
||||
{{ getGenderText(row.gender) }}
|
||||
</template>
|
||||
<template #op="{ row }">
|
||||
<div class="table-actions">
|
||||
<t-button size="small" variant="text" @click="openEdit(row)">编辑</t-button>
|
||||
@@ -21,6 +24,9 @@
|
||||
|
||||
<t-dialog v-model:visible="dialogVisible" :header="dialogTitle" :on-confirm="submit">
|
||||
<t-form :data="form">
|
||||
<t-form-item v-if="!isCustomer" label="主人" required>
|
||||
<t-select v-model="form.ownerId" :options="customerOptions" placeholder="请选择主人" clearable />
|
||||
</t-form-item>
|
||||
<t-form-item label="名称"><t-input v-model="form.name" /></t-form-item>
|
||||
<t-form-item label="品种"><t-input v-model="form.breed" /></t-form-item>
|
||||
<t-form-item label="性别"><t-select v-model="form.gender" :options="genderOptions" /></t-form-item>
|
||||
@@ -31,16 +37,28 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
|
||||
const query = reactive({ ownerId: '' });
|
||||
const list = ref([] as any[]);
|
||||
const customers = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增宠物');
|
||||
const editingId = ref<number | null>(null);
|
||||
const form = reactive({ name: '', breed: '', gender: 'MALE', weight: '' });
|
||||
const form = reactive({ ownerId: '', name: '', breed: '', gender: 'MALE', weight: '' });
|
||||
const auth = useAuthStore();
|
||||
|
||||
const isCustomer = computed(() => auth.user?.role === 'CUSTOMER');
|
||||
|
||||
const customerOptions = computed(() => {
|
||||
return customers.value.map((customer: any) => ({
|
||||
label: customer.username || `顾客${customer.id}`,
|
||||
value: customer.id,
|
||||
}));
|
||||
});
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
@@ -56,6 +74,14 @@ const genderOptions = [
|
||||
{ label: '雌性', value: 'FEMALE' },
|
||||
];
|
||||
|
||||
const getGenderText = (gender: string) => {
|
||||
const map: Record<string, string> = {
|
||||
MALE: '雄性',
|
||||
FEMALE: '雌性',
|
||||
};
|
||||
return map[gender] || gender || '-';
|
||||
};
|
||||
|
||||
const load = async () => {
|
||||
const params: any = { page: 1, size: 20 };
|
||||
if (query.ownerId) params.ownerId = query.ownerId;
|
||||
@@ -66,6 +92,9 @@ const load = async () => {
|
||||
const openCreate = () => {
|
||||
dialogTitle.value = '新增宠物';
|
||||
editingId.value = null;
|
||||
form.ownerId = isCustomer.value
|
||||
? auth.user?.userId || ''
|
||||
: query.ownerId ? Number(query.ownerId) : '';
|
||||
form.name = '';
|
||||
form.breed = '';
|
||||
form.gender = 'MALE';
|
||||
@@ -76,6 +105,7 @@ const openCreate = () => {
|
||||
const openEdit = (row: any) => {
|
||||
dialogTitle.value = '编辑宠物';
|
||||
editingId.value = row.id;
|
||||
form.ownerId = row.ownerId || '';
|
||||
form.name = row.name || '';
|
||||
form.breed = row.breed || '';
|
||||
form.gender = row.gender || 'MALE';
|
||||
@@ -83,8 +113,18 @@ const openEdit = (row: any) => {
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const loadCustomers = async () => {
|
||||
const res = await api.users({ page: 1, size: 100, role: 'CUSTOMER' });
|
||||
if (res.code === 0) {
|
||||
customers.value = res.data?.records || [];
|
||||
}
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
const payload = { ...form };
|
||||
const payload = { ...form } as any;
|
||||
if (isCustomer.value) {
|
||||
payload.ownerId = auth.user?.userId || payload.ownerId;
|
||||
}
|
||||
const res = editingId.value
|
||||
? await api.updatePet(editingId.value, payload)
|
||||
: await api.createPet(payload);
|
||||
@@ -107,5 +147,10 @@ const remove = async (id: number) => {
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
onMounted(() => {
|
||||
load();
|
||||
if (!isCustomer.value) {
|
||||
loadCustomers();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id" bordered stripe hover>
|
||||
<template #visitId="{ row }">
|
||||
{{ getVisitLabel(row.visitId) }}
|
||||
</template>
|
||||
<template #doctorId="{ row }">
|
||||
{{ getDoctorName(row.doctorId) }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<span class="status-badge" :class="getStatusClass(row.status)">
|
||||
{{ getStatusText(row.status) }}
|
||||
@@ -71,6 +77,18 @@ const visitOptions = computed(() => {
|
||||
}));
|
||||
});
|
||||
|
||||
const getVisitLabel = (visitId: number) => {
|
||||
const visit = visits.value.find((item: any) => item.id === visitId);
|
||||
if (!visit) return visitId ? `就诊ID ${visitId}` : '-';
|
||||
return `就诊#${visit.id}`;
|
||||
};
|
||||
|
||||
const getDoctorName = (doctorId: number) => {
|
||||
const doctor = doctors.value.find((item: any) => item.id === doctorId);
|
||||
if (!doctor) return doctorId ? `医生ID ${doctorId}` : '-';
|
||||
return doctor.name || `医生${doctor.id}`;
|
||||
};
|
||||
|
||||
const doctorOptions = computed(() => {
|
||||
return doctors.value.map((doctor: any) => ({
|
||||
label: doctor.name,
|
||||
@@ -107,8 +125,8 @@ const statusOptions = [
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'visitId', title: '就诊ID' },
|
||||
{ colKey: 'doctorId', title: '医生ID' },
|
||||
{ colKey: 'visitId', title: '就诊' },
|
||||
{ colKey: 'doctorId', title: '医生' },
|
||||
{ colKey: 'status', title: '状态' },
|
||||
{ colKey: 'op', title: '操作', width: 100 },
|
||||
];
|
||||
|
||||
@@ -3,15 +3,18 @@
|
||||
<h2 class="page-title">检查报告</h2>
|
||||
<div class="panel">
|
||||
<div class="inline-form">
|
||||
<t-input v-model="query.petId" placeholder="宠物ID" style="width: 160px" />
|
||||
<t-select v-model="query.petId" :options="petOptions" placeholder="宠物" style="width: 200px" clearable />
|
||||
<t-button theme="primary" @click="load">查询</t-button>
|
||||
<t-button variant="outline" @click="openCreate">新增报告</t-button>
|
||||
<t-button v-if="canEdit" variant="outline" @click="openCreate">新增报告</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #petId="{ row }">
|
||||
{{ getPetName(row.petId) }}
|
||||
</template>
|
||||
<template #op="{ row }">
|
||||
<div class="table-actions">
|
||||
<t-button size="small" variant="text" @click="openEdit(row)">编辑</t-button>
|
||||
<t-popconfirm content="确认删除?" @confirm="remove(row.id)">
|
||||
<t-button v-if="canEdit" size="small" variant="text" @click="openEdit(row)">编辑</t-button>
|
||||
<t-popconfirm v-if="canEdit" content="确认删除?" @confirm="remove(row.id)">
|
||||
<t-button size="small" theme="danger" variant="text">删除</t-button>
|
||||
</t-popconfirm>
|
||||
</div>
|
||||
@@ -21,8 +24,12 @@
|
||||
|
||||
<t-dialog v-model:visible="dialogVisible" :header="dialogTitle" :on-confirm="submit">
|
||||
<t-form :data="form">
|
||||
<t-form-item label="就诊ID"><t-input v-model="form.visitId" /></t-form-item>
|
||||
<t-form-item label="宠物ID"><t-input v-model="form.petId" /></t-form-item>
|
||||
<t-form-item label="就诊记录" required>
|
||||
<t-select v-model="form.visitId" :options="visitOptions" placeholder="请选择就诊记录" clearable />
|
||||
</t-form-item>
|
||||
<t-form-item label="宠物" required>
|
||||
<t-select v-model="form.petId" :options="petOptions" placeholder="请选择宠物" clearable />
|
||||
</t-form-item>
|
||||
<t-form-item label="类型"><t-input v-model="form.type" /></t-form-item>
|
||||
<t-form-item label="标题"><t-input v-model="form.title" /></t-form-item>
|
||||
<t-form-item label="摘要"><t-textarea v-model="form.summary" /></t-form-item>
|
||||
@@ -32,20 +39,51 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const visits = ref([] as any[]);
|
||||
const pets = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增报告');
|
||||
const editingId = ref<number | null>(null);
|
||||
const query = reactive({ petId: '' });
|
||||
const form = reactive({ visitId: '', petId: '', type: '', title: '', summary: '' });
|
||||
const auth = useAuthStore();
|
||||
|
||||
const canEdit = computed(() => ['ADMIN', 'DOCTOR'].includes(auth.user?.role || ''));
|
||||
|
||||
const visitOptions = computed(() => {
|
||||
return visits.value.map((visit: any) => {
|
||||
const labelParts = [`就诊ID ${visit.id}`];
|
||||
if (visit.petId) labelParts.push(`宠物ID ${visit.petId}`);
|
||||
if (visit.customerId) labelParts.push(`顾客ID ${visit.customerId}`);
|
||||
return {
|
||||
label: labelParts.join(' / '),
|
||||
value: visit.id,
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
const petOptions = computed(() => {
|
||||
return pets.value.map((pet: any) => ({
|
||||
label: `${pet.name || '宠物'}${pet.breed ? ` (${pet.breed})` : ''}`,
|
||||
value: pet.id,
|
||||
}));
|
||||
});
|
||||
|
||||
const getPetName = (petId: number) => {
|
||||
const pet = pets.value.find((item: any) => item.id === petId);
|
||||
if (!pet) return petId ? `宠物ID ${petId}` : '-';
|
||||
return `${pet.name || '宠物'}${pet.breed ? ` (${pet.breed})` : ''}`;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'petId', title: '宠物ID' },
|
||||
{ colKey: 'petId', title: '宠物' },
|
||||
{ colKey: 'type', title: '类型' },
|
||||
{ colKey: 'title', title: '标题' },
|
||||
{ colKey: 'op', title: '操作', width: 140 },
|
||||
@@ -59,10 +97,11 @@ const load = async () => {
|
||||
};
|
||||
|
||||
const openCreate = () => {
|
||||
if (!canEdit.value) return;
|
||||
dialogTitle.value = '新增报告';
|
||||
editingId.value = null;
|
||||
form.visitId = '';
|
||||
form.petId = query.petId;
|
||||
form.petId = query.petId ? Number(query.petId) : '';
|
||||
form.type = '';
|
||||
form.title = '';
|
||||
form.summary = '';
|
||||
@@ -70,6 +109,7 @@ const openCreate = () => {
|
||||
};
|
||||
|
||||
const openEdit = (row: any) => {
|
||||
if (!canEdit.value) return;
|
||||
dialogTitle.value = '编辑报告';
|
||||
editingId.value = row.id;
|
||||
form.visitId = row.visitId || '';
|
||||
@@ -80,7 +120,18 @@ const openEdit = (row: any) => {
|
||||
dialogVisible.value = true;
|
||||
};
|
||||
|
||||
const loadVisits = async () => {
|
||||
const res = await api.visits({ page: 1, size: 100 });
|
||||
if (res.code === 0) visits.value = res.data?.records || [];
|
||||
};
|
||||
|
||||
const loadPets = async () => {
|
||||
const res = await api.pets({ page: 1, size: 100 });
|
||||
if (res.code === 0) pets.value = res.data?.records || [];
|
||||
};
|
||||
|
||||
const submit = async () => {
|
||||
if (!canEdit.value) return;
|
||||
const payload = { ...form };
|
||||
const res = editingId.value
|
||||
? await api.updateReport(editingId.value, payload)
|
||||
@@ -95,6 +146,7 @@ const submit = async () => {
|
||||
};
|
||||
|
||||
const remove = async (id: number) => {
|
||||
if (!canEdit.value) return;
|
||||
const res = await api.deleteReport(id);
|
||||
if (res.code === 0) {
|
||||
MessagePlugin.success('删除成功');
|
||||
@@ -104,5 +156,9 @@ const remove = async (id: number) => {
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
onMounted(() => {
|
||||
load();
|
||||
loadVisits();
|
||||
loadPets();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -6,12 +6,18 @@
|
||||
<t-button theme="primary" @click="load">刷新</t-button>
|
||||
<t-button variant="outline" @click="openCreate">新增入库</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id" />
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #drugId="{ row }">
|
||||
{{ getDrugName(row.drugId) }}
|
||||
</template>
|
||||
</t-table>
|
||||
</div>
|
||||
|
||||
<t-dialog v-model:visible="dialogVisible" header="新增入库" :on-confirm="submitCreate">
|
||||
<t-form :data="form">
|
||||
<t-form-item label="药品ID"><t-input v-model="form.drugId" /></t-form-item>
|
||||
<t-form-item label="药品" required>
|
||||
<t-select v-model="form.drugId" :options="drugOptions" placeholder="请选择药品" clearable />
|
||||
</t-form-item>
|
||||
<t-form-item label="数量"><t-input v-model="form.quantity" /></t-form-item>
|
||||
</t-form>
|
||||
</t-dialog>
|
||||
@@ -19,17 +25,31 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const form = reactive({ drugId: '', quantity: '' });
|
||||
const drugs = ref([] as any[]);
|
||||
|
||||
const drugOptions = computed(() => {
|
||||
return drugs.value.map((drug: any) => ({
|
||||
label: drug.name,
|
||||
value: drug.id,
|
||||
}));
|
||||
});
|
||||
|
||||
const getDrugName = (drugId: number) => {
|
||||
const drug = drugs.value.find((item: any) => item.id === drugId);
|
||||
if (!drug) return drugId ? `药品ID ${drugId}` : '-';
|
||||
return drug.name || `药品${drug.id}`;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'drugId', title: '药品ID' },
|
||||
{ colKey: 'drugId', title: '药品' },
|
||||
{ colKey: 'quantity', title: '数量' },
|
||||
{ colKey: 'stockInTime', title: '入库时间' },
|
||||
];
|
||||
@@ -39,6 +59,11 @@ const load = async () => {
|
||||
if (res.code === 0) list.value = res.data.records || [];
|
||||
};
|
||||
|
||||
const loadDrugs = async () => {
|
||||
const res = await api.drugs({ page: 1, size: 200 });
|
||||
if (res.code === 0) drugs.value = res.data?.records || [];
|
||||
};
|
||||
|
||||
const openCreate = () => {
|
||||
form.drugId = '';
|
||||
form.quantity = '';
|
||||
@@ -56,5 +81,8 @@ const submitCreate = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
onMounted(() => {
|
||||
load();
|
||||
loadDrugs();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -6,12 +6,18 @@
|
||||
<t-button theme="primary" @click="load">刷新</t-button>
|
||||
<t-button variant="outline" @click="openCreate">新增出库</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id" />
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #drugId="{ row }">
|
||||
{{ getDrugName(row.drugId) }}
|
||||
</template>
|
||||
</t-table>
|
||||
</div>
|
||||
|
||||
<t-dialog v-model:visible="dialogVisible" header="新增出库" :on-confirm="submitCreate">
|
||||
<t-form :data="form">
|
||||
<t-form-item label="药品ID"><t-input v-model="form.drugId" /></t-form-item>
|
||||
<t-form-item label="药品" required>
|
||||
<t-select v-model="form.drugId" :options="drugOptions" placeholder="请选择药品" clearable />
|
||||
</t-form-item>
|
||||
<t-form-item label="数量"><t-input v-model="form.quantity" /></t-form-item>
|
||||
</t-form>
|
||||
</t-dialog>
|
||||
@@ -19,17 +25,31 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, reactive, ref } from 'vue';
|
||||
import { computed, onMounted, reactive, ref } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const form = reactive({ drugId: '', quantity: '' });
|
||||
const drugs = ref([] as any[]);
|
||||
|
||||
const drugOptions = computed(() => {
|
||||
return drugs.value.map((drug: any) => ({
|
||||
label: drug.name,
|
||||
value: drug.id,
|
||||
}));
|
||||
});
|
||||
|
||||
const getDrugName = (drugId: number) => {
|
||||
const drug = drugs.value.find((item: any) => item.id === drugId);
|
||||
if (!drug) return drugId ? `药品ID ${drugId}` : '-';
|
||||
return drug.name || `药品${drug.id}`;
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'drugId', title: '药品ID' },
|
||||
{ colKey: 'drugId', title: '药品' },
|
||||
{ colKey: 'quantity', title: '数量' },
|
||||
{ colKey: 'stockOutTime', title: '出库时间' },
|
||||
];
|
||||
@@ -39,6 +59,11 @@ const load = async () => {
|
||||
if (res.code === 0) list.value = res.data.records || [];
|
||||
};
|
||||
|
||||
const loadDrugs = async () => {
|
||||
const res = await api.drugs({ page: 1, size: 200 });
|
||||
if (res.code === 0) drugs.value = res.data?.records || [];
|
||||
};
|
||||
|
||||
const openCreate = () => {
|
||||
form.drugId = '';
|
||||
form.quantity = '';
|
||||
@@ -56,5 +81,8 @@ const submitCreate = async () => {
|
||||
}
|
||||
};
|
||||
|
||||
onMounted(load);
|
||||
onMounted(() => {
|
||||
load();
|
||||
loadDrugs();
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -8,6 +8,12 @@
|
||||
<t-button variant="outline" @click="openCreate">新增账号</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id">
|
||||
<template #role="{ row }">
|
||||
{{ getRoleText(row.role) }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
{{ getStatusText(row.status) }}
|
||||
</template>
|
||||
<template #op="{ row }">
|
||||
<div class="table-actions">
|
||||
<t-button size="small" variant="text" @click="toggleStatus(row)">
|
||||
@@ -54,6 +60,23 @@ const roleOptions = [
|
||||
{ label: '顾客', value: 'CUSTOMER' },
|
||||
];
|
||||
|
||||
const getRoleText = (role: string) => {
|
||||
const map: Record<string, string> = {
|
||||
ADMIN: '管理员',
|
||||
DOCTOR: '医生',
|
||||
CUSTOMER: '顾客',
|
||||
};
|
||||
return map[role] || role || '-';
|
||||
};
|
||||
|
||||
const getStatusText = (status: number) => {
|
||||
const map: Record<number, string> = {
|
||||
0: '禁用',
|
||||
1: '启用',
|
||||
};
|
||||
return map[status] ?? '-';
|
||||
};
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'username', title: '用户名' },
|
||||
|
||||
@@ -13,6 +13,15 @@
|
||||
</t-button>
|
||||
</div>
|
||||
<t-table :data="list" :columns="columns" row-key="id" bordered stripe hover>
|
||||
<template #customerId="{ row }">
|
||||
{{ getCustomerName(row.customerId) }}
|
||||
</template>
|
||||
<template #petId="{ row }">
|
||||
{{ getPetName(row.petId) }}
|
||||
</template>
|
||||
<template #doctorId="{ row }">
|
||||
{{ getDoctorName(row.doctorId) }}
|
||||
</template>
|
||||
<template #status="{ row }">
|
||||
<span class="status-badge" :class="getStatusClass(row.status)">
|
||||
{{ getStatusText(row.status) }}
|
||||
@@ -90,6 +99,7 @@
|
||||
import { onMounted, reactive, ref, computed } from 'vue';
|
||||
import { MessagePlugin } from 'tdesign-vue-next';
|
||||
import { api } from '../api';
|
||||
import { useAuthStore } from '../store/auth';
|
||||
|
||||
const list = ref([] as any[]);
|
||||
const customers = ref([] as any[]);
|
||||
@@ -98,6 +108,9 @@ const doctors = ref([] as any[]);
|
||||
const dialogVisible = ref(false);
|
||||
const dialogTitle = ref('新增就诊');
|
||||
const editingId = ref<number | null>(null);
|
||||
const auth = useAuthStore();
|
||||
|
||||
const isAdmin = computed(() => auth.user?.role === 'ADMIN');
|
||||
const form = reactive({
|
||||
customerId: '',
|
||||
petId: '',
|
||||
@@ -123,7 +136,7 @@ const petOptions = computed(() => {
|
||||
|
||||
const doctorOptions = computed(() => {
|
||||
return doctors.value.map((doctor: any) => ({
|
||||
label: doctor.name,
|
||||
label: doctor.username || doctor.name,
|
||||
value: doctor.id
|
||||
}));
|
||||
});
|
||||
@@ -137,6 +150,24 @@ const getStatusText = (status: string) => {
|
||||
return statusMap[status] || status;
|
||||
};
|
||||
|
||||
const getCustomerName = (customerId: number) => {
|
||||
const customer = customers.value.find((item: any) => item.id === customerId);
|
||||
if (!customer) return customerId ? `顾客ID ${customerId}` : '-';
|
||||
return customer.username || `顾客${customer.id}`;
|
||||
};
|
||||
|
||||
const getPetName = (petId: number) => {
|
||||
const pet = pets.value.find((item: any) => item.id === petId);
|
||||
if (!pet) return petId ? `宠物ID ${petId}` : '-';
|
||||
return `${pet.name}${pet.breed ? ` (${pet.breed})` : ''}`;
|
||||
};
|
||||
|
||||
const getDoctorName = (doctorId: number) => {
|
||||
const doctor = doctors.value.find((item: any) => item.id === doctorId);
|
||||
if (!doctor) return doctorId ? `医生ID ${doctorId}` : '-';
|
||||
return doctor.username || doctor.name || `医生${doctor.id}`;
|
||||
};
|
||||
|
||||
const getStatusClass = (status: string) => {
|
||||
const classMap: Record<string, string> = {
|
||||
'IN_PROGRESS': 'status-pending',
|
||||
@@ -188,9 +219,9 @@ const payMethodOptions = [
|
||||
|
||||
const columns = [
|
||||
{ colKey: 'id', title: 'ID', width: 80 },
|
||||
{ colKey: 'customerId', title: '顾客ID' },
|
||||
{ colKey: 'petId', title: '宠物ID' },
|
||||
{ colKey: 'doctorId', title: '医生ID' },
|
||||
{ colKey: 'customerId', title: '顾客' },
|
||||
{ colKey: 'petId', title: '宠物' },
|
||||
{ colKey: 'doctorId', title: '医生' },
|
||||
{ colKey: 'status', title: '就诊状态' },
|
||||
{ colKey: 'paymentStatus', title: '支付状态' },
|
||||
{ colKey: 'totalAmount', title: '总金额', width: 100 },
|
||||
@@ -207,7 +238,7 @@ const openCreate = () => {
|
||||
editingId.value = null;
|
||||
form.customerId = '';
|
||||
form.petId = '';
|
||||
form.doctorId = '';
|
||||
form.doctorId = isAdmin.value ? '' : auth.user?.userId || '';
|
||||
form.status = 'IN_PROGRESS';
|
||||
form.paymentStatus = 'UNPAID';
|
||||
form.paymentMethod = 'OFFLINE';
|
||||
@@ -227,6 +258,10 @@ const openEdit = (row: any) => {
|
||||
};
|
||||
|
||||
const loadCustomers = async () => {
|
||||
if (!isAdmin.value) {
|
||||
customers.value = [];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await api.users({ page: 1, size: 100, role: 'CUSTOMER' }); // 获取所有顾客
|
||||
if (res.code === 0) {
|
||||
@@ -255,6 +290,12 @@ const loadPets = async () => {
|
||||
};
|
||||
|
||||
const loadDoctors = async () => {
|
||||
if (!isAdmin.value) {
|
||||
doctors.value = auth.user?.userId
|
||||
? [{ id: auth.user.userId, username: auth.user.username }]
|
||||
: [];
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await api.users({ page: 1, size: 100, role: 'DOCTOR' }); // 获取所有医生
|
||||
if (res.code === 0) {
|
||||
|
||||
527
pet_hospital_class_diagram.puml
Normal file
527
pet_hospital_class_diagram.puml
Normal file
@@ -0,0 +1,527 @@
|
||||
@startuml
|
||||
!theme plain
|
||||
skinparam backgroundColor #FFFFFF
|
||||
skinparam classAttributeIconSize 0
|
||||
skinparam linetype ortho
|
||||
|
||||
package "com.gpf.pethospital.entity" {
|
||||
class User {
|
||||
- Long id
|
||||
- String username
|
||||
- String phone
|
||||
- String email
|
||||
- String password
|
||||
- String role
|
||||
- Integer status
|
||||
- String avatar
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Appointment {
|
||||
- Long id
|
||||
- Long userId
|
||||
- Long petId
|
||||
- Long doctorId
|
||||
- LocalDateTime appointmentTime
|
||||
- String reason
|
||||
- String status
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Pet {
|
||||
- Long id
|
||||
- Long ownerId
|
||||
- String name
|
||||
- String species
|
||||
- String breed
|
||||
- String gender
|
||||
- LocalDate birthDate
|
||||
- String medicalHistory
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Drug {
|
||||
- Long id
|
||||
- String name
|
||||
- String category
|
||||
- String manufacturer
|
||||
- String description
|
||||
- BigDecimal price
|
||||
- Integer stock
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class MedicalRecord {
|
||||
- Long id
|
||||
- Long appointmentId
|
||||
- Long doctorId
|
||||
- Long petId
|
||||
- String symptoms
|
||||
- String diagnosis
|
||||
- String treatment
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Prescription {
|
||||
- Long id
|
||||
- Long medicalRecordId
|
||||
- String description
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class PrescriptionItem {
|
||||
- Long id
|
||||
- Long prescriptionId
|
||||
- Long drugId
|
||||
- Integer quantity
|
||||
- String usage
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Visit {
|
||||
- Long id
|
||||
- Long appointmentId
|
||||
- Long doctorId
|
||||
- Long petId
|
||||
- String chiefComplaint
|
||||
- String physicalExamination
|
||||
- String diagnosis
|
||||
- String treatmentPlan
|
||||
- LocalDateTime visitTime
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class VaccineRecord {
|
||||
- Long id
|
||||
- Long petId
|
||||
- Long vaccineId
|
||||
- String vaccineName
|
||||
- LocalDate vaccinationDate
|
||||
- LocalDate nextDueDate
|
||||
- String administeredBy
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Order {
|
||||
- Long id
|
||||
- Long userId
|
||||
- String orderNo
|
||||
- String status
|
||||
- BigDecimal totalAmount
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class StockIn {
|
||||
- Long id
|
||||
- Long drugId
|
||||
- Integer quantity
|
||||
- BigDecimal unitPrice
|
||||
- String supplier
|
||||
- String operator
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class StockOut {
|
||||
- Long id
|
||||
- Long drugId
|
||||
- Integer quantity
|
||||
- String purpose
|
||||
- String operator
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Message {
|
||||
- Long id
|
||||
- Long senderId
|
||||
- Long receiverId
|
||||
- String title
|
||||
- String content
|
||||
- String status
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Notice {
|
||||
- Long id
|
||||
- String title
|
||||
- String content
|
||||
- String publisher
|
||||
- LocalDateTime publishTime
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
|
||||
class Report {
|
||||
- Long id
|
||||
- String reportType
|
||||
- String title
|
||||
- String content
|
||||
- LocalDate reportDate
|
||||
- String generatedBy
|
||||
- LocalDateTime createTime
|
||||
- LocalDateTime updateTime
|
||||
- Integer deleted
|
||||
}
|
||||
}
|
||||
|
||||
package "com.gpf.pethospital.mapper" {
|
||||
interface BaseMapper<T> {
|
||||
+ insert(T entity): int
|
||||
+ deleteById(Serializable id): int
|
||||
+ updateById(T entity): int
|
||||
+ selectById(Serializable id): T
|
||||
+ selectList(Wrapper<T> queryWrapper): List<T>
|
||||
}
|
||||
|
||||
interface UserMapper {
|
||||
}
|
||||
|
||||
interface AppointmentMapper {
|
||||
}
|
||||
|
||||
interface PetMapper {
|
||||
}
|
||||
|
||||
interface DrugMapper {
|
||||
}
|
||||
|
||||
interface MedicalRecordMapper {
|
||||
}
|
||||
|
||||
interface PrescriptionMapper {
|
||||
}
|
||||
|
||||
interface PrescriptionItemMapper {
|
||||
}
|
||||
|
||||
interface VisitMapper {
|
||||
}
|
||||
|
||||
interface VaccineRecordMapper {
|
||||
}
|
||||
|
||||
interface OrderMapper {
|
||||
}
|
||||
|
||||
interface StockInMapper {
|
||||
}
|
||||
|
||||
interface StockOutMapper {
|
||||
}
|
||||
|
||||
interface MessageMapper {
|
||||
}
|
||||
|
||||
interface NoticeMapper {
|
||||
}
|
||||
|
||||
interface ReportMapper {
|
||||
}
|
||||
}
|
||||
|
||||
package "com.gpf.pethospital.service" {
|
||||
interface IService<T> {
|
||||
+ save(T entity): boolean
|
||||
+ removeById(Serializable id): boolean
|
||||
+ updateById(T entity): boolean
|
||||
+ getById(Serializable id): T
|
||||
+ list(): List<T>
|
||||
+ page(IPage<T> page, Wrapper<T> queryWrapper): IPage<T>
|
||||
}
|
||||
|
||||
interface UserService {
|
||||
+ register(User user): boolean
|
||||
+ login(String username, String password): AuthUser
|
||||
}
|
||||
|
||||
interface AppointmentService {
|
||||
+ book(Appointment appointment): boolean
|
||||
+ cancel(Long id): boolean
|
||||
+ getByUserId(Long userId): List<Appointment>
|
||||
}
|
||||
|
||||
interface PetService {
|
||||
+ getPetsByOwnerId(Long ownerId): List<Pet>
|
||||
+ updatePet(Pet pet): boolean
|
||||
}
|
||||
|
||||
interface DrugService {
|
||||
+ getLowStockDrugs(): List<Drug>
|
||||
+ updateStock(Long drugId, Integer quantity): boolean
|
||||
}
|
||||
|
||||
interface MedicalRecordService {
|
||||
+ createRecord(MedicalRecord record): boolean
|
||||
+ getRecordsByPetId(Long petId): List<MedicalRecord>
|
||||
}
|
||||
|
||||
interface PrescriptionService {
|
||||
+ createPrescription(Prescription prescription): boolean
|
||||
+ getPrescriptionsByRecordId(Long recordId): List<Prescription>
|
||||
}
|
||||
|
||||
interface PrescriptionItemService {
|
||||
+ addItems(Long prescriptionId, List<PrescriptionItem> items): boolean
|
||||
}
|
||||
|
||||
interface VisitService {
|
||||
+ createVisit(Visit visit): boolean
|
||||
+ getVisitsByAppointmentId(Long appointmentId): Visit
|
||||
}
|
||||
|
||||
interface VaccineRecordService {
|
||||
+ addVaccineRecord(VaccineRecord record): boolean
|
||||
+ getVaccineRecordsByPetId(Long petId): List<VaccineRecord>
|
||||
}
|
||||
|
||||
interface OrderService {
|
||||
+ createOrder(Order order): boolean
|
||||
+ updateOrderStatus(Long orderId, String status): boolean
|
||||
}
|
||||
|
||||
interface StockInService {
|
||||
+ addStock(StockIn stockIn): boolean
|
||||
}
|
||||
|
||||
interface StockOutService {
|
||||
+ consumeStock(StockOut stockOut): boolean
|
||||
}
|
||||
|
||||
interface MessageService {
|
||||
+ sendMessage(Message message): boolean
|
||||
+ getMessagesByUserId(Long userId): List<Message>
|
||||
}
|
||||
|
||||
interface NoticeService {
|
||||
+ publishNotice(Notice notice): boolean
|
||||
+ getPublishedNotices(): List<Notice>
|
||||
}
|
||||
|
||||
interface ReportService {
|
||||
+ generateReport(String type, LocalDate startDate, LocalDate endDate): Report
|
||||
+ getReportsByType(String type): List<Report>
|
||||
}
|
||||
}
|
||||
|
||||
package "com.gpf.pethospital.service.impl" {
|
||||
class UserServiceImpl {
|
||||
}
|
||||
|
||||
class AppointmentServiceImpl {
|
||||
}
|
||||
|
||||
class PetServiceImpl {
|
||||
}
|
||||
|
||||
class DrugServiceImpl {
|
||||
}
|
||||
|
||||
class MedicalRecordServiceImpl {
|
||||
}
|
||||
|
||||
class PrescriptionServiceImpl {
|
||||
}
|
||||
|
||||
class PrescriptionItemServiceImpl {
|
||||
}
|
||||
|
||||
class VisitServiceImpl {
|
||||
}
|
||||
|
||||
class VaccineRecordServiceImpl {
|
||||
}
|
||||
|
||||
class OrderServiceImpl {
|
||||
}
|
||||
|
||||
class StockInServiceImpl {
|
||||
}
|
||||
|
||||
class StockOutServiceImpl {
|
||||
}
|
||||
|
||||
class MessageServiceImpl {
|
||||
}
|
||||
|
||||
class NoticeServiceImpl {
|
||||
}
|
||||
|
||||
class ReportServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
package "com.gpf.pethospital.controller" {
|
||||
class UserController {
|
||||
- UserService userService
|
||||
- PasswordEncoder passwordEncoder
|
||||
+ me(): ApiResponse<?>
|
||||
+ updateMe(User payload): ApiResponse<?>
|
||||
+ list(long page, long size, String role): ApiResponse<?>
|
||||
+ create(User user): ApiResponse<?>
|
||||
+ updateStatus(Long id, Integer status): ApiResponse<?>
|
||||
+ resetPassword(Long id, String newPassword): ApiResponse<?>
|
||||
+ stats(): ApiResponse<?>
|
||||
}
|
||||
|
||||
class AppointmentController {
|
||||
- AppointmentService appointmentService
|
||||
+ book(Appointment appointment): ApiResponse<?>
|
||||
+ cancel(Long id): ApiResponse<?>
|
||||
+ list(Long userId, String status): ApiResponse<?>
|
||||
}
|
||||
|
||||
class PetController {
|
||||
- PetService petService
|
||||
+ listByOwner(Long ownerId): ApiResponse<?>
|
||||
+ create(Pet pet): ApiResponse<?>
|
||||
+ update(Pet pet): ApiResponse<?>
|
||||
}
|
||||
|
||||
class DrugController {
|
||||
- DrugService drugService
|
||||
+ list(String category, String keyword): ApiResponse<?>
|
||||
+ create(Drug drug): ApiResponse<?>
|
||||
+ update(Drug drug): ApiResponse<?>
|
||||
}
|
||||
|
||||
class MedicalRecordController {
|
||||
- MedicalRecordService medicalRecordService
|
||||
+ create(MedicalRecord record): ApiResponse<?>
|
||||
+ getByPet(Long petId): ApiResponse<?>
|
||||
}
|
||||
|
||||
class PrescriptionController {
|
||||
- PrescriptionService prescriptionService
|
||||
+ create(Prescription prescription): ApiResponse<?>
|
||||
+ getByRecord(Long recordId): ApiResponse<?>
|
||||
}
|
||||
|
||||
class PrescriptionItemController {
|
||||
- PrescriptionItemService prescriptionItemService
|
||||
+ addItems(Long prescriptionId, List<PrescriptionItem> items): ApiResponse<?>
|
||||
}
|
||||
|
||||
class VaccineRecordController {
|
||||
- VaccineRecordService vaccineRecordService
|
||||
+ addRecord(VaccineRecord record): ApiResponse<?>
|
||||
+ getByPet(Long petId): ApiResponse<?>
|
||||
}
|
||||
|
||||
class OrderController {
|
||||
- OrderService orderService
|
||||
+ create(Order order): ApiResponse<?>
|
||||
+ updateStatus(Long orderId, String status): ApiResponse<?>
|
||||
}
|
||||
|
||||
class StockInController {
|
||||
- StockInService stockInService
|
||||
+ addStock(StockIn stockIn): ApiResponse<?>
|
||||
}
|
||||
|
||||
class StockOutController {
|
||||
- StockOutService stockOutService
|
||||
+ consume(StockOut stockOut): ApiResponse<?>
|
||||
}
|
||||
|
||||
class MessageController {
|
||||
- MessageService messageService
|
||||
+ send(Message message): ApiResponse<?>
|
||||
+ listByUser(Long userId): ApiResponse<?>
|
||||
}
|
||||
|
||||
class NoticeController {
|
||||
- NoticeService noticeService
|
||||
+ publish(Notice notice): ApiResponse<?>
|
||||
+ list(): ApiResponse<?>
|
||||
}
|
||||
|
||||
class ReportController {
|
||||
- ReportService reportService
|
||||
+ generate(String type, LocalDate startDate, LocalDate endDate): ApiResponse<?>
|
||||
+ list(String type): ApiResponse<?>
|
||||
}
|
||||
|
||||
class AuthController {
|
||||
- UserService userService
|
||||
- JwtTokenUtil jwtTokenUtil
|
||||
+ register(User user): ApiResponse<?>
|
||||
+ login(UserLoginDto loginDto): ApiResponse<?>
|
||||
}
|
||||
}
|
||||
|
||||
package "com.gpf.pethospital.config" {
|
||||
class SecurityConfig {
|
||||
}
|
||||
|
||||
class WebConfig {
|
||||
}
|
||||
|
||||
class MybatisPlusConfig {
|
||||
}
|
||||
}
|
||||
|
||||
package "com.gpf.pethospital.common" {
|
||||
class ApiResponse {
|
||||
- Integer code
|
||||
- String message
|
||||
- Object data
|
||||
+ success(Object data): ApiResponse
|
||||
+ error(Integer code, String message): ApiResponse
|
||||
}
|
||||
}
|
||||
|
||||
' 关系映射
|
||||
User ||--o{ Appointment : "makes"
|
||||
User ||--o{ Pet : "owns"
|
||||
User ||--o{ MedicalRecord : "creates"
|
||||
User ||--o{ Message : "sends/receives"
|
||||
User ||--o{ Order : "places"
|
||||
|
||||
Pet ||--o{ Appointment : "has"
|
||||
Pet ||--o{ MedicalRecord : "has"
|
||||
Pet ||--o{ VaccineRecord : "has"
|
||||
Pet ||--o{ Visit : "has"
|
||||
|
||||
Appointment ||--|| MedicalRecord : "generates"
|
||||
Appointment ||--|| Visit : "generates"
|
||||
|
||||
Drug }o--o{ PrescriptionItem : "included in"
|
||||
Prescription ||--o{ PrescriptionItem : "contains"
|
||||
|
||||
MedicalRecord ||--o{ Prescription : "has"
|
||||
MedicalRecord ||--o{ Visit : "has"
|
||||
|
||||
StockIn ||--|| Drug : "affects"
|
||||
StockOut ||--|| Drug : "affects"
|
||||
|
||||
Order ||--o{ PrescriptionItem : "contains"
|
||||
|
||||
User ||--o{ VaccineRecord : "administers"
|
||||
|
||||
@enduml
|
||||
64
pet_hospital_sequence_diagram.puml
Normal file
64
pet_hospital_sequence_diagram.puml
Normal file
@@ -0,0 +1,64 @@
|
||||
@startuml
|
||||
!theme plain
|
||||
skinparam backgroundColor #FFFFFF
|
||||
skinparam sequence {
|
||||
ArrowColor #333333
|
||||
LifeLineBorderColor #777777
|
||||
LifeLineBackgroundColor #FFFFFF
|
||||
LifeLineBorderColor #AAAAAA
|
||||
ParticipantBorderColor #AAAAAA
|
||||
ParticipantBackgroundColor #F5F5F5
|
||||
ParticipantFontColor #333333
|
||||
ParticipantFontSize 12
|
||||
}
|
||||
|
||||
title Pet Hospital Appointment Booking Process
|
||||
|
||||
actor Customer as C
|
||||
participant "UserController" as UC
|
||||
participant "UserService" as US
|
||||
participant "AppointmentService" as AS
|
||||
participant "AppointmentMapper" as AM
|
||||
database "Database" as DB
|
||||
|
||||
C -> UC: Login(username, password)
|
||||
UC -> US: login(username, password)
|
||||
US -> DB: SELECT user FROM user WHERE username=?
|
||||
activate US
|
||||
return AuthUser
|
||||
return JWT Token
|
||||
deactivate US
|
||||
|
||||
C -> UC: View available pets
|
||||
UC -> US: getPetsByOwnerId(userId)
|
||||
activate US
|
||||
US -> DB: SELECT pets FROM pet WHERE ownerId=?
|
||||
return List<Pet>
|
||||
deactivate US
|
||||
|
||||
C -> UC: Book appointment(Appointment)
|
||||
activate UC
|
||||
UC -> AS: book(Appointment)
|
||||
activate AS
|
||||
AS -> DB: INSERT appointment
|
||||
activate AM
|
||||
AM -> DB: Insert appointment record
|
||||
return Success
|
||||
deactivate AM
|
||||
return Appointment ID
|
||||
deactivate AS
|
||||
return Success Response
|
||||
deactivate UC
|
||||
|
||||
C -> UC: View appointments
|
||||
UC -> AS: getByUserId(userId)
|
||||
activate AS
|
||||
AS -> DB: SELECT appointments FROM appointment WHERE userId=?
|
||||
return List<Appointment>
|
||||
deactivate AS
|
||||
return Appointment List
|
||||
deactivate UC
|
||||
|
||||
note right: Customer receives confirmation\nof successful booking
|
||||
|
||||
@enduml
|
||||
92
pet_hospital_use_case_diagram.puml
Normal file
92
pet_hospital_use_case_diagram.puml
Normal file
@@ -0,0 +1,92 @@
|
||||
@startuml
|
||||
!theme plain
|
||||
left to right direction
|
||||
skinparam backgroundColor #FFFFFF
|
||||
skinparam actorStyle awesome
|
||||
skinparam linetype ortho
|
||||
|
||||
actor "Customer" as Customer
|
||||
actor "Doctor" as Doctor
|
||||
actor "Admin" as Admin
|
||||
|
||||
package "Pet Hospital System" {
|
||||
usecase "Register Account" as UC1
|
||||
usecase "Login" as UC2
|
||||
usecase "View Profile" as UC3
|
||||
usecase "Update Profile" as UC4
|
||||
|
||||
usecase "View Pets" as UC5
|
||||
usecase "Add Pet" as UC6
|
||||
usecase "Update Pet Info" as UC7
|
||||
usecase "View Pet Records" as UC8
|
||||
|
||||
usecase "Book Appointment" as UC9
|
||||
usecase "Cancel Appointment" as UC10
|
||||
usecase "View Appointments" as UC11
|
||||
|
||||
usecase "View Prescriptions" as UC12
|
||||
usecase "View Medical Records" as UC13
|
||||
usecase "View Vaccination History" as UC14
|
||||
|
||||
usecase "View Available Time Slots" as UC15
|
||||
usecase "Confirm Appointment" as UC16
|
||||
|
||||
usecase "Manage Users" as UC17
|
||||
usecase "Manage Drugs" as UC18
|
||||
usecase "Manage Appointments" as UC19
|
||||
usecase "Generate Reports" as UC20
|
||||
|
||||
usecase "Create Medical Record" as UC21
|
||||
usecase "Create Prescription" as UC22
|
||||
usecase "Add Vaccination Record" as UC23
|
||||
usecase "Perform Visit" as UC24
|
||||
|
||||
usecase "View Statistics" as UC25
|
||||
usecase "View System Notices" as UC26
|
||||
usecase "Send Messages" as UC27
|
||||
}
|
||||
|
||||
Customer --> UC1
|
||||
Customer --> UC2
|
||||
Customer --> UC3
|
||||
Customer --> UC4
|
||||
Customer --> UC5
|
||||
Customer --> UC6
|
||||
Customer --> UC7
|
||||
Customer --> UC8
|
||||
Customer --> UC9
|
||||
Customer --> UC10
|
||||
Customer --> UC11
|
||||
Customer --> UC12
|
||||
Customer --> UC13
|
||||
Customer --> UC14
|
||||
Customer --> UC15
|
||||
Customer --> UC16
|
||||
Customer --> UC26
|
||||
Customer --> UC27
|
||||
|
||||
Doctor --> UC2
|
||||
Doctor --> UC3
|
||||
Doctor --> UC11
|
||||
Doctor --> UC13
|
||||
Doctor --> UC14
|
||||
Doctor --> UC21
|
||||
Doctor --> UC22
|
||||
Doctor --> UC23
|
||||
Doctor --> UC24
|
||||
Doctor --> UC26
|
||||
Doctor --> UC27
|
||||
|
||||
Admin --> UC17
|
||||
Admin --> UC18
|
||||
Admin --> UC19
|
||||
Admin --> UC20
|
||||
Admin --> UC25
|
||||
Admin --> UC26
|
||||
|
||||
UC9 ..> UC15 : includes
|
||||
UC21 ..> UC9 : extends
|
||||
UC22 ..> UC21 : extends
|
||||
UC24 ..> UC9 : extends
|
||||
|
||||
@enduml
|
||||
236
system_er_diagram.drawio
Normal file
236
system_er_diagram.drawio
Normal file
@@ -0,0 +1,236 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T13:55:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="system er diagram"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<!-- User实体 -->
|
||||
<mxCell id="2" value="User" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="80" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="+ id: BIGINT + username: VARCHAR(50) + phone: VARCHAR(20) + email: VARCHAR(100) + password: VARCHAR(255) + role: VARCHAR(20) + status: INT + avatar: VARCHAR(255) + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="2">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="4" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="2">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Doctor实体 -->
|
||||
<mxCell id="5" value="Doctor" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="80" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="6" value="+ id: BIGINT + name: VARCHAR(50) + department: VARCHAR(50) + title: VARCHAR(50) + phone: VARCHAR(20) + email: VARCHAR(100) + avatar: VARCHAR(255) + status: INT + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="5">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="7" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="5">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Pet实体 -->
|
||||
<mxCell id="8" value="Pet" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="540" y="80" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="9" value="+ id: BIGINT + owner_id: BIGINT + name: VARCHAR(50) + species: VARCHAR(50) + breed: VARCHAR(100) + gender: VARCHAR(10) + birthday: DATE + weight: DOUBLE + photo: VARCHAR(255) + remark: TEXT + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="8">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="10" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="8">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Appointment实体 -->
|
||||
<mxCell id="11" value="Appointment" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="380" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="+ id: BIGINT + customer_id: BIGINT + pet_id: BIGINT + doctor_id: BIGINT + department: VARCHAR(50) + appointment_date: DATE + time_slot: VARCHAR(20) + status: VARCHAR(20) + remark: TEXT + cancel_time: TIMESTAMP + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="11">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="11">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Visit实体 -->
|
||||
<mxCell id="14" value="Visit" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="380" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="+ id: BIGINT + appointment_id: BIGINT + customer_id: BIGINT + pet_id: BIGINT + doctor_id: BIGINT + symptoms: TEXT + diagnosis: TEXT + treatment_plan: TEXT + status: VARCHAR(20) + total_amount: DECIMAL(10,2) + payment_status: VARCHAR(20) + payment_method: VARCHAR(20) + payment_time: TIMESTAMP + start_time: TIMESTAMP + end_time: TIMESTAMP + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="14">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="14">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Medical Record实体 -->
|
||||
<mxCell id="17" value="Medical Record" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="540" y="380" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="+ id: BIGINT + visit_id: BIGINT + record_type: VARCHAR(50) + content: TEXT + attachment_urls: TEXT + doctor_id: BIGINT + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="17">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="19" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="17">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Prescription实体 -->
|
||||
<mxCell id="20" value="Prescription" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="680" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="+ id: BIGINT + visit_id: BIGINT + doctor_id: BIGINT + customer_id: BIGINT + total_amount: DECIMAL(10,2) + status: VARCHAR(20) + remark: TEXT + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="20">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="20">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- Drug实体 -->
|
||||
<mxCell id="23" value="Drug" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;comic=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="320" y="680" width="160" height="230" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="+ id: BIGINT + name: VARCHAR(100) + category: VARCHAR(50) + manufacturer: VARCHAR(100) + specification: VARCHAR(100) + unit_price: DECIMAL(10,2) + stock_quantity: INT + unit: VARCHAR(20) + status: INT + create_time: TIMESTAMP + update_time: TIMESTAMP + deleted: INT" style="text;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="23">
|
||||
<mxGeometry y="26" width="160" height="204" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="" style="line;strokeWidth=1;fillColor=none;align=left;verticalAlign=middle;spacingTop=-1;spacingLeft=3;spacingRight=3;rotatable=0;labelPosition=right;points=[];portConstraint=eastwest;" vertex="1" parent="23">
|
||||
<mxGeometry y="230" width="160" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 关系连线 -->
|
||||
<mxCell id="26" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="2" target="8">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="280" y="200" as="sourcePoint"/>
|
||||
<mxPoint x="520" y="200" as="targetPoint"/>
|
||||
<Array as="points">
|
||||
<mxPoint x="260" y="200"/>
|
||||
<mxPoint x="540" y="200"/>
|
||||
</Array>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="26">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="28" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="2" target="11">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="280" y="210" as="sourcePoint"/>
|
||||
<mxPoint x="520" y="210" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="29" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="28">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="30" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="5" target="11">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="290" y="220" as="sourcePoint"/>
|
||||
<mxPoint x="530" y="220" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="31" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="30">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="32" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="8" target="11">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="300" y="230" as="sourcePoint"/>
|
||||
<mxPoint x="540" y="230" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="33" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="32">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="34" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="11" target="14">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="310" y="240" as="sourcePoint"/>
|
||||
<mxPoint x="550" y="240" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="35" value="1" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="34">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="36" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="2" target="14">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="250" as="sourcePoint"/>
|
||||
<mxPoint x="560" y="250" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="37" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="36">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="38" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="8" target="14">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="330" y="260" as="sourcePoint"/>
|
||||
<mxPoint x="570" y="260" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="39" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="38">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="40" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="5" target="14">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="340" y="270" as="sourcePoint"/>
|
||||
<mxPoint x="580" y="270" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="41" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="40">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="42" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="14" target="17">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="350" y="280" as="sourcePoint"/>
|
||||
<mxPoint x="590" y="280" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="43" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="42">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="44" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="5" target="17">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="360" y="290" as="sourcePoint"/>
|
||||
<mxPoint x="600" y="290" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="45" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="44">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="46" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="14" target="20">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="300" as="sourcePoint"/>
|
||||
<mxPoint x="610" y="300" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="47" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="46">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="48" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="5" target="20">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="380" y="310" as="sourcePoint"/>
|
||||
<mxPoint x="620" y="310" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="49" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="48">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="50" value="1" style="endArrow=open;endSize=12;startArrow=diamondThin;startSize=14;startFill=0;edgeStyle=orthogonalEdgeStyle;align=left;verticalAlign=bottom;" edge="1" parent="1" source="2" target="20">
|
||||
<mxGeometry x="-1" y="3" relative="1" as="geometry">
|
||||
<mxPoint x="390" y="320" as="sourcePoint"/>
|
||||
<mxPoint x="630" y="320" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="51" value="*" style="text;html=1;resizable=0;points=[];align=center;verticalAlign=middle;labelBackgroundColor=#ffffff;" vertex="1" connectable="0" parent="50">
|
||||
<mxGeometry x="0.7692" y="-1" relative="1" as="geometry">
|
||||
<mxPoint x="-11" y="-13" as="offset"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
2059
thesis_with_diagrams.md
Normal file
2059
thesis_with_diagrams.md
Normal file
File diff suppressed because it is too large
Load Diff
56
uml_diagrams_readme.md
Normal file
56
uml_diagrams_readme.md
Normal file
@@ -0,0 +1,56 @@
|
||||
# 爱维宠物医院管理系统 - UML图说明文档
|
||||
|
||||
本目录包含为爱维宠物医院管理系统设计的各种UML图,均按照《2026届网络工程毕业设计论文撰写规范(应用开发类)》要求制作。
|
||||
|
||||
## 文件说明
|
||||
|
||||
### 1. pet_hospital_uml.drawio
|
||||
- **类型**: 用例图和类图
|
||||
- **内容**:
|
||||
- 系统用例图,展示三个角色(顾客、医生、管理员)的功能用例
|
||||
- 系统类图,展示主要实体类及其关系
|
||||
|
||||
### 2. sequence_diagram.drawio
|
||||
- **类型**: 序列图
|
||||
- **内容**: 预约挂号流程的序列图,展示顾客、系统、预约服务和数据库之间的交互
|
||||
|
||||
### 3. activity_diagram.drawio
|
||||
- **类型**: 活动图
|
||||
- **内容**: 医生接诊流程的活动图,展示从登录到结束就诊的完整流程
|
||||
|
||||
### 4. er_diagram.drawio
|
||||
- **类型**: 实体关系图
|
||||
- **内容**: 数据库实体关系图,展示系统各实体及它们之间的关系
|
||||
|
||||
## 如何使用
|
||||
|
||||
1. 安装draw.io (现在称为 diagrams.net)
|
||||
- 访问 https://app.diagrams.net/
|
||||
- 或下载桌面版
|
||||
|
||||
2. 打开文件
|
||||
- 在draw.io中选择"文件" → "打开"
|
||||
- 选择对应的.drawio文件
|
||||
|
||||
3. 编辑和导出
|
||||
- 可以根据需要调整图形样式
|
||||
- 选择"文件" → "导出为" → 选择所需格式(PNG、PDF、SVG等)
|
||||
|
||||
## 论文中应用位置
|
||||
|
||||
根据撰写规范要求,这些图表可用于:
|
||||
|
||||
- 第3章 系统分析: 用例图
|
||||
- 第3.4节 用例描述: 用例图
|
||||
- 第4章 系统设计: 类图、序列图、活动图、ER图
|
||||
- 第4.2节 类图: 系统类图
|
||||
- 第4.3节 序列图: 序列图
|
||||
- 第4.4节 活动图: 活动图
|
||||
- 第4.5节 数据库设计: ER图
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 所有图表均已按照规范要求设计,包含足够的实体和关系
|
||||
2. 图表命名遵循章节编号规则
|
||||
3. 可根据实际需要调整图表细节
|
||||
4. 导出图像时建议使用高分辨率以保证打印质量
|
||||
72
updated_uml_diagrams_readme.md
Normal file
72
updated_uml_diagrams_readme.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# 爱维宠物医院管理系统 - UML图说明文档
|
||||
|
||||
本目录包含为爱维宠物医院管理系统设计的各种UML图,均按照《2026届网络工程毕业设计论文撰写规范(应用开发类)》要求制作。
|
||||
|
||||
## 文件说明
|
||||
|
||||
### 1. pet_hospital_uml.drawio
|
||||
- **类型**: 用例图和类图
|
||||
- **内容**:
|
||||
- 系统用例图,展示三个角色(顾客、医生、管理员)的功能用例
|
||||
- 系统类图,展示主要实体类及其关系
|
||||
|
||||
### 2. sequence_diagram.drawio
|
||||
- **类型**: 序列图
|
||||
- **内容**: 预约挂号流程的序列图,展示医生、系统、预约服务和数据库之间的交互
|
||||
|
||||
### 3. customer_sequence_diagram.drawio
|
||||
- **类型**: 序列图
|
||||
- **内容**: 顾客预约流程的序列图,展示顾客、系统、预约服务和数据库之间的交互
|
||||
|
||||
### 4. admin_sequence_diagram.drawio
|
||||
- **类型**: 序列图
|
||||
- **内容**: 管理员管理药品流程的序列图,展示管理员、系统、药品管理模块和数据库之间的交互
|
||||
|
||||
### 5. activity_diagram.drawio
|
||||
- **类型**: 活动图
|
||||
- **内容**: 医生接诊流程的活动图,展示从登录到结束就诊的完整流程
|
||||
|
||||
### 6. customer_activity_diagram.drawio
|
||||
- **类型**: 活动图
|
||||
- **内容**: 顾客查看病历流程的活动图,展示从登录到查看病历再到退出的完整流程
|
||||
|
||||
### 7. admin_activity_diagram.drawio
|
||||
- **类型**: 活动图
|
||||
- **内容**: 管理员管理用户流程的活动图,展示从登录到管理用户再到退出的完整流程
|
||||
|
||||
### 8. er_diagram.drawio
|
||||
- **类型**: 实体关系图
|
||||
- **内容**: 数据库实体关系图,展示系统各实体及它们之间的关系
|
||||
|
||||
## 如何使用
|
||||
|
||||
1. 安装draw.io (现在称为 diagrams.net)
|
||||
- 访问 https://app.diagrams.net/
|
||||
- 或下载桌面版
|
||||
|
||||
2. 打开文件
|
||||
- 在draw.io中选择"文件" → "打开"
|
||||
- 选择对应的.drawio文件
|
||||
|
||||
3. 编辑和导出
|
||||
- 可以根据需要调整图形样式
|
||||
- 选择"文件" → "导出为" → 选择所需格式(PNG、PDF、SVG等)
|
||||
|
||||
## 论文中应用位置
|
||||
|
||||
根据撰写规范要求,这些图表可用于:
|
||||
|
||||
- 第3章 系统分析: 用例图
|
||||
- 第3.4节 用例描述: 用例图
|
||||
- 第4章 系统设计: 类图、序列图、活动图、ER图
|
||||
- 第4.2节 类图: 系统类图
|
||||
- 第4.3节 序列图: 医生预约序列图、顾客预约序列图、管理员管理药品序列图
|
||||
- 第4.4节 活动图: 医生接诊活动图、顾客查看病历活动图、管理员管理用户活动图
|
||||
- 第4.5节 数据库设计: ER图
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. 所有图表均已按照规范要求设计,包含足够的实体和关系
|
||||
2. 图表命名遵循章节编号规则
|
||||
3. 可根据实际需要调整图表细节
|
||||
4. 导出图像时建议使用高分辨率以保证打印质量
|
||||
189
user_activity_diagram.drawio
Normal file
189
user_activity_diagram.drawio
Normal file
@@ -0,0 +1,189 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T13:55:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="user activity diagram"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<!-- 开始节点 -->
|
||||
<mxCell id="2" value="" style="ellipse;html=1;shape=startState;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="40" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="3" value="顾客登录系统" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="110" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 状态节点 -->
|
||||
<mxCell id="4" value="系统验证顾客身份" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="180" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 判断节点 -->
|
||||
<mxCell id="5" value="" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="250" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="6" value="显示错误信息" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="245" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="7" value="进入个人中心" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="320" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="8" value="选择宠物" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="390" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="9" value="查看病历记录" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="460" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="10" value="选择查看时间范围" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="530" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="11" value="系统查询病历数据" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="600" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="12" value="显示病历信息" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="670" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="13" value="查看病历详情" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="740" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 判断节点 -->
|
||||
<mxCell id="14" value="" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="810" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="15" value="下载病历" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="460" y="805" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="16" value="继续浏览其他病历" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="880" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 活动节点 -->
|
||||
<mxCell id="17" value="退出系统" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="335" y="950" width="80" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 结束节点 -->
|
||||
<mxCell id="18" value="" style="ellipse;html=1;shape=endState;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="1020" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 结束节点 -->
|
||||
<mxCell id="19" value="" style="ellipse;html=1;shape=endState;fillColor=#000000;strokeColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="500" y="315" width="30" height="30" as="geometry"/>
|
||||
</mxCell>
|
||||
<!-- 连接线 -->
|
||||
<mxCell id="20" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;exitPerimeter=0;entryX=0.5;entryY=0;" edge="1" parent="1" source="2" target="3">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="210" y="140" as="sourcePoint"/>
|
||||
<mxPoint x="260" y="90" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="3" target="4">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="220" y="150" as="sourcePoint"/>
|
||||
<mxPoint x="270" y="100" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="4" target="5">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="230" y="160" as="sourcePoint"/>
|
||||
<mxPoint x="280" y="110" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="23" value="是" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="5" target="7">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="240" y="170" as="sourcePoint"/>
|
||||
<mxPoint x="290" y="120" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="否" style="endArrow=classic;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="5" target="6">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="250" y="180" as="sourcePoint"/>
|
||||
<mxPoint x="300" y="130" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="7" target="8">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="290" as="sourcePoint"/>
|
||||
<mxPoint x="310" y="240" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="26" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="8" target="9">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="270" y="300" as="sourcePoint"/>
|
||||
<mxPoint x="320" y="250" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="9" target="10">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="280" y="310" as="sourcePoint"/>
|
||||
<mxPoint x="330" y="260" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="28" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="10" target="11">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="290" y="320" as="sourcePoint"/>
|
||||
<mxPoint x="340" y="270" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="29" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="11" target="12">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="300" y="330" as="sourcePoint"/>
|
||||
<mxPoint x="350" y="280" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="30" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="12" target="13">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="310" y="340" as="sourcePoint"/>
|
||||
<mxPoint x="360" y="290" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="31" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="13" target="14">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="320" y="350" as="sourcePoint"/>
|
||||
<mxPoint x="370" y="300" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="32" value="是" style="endArrow=classic;html=1;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="14" target="15">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="340" y="370" as="sourcePoint"/>
|
||||
<mxPoint x="390" y="320" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="33" value="否" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="14" target="16">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="350" y="380" as="sourcePoint"/>
|
||||
<mxPoint x="400" y="330" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="34" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="15" target="16">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="360" y="390" as="sourcePoint"/>
|
||||
<mxPoint x="410" y="340" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="35" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="16" target="17">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="400" as="sourcePoint"/>
|
||||
<mxPoint x="420" y="350" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="36" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="17" target="18">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="380" y="410" as="sourcePoint"/>
|
||||
<mxPoint x="430" y="360" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="37" value="" style="endArrow=classic;html=1;exitX=0.5;exitY=1;entryX=0.5;entryY=0;" edge="1" parent="1" source="6" target="19">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||
<mxPoint x="500" y="430" as="sourcePoint"/>
|
||||
<mxPoint x="550" y="380" as="targetPoint"/>
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
14
user_entity.drawio
Normal file
14
user_entity.drawio
Normal file
@@ -0,0 +1,14 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T13:55:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="???????"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="??(User)" style="swimlane;fontStyle=1;align=center;verticalAlign=top;childLayout=stackLayout;horizontal=1;startSize=26;horizontalStack=0;resizeParent=1;resizeParentMax=0;resizeLast=0;collapsible=1;marginBottom=0;swimlaneFillColor=#ffffff;rounded=0;shadow=0;labelBackgroundColor=none;strokeColor=#000000;strokeWidth=1;fillColor=none;fontFamily=Verdana;fontSize=12;fontColor=#000000;" vertex="1" parent="1">
|
||||
<mxGeometry x="200" y="120" width="240" height="260" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="+ user_id: BIGINT
+ username: VARCHAR(50)
+ phone: VARCHAR(20)
+ email: VARCHAR(100)
+ password: VARCHAR(255)
+ role: VARCHAR(20)
+ status: INT
+ avatar: VARCHAR(255)
+ create_time: TIMESTAMP
+ update_time: TIMESTAMP
+ deleted: INT" style="text;html=1;whiteSpace=wrap;strokeColor=none;fillColor=none;align=left;verticalAlign=top;spacingLeft=4;spacingRight=4;overflow=hidden;rotatable=0;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;" vertex="1" parent="2">
|
||||
<mxGeometry y="26" width="240" height="234" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
89
user_function_structure.drawio
Normal file
89
user_function_structure.drawio
Normal file
@@ -0,0 +1,89 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T14:00:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="用户功能结构图"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="用户功能结构" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="310" y="40" width="180" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="10" value="账户与资料" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="140" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="100" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="10">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="11" value="注册/登录" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="130" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="101" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="10" target="11">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="个人资料维护" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="176" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="102" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="11" target="12">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="宠物管理" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="230" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="103" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="13">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="14" value="宠物档案维护" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="220" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="104" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="13" target="14">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="预约与就诊" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="320" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="105" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="15">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="预约挂号" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="310" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="106" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="15" target="16">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="17" value="查看预约记录" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="356" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="107" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="16" target="17">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="记录与查询" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="410" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="108" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="18">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="19" value="病历/处方查看" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="400" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="109" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="18" target="19">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="20" value="报告查询" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="446" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="110" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="19" target="20">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="费用支付" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#333333;" vertex="1" parent="1">
|
||||
<mxGeometry x="100" y="500" width="180" height="40" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="111" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="2" target="21">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="费用结算与支付" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffffff;strokeColor=#666666;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="490" width="180" height="36" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="112" value="" style="endArrow=classic;html=1;" edge="1" parent="1" source="21" target="22">
|
||||
<mxGeometry relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
180
user_sequence_diagram.drawio
Normal file
180
user_sequence_diagram.drawio
Normal file
@@ -0,0 +1,180 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T14:02:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="user sequence diagram"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0" />
|
||||
<mxCell id="1" parent="0" />
|
||||
|
||||
<mxCell id="2" value="顾客" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="60" width="80" height="700" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="3" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="2">
|
||||
<mxGeometry x="35" y="60" width="10" height="640" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="4" value="系统" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="60" width="80" height="700" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="5" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="4">
|
||||
<mxGeometry x="35" y="70" width="10" height="630" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="6" value="预约服务" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="360" y="60" width="80" height="700" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="7" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="6">
|
||||
<mxGeometry x="35" y="90" width="10" height="610" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="8" value="数据库" style="shape=umlLifeline;perimeter=lifelinePerimeter;whiteSpace=wrap;html=1;container=1;collapsible=0;recursiveResize=0;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="500" y="60" width="80" height="700" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="9" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="8">
|
||||
<mxGeometry x="35" y="110" width="10" height="590" as="geometry" />
|
||||
</mxCell>
|
||||
|
||||
<mxCell id="10" value="" style="html=1;points=[];perimeter=orthogonalPerimeter;" vertex="1" parent="1">
|
||||
<mxGeometry x="125" y="140" width="10" height="30" as="geometry" />
|
||||
</mxCell>
|
||||
<mxCell id="11" value="登录系统" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="3" target="10">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="140" y="155" as="sourcePoint" />
|
||||
<mxPoint x="225" y="155" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="验证用户身份" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="5" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="260" y="180" as="sourcePoint" />
|
||||
<mxPoint x="365" y="180" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="返回验证结果" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="7" target="5">
|
||||
<mxGeometry x="0.16" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="210" as="targetPoint" />
|
||||
<mxPoint x="320" y="210" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="14" value="登录成功" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="10" target="3">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="140" y="240" as="targetPoint" />
|
||||
<mxPoint x="200" y="240" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="请求可预约时间段" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="3" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="140" y="270" as="sourcePoint" />
|
||||
<mxPoint x="350" y="270" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="查询可用时间段" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="5" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="260" y="300" as="sourcePoint" />
|
||||
<mxPoint x="365" y="300" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="17" value="查询预约数据" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="7" target="9">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="370" y="330" as="sourcePoint" />
|
||||
<mxPoint x="450" y="330" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="18" value="返回可用时间段" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="9" target="7">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="360" as="targetPoint" />
|
||||
<mxPoint x="430" y="360" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="19" value="返回可用时间段" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="7" target="5">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="390" as="targetPoint" />
|
||||
<mxPoint x="320" y="390" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="20" value="显示可预约时间段" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="5" target="3">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="140" y="420" as="targetPoint" />
|
||||
<mxPoint x="200" y="420" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="21" value="选择医生、时间段和宠物" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="3" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="140" y="450" as="sourcePoint" />
|
||||
<mxPoint x="350" y="450" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="22" value="验证时段可用性" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="5" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="260" y="480" as="sourcePoint" />
|
||||
<mxPoint x="365" y="480" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="23" value="检查时段是否已被预约" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="7" target="9">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="370" y="510" as="sourcePoint" />
|
||||
<mxPoint x="450" y="510" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="24" value="返回验证结果" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="9" target="7">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="540" as="targetPoint" />
|
||||
<mxPoint x="430" y="540" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="25" value="返回验证结果" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="7" target="5">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="570" as="targetPoint" />
|
||||
<mxPoint x="320" y="570" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="26" value="验证通过" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="5" target="3">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="140" y="600" as="targetPoint" />
|
||||
<mxPoint x="200" y="600" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="27" value="确认预约信息" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="3" target="5">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="140" y="630" as="sourcePoint" />
|
||||
<mxPoint x="350" y="630" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="28" value="创建预约记录" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="5" target="7">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="260" y="660" as="sourcePoint" />
|
||||
<mxPoint x="365" y="660" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="29" value="保存预约信息" style="html=1;verticalAlign=bottom;endArrow=block;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=1;exitY=0.5;entryX=0;entryY=0.5;" edge="1" parent="1" source="7" target="9">
|
||||
<mxGeometry relative="1" as="geometry">
|
||||
<mxPoint x="370" y="690" as="sourcePoint" />
|
||||
<mxPoint x="450" y="690" as="targetPoint" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="30" value="保存成功" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="9" target="7">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="370" y="720" as="targetPoint" />
|
||||
<mxPoint x="430" y="720" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="31" value="预约创建成功" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="7" target="5">
|
||||
<mxGeometry x="0.1" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="260" y="750" as="targetPoint" />
|
||||
<mxPoint x="320" y="750" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
<mxCell id="32" value="预约确认信息" style="html=1;verticalAlign=bottom;endArrow=block;endSize=8;startArrow=classic;startSize=8;labelBackgroundColor=none;edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;exitX=0;exitY=0.5;entryX=1;entryY=0.5;" edge="1" parent="1" source="5" target="3">
|
||||
<mxGeometry x="0.08" y="-20" relative="1" as="geometry">
|
||||
<mxPoint x="140" y="780" as="targetPoint" />
|
||||
<mxPoint x="200" y="780" as="sourcePoint" />
|
||||
<mxPoint as="offset" />
|
||||
</mxGeometry>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
62
user_use_case.drawio
Normal file
62
user_use_case.drawio
Normal file
@@ -0,0 +1,62 @@
|
||||
<mxfile host="app.diagrams.net" modified="2026-01-30T14:00:00.000Z" agent="codex" version="24.7.7">
|
||||
<diagram name="用户用例图"><mxGraphModel dx="1426" dy="769" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" background="#ffffff" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="2" value="爱维宠物医院管理系统" style="html=1;fontStyle=1;verticalAlign=top;align=left;spacingTop=8;spacingLeft=6;spacingRight=12;shape=cube;size=10;direction=south;fontSize=14;" vertex="1" parent="1">
|
||||
<mxGeometry x="20" y="20" width="760" height="520" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="3" value="用户" style="shape=umlActor;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
|
||||
<mxGeometry x="80" y="220" width="30" height="60" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="10" value="注册/登录" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="80" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="11" value="个人资料管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="150" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="12" value="宠物档案管理" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="220" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="13" value="预约挂号" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="220" y="290" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="14" value="查看预约记录" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="80" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="15" value="查看病历与处方" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="150" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="16" value="查询报告" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="220" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="17" value="费用支付" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||
<mxGeometry x="420" y="290" width="120" height="50" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="100" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="10">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="101" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="11">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="102" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="12">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="103" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="13">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="104" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="14">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="105" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="15">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="106" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="16">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
<mxCell id="107" value="" style="endArrow=none;html=1;entryX=0;entryY=0.5;exitX=1;exitY=0.5;exitPerimeter=0;" edge="1" parent="1" source="3" target="17">
|
||||
<mxGeometry width="50" height="50" relative="1" as="geometry"/>
|
||||
</mxCell>
|
||||
</root>
|
||||
</mxGraphModel></diagram>
|
||||
</mxfile>
|
||||
BIN
~$宠物医院管理系统毕业论文-正确转换版.docx
Normal file
BIN
~$宠物医院管理系统毕业论文-正确转换版.docx
Normal file
Binary file not shown.
BIN
爱维宠物医院管理系统毕业论文-含图表版.docx
Normal file
BIN
爱维宠物医院管理系统毕业论文-含图表版.docx
Normal file
Binary file not shown.
BIN
爱维宠物医院管理系统毕业论文-改进版.docx
Normal file
BIN
爱维宠物医院管理系统毕业论文-改进版.docx
Normal file
Binary file not shown.
BIN
爱维宠物医院管理系统毕业论文-正确转换版.docx
Normal file
BIN
爱维宠物医院管理系统毕业论文-正确转换版.docx
Normal file
Binary file not shown.
BIN
爱维宠物医院管理系统毕业论文-由markdown转换版.docx
Normal file
BIN
爱维宠物医院管理系统毕业论文-由markdown转换版.docx
Normal file
Binary file not shown.
1639
爱维宠物医院管理系统毕业论文.md
Normal file
1639
爱维宠物医院管理系统毕业论文.md
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user