diff --git a/.gitmodules b/.gitmodules
index 588e4fc..e69de29 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +0,0 @@
-[submodule "rlz"]
- path = rlz
- url = https://gitee.com/renjianbo0118/ruoyi.git
diff --git a/docs/后台管理功能模块规划.md b/docs/后台管理功能模块规划.md
new file mode 100644
index 0000000..e289449
--- /dev/null
+++ b/docs/后台管理功能模块规划.md
@@ -0,0 +1,257 @@
+# 后台管理功能模块规划
+
+> 基于 PRD 文档 (v1.0, 2026-05-12) 第 3.3 节「后台管理系统功能需求」
+> 对照现有 RuoYi 框架 + 已开发页面,梳理差距并规划改进
+
+---
+
+## 一、现状总览
+
+### 已有模块(RuoYi 自带 + 项目扩展)
+
+| 模块 | 路由 | 状态 | 说明 |
+|------|------|------|------|
+| 用户管理 | `/system/user` | 已有 | 含患者(C)和陪护(B),但无类型筛选增强 |
+| 角色管理 | `/system/role` | 已有 | RuoYi 标准 |
+| 菜单管理 | `/system/menu` | 已有 | RuoYi 标准 |
+| 部门管理 | `/system/dept` | 已有 | RuoYi 标准 |
+| 岗位管理 | `/system/post` | 已有 | RuoYi 标准 |
+| 字典管理 | `/system/dict` | 已有 | RuoYi 标准 |
+| 参数配置 | `/system/config` | 已有 | 含 price / priceType 配置 |
+| 通知公告 | `/system/notice` | 已有 | RuoYi 标准 |
+| 医院管理 | `/system/hospital` | **需增强** | 字段与 PRD 不一致 |
+| 订单管理 | `/system/order` | **需增强** | 缺状态筛选、退款审核、结算 |
+| 认证管理 | `/system/renzheng` | **需增强** | 陪护实名认证审核 |
+| 仪表盘 | `/index` | **需增强** | 缺业务统计图表 |
+| 在线用户 | `/monitor/online` | 已有 | RuoYi 标准 |
+| 操作日志 | `/monitor/operlog` | 已有 | RuoYi 标准 |
+| 登录日志 | `/monitor/logininfor` | 已有 | RuoYi 标准 |
+| 定时任务 | `/monitor/job` | 已有 | RuoYi 标准 |
+| 服务监控 | `/monitor/server` | 已有 | RuoYi 标准 |
+| 缓存监控 | `/monitor/cache` | 已有 | RuoYi 标准 |
+| 代码生成 | `/tool/gen` | 已有 | RuoYi 标准 |
+
+### 后端已有 Controller(业务相关)
+
+| Controller | 路由前缀 | 说明 |
+|-----------|---------|------|
+| `RlzOrderController` | `/system/order` | 订单 CRUD + 微信支付 + 退款 + 取消 |
+| `OrderViewController` | `/system/view` | 订单视图(join 查询),含接单/拒单/开始/完成 |
+| `SysHospitalController` | `/system/hospital` | 医院 CRUD |
+| `SysUserRenzhengController` | `/system/renzheng` | 认证审核 CRUD |
+| `JiaoyiDetailController` | `/system/detail` | 交易明细 CRUD |
+| `SysUserController` | `/system/user` | 用户 CRUD(含患者/陪护) |
+
+---
+
+## 二、差距分析:PRD 要求 vs 现有实现
+
+| PRD 模块 (3.3.x) | 完成度 | 差距 |
+|-----------------|--------|------|
+| 3.3.1 用户管理 | 60% | 缺患者/陪护类型筛选、患者订单统计、陪护服务统计、陪护等级 |
+| 3.3.2 订单管理 | 40% | 缺状态筛选、服务类型筛选、订单搜索、退款审核流程、结算流程、订单统计 |
+| 3.3.3 医院管理 | 50% | 字段不匹配(现有字段偏旧,PRD 要求医院等级/简介/图片) |
+| 3.3.4 服务类型管理 | **0%** | 完全缺失,无服务类型和价格管理页面 |
+| 3.3.5 财务管理 | 20% | 仅交易明细 CRUD,缺收入统计、退款审核、结算管理 |
+| 3.3.6 数据统计 | 30% | 仅 RuoYi 通用仪表盘,缺业务数据统计 |
+| 3.3.7 系统配置 | 90% | 基本完整 |
+| 3.3.8 权限管理 | 90% | 基本完整(角色+菜单+用户) |
+
+---
+
+## 三、改进方案:模块划分与实施计划
+
+### 第一优先级(核心业务闭环)
+
+#### A. 订单管理增强 (`/system/order`)
+
+**目标**:让管理员能完整管理订单生命周期
+
+| 功能 | 具体改动 | 前端 | 后端 |
+|------|---------|------|------|
+| 状态筛选增强 | 添加状态下拉选择(全部/待接单/待付款/待服务/服务中/已完成/已取消/退款中/已退款/已结算) | 改 `order/index.vue` 搜索表单 | `RlzOrderController.list()` 已支持 status 参数 |
+| 服务类型筛选 | 添加订单类别(yuliu9)和类型(yuliu10)下拉筛选 | 同上 | 已支持 |
+| 订单搜索 | 支持按订单号、患者姓名、患者手机号搜索 | 添加搜索输入框 | 需增强 `list()` 支持多字段模糊搜索 |
+| 订单详情增强 | 显示关联的患者姓名/电话、陪护姓名/电话、医院名称(JOIN 查询) | 改用 `OrderViewController` 数据源 | `OrderViewController` 已有 join 视图 |
+| 状态手动变更 | 管理员可手动修改订单状态(如强制取消、标记完成) | 添加状态变更按钮+确认弹窗 | `RlzOrderController.update()` 需增加状态校验 |
+| 退款审核 | 退款申请列表 + 审核通过/驳回操作 + 驳回原因填写 | 新增退款审核区域或子页面 | 已有 `refundOrder` 接口,需增加审核逻辑 |
+| 订单结算 | 手动/批量结算已完成订单 | 添加结算按钮 | 新增 `settlementOrder` 接口 |
+
+**数据来源切换**:当前 order 页面查询 `rlz_order` 原始表,字段名晦涩(yuliu1/yuliu9/yuliu10 等)。建议改用 `order_view` 视图,已 JOIN 了用户姓名、手机号、医院名称。
+
+#### B. 服务类型与价格管理(新增 `/system/serviceType`)
+
+**目标**:让管理员能配置服务类型和价格,取代硬编码
+
+| 功能 | 说明 |
+|------|------|
+| 服务类型列表 | 展示 4 种服务类型(全程陪诊/诊前约号/取送结果/代办问诊),含名称、价格、描述、状态 |
+| 新增/编辑服务类型 | 配置服务名称、价格、服务内容描述、类别(陪诊/陪护) |
+| 价格历史 | 记录价格变更历史,支持回溯 |
+| 状态管理 | 启用/停用某项服务类型 |
+
+**数据表设计**:
+```sql
+-- 服务类型表
+CREATE TABLE rlz_service_type (
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ name VARCHAR(50) NOT NULL COMMENT '服务名称',
+ category VARCHAR(10) COMMENT '类别: 1=陪护 2=陪诊',
+ type_code VARCHAR(10) COMMENT '类型编码: 1=全程陪诊 2=诊前约号 3=取送结果 4=代办问诊',
+ price DECIMAL(10,2) NOT NULL COMMENT '价格',
+ description TEXT COMMENT '服务内容描述',
+ status CHAR(1) DEFAULT '0' COMMENT '0=启用 1=停用',
+ sort_order INT DEFAULT 0 COMMENT '排序',
+ create_time DATETIME,
+ update_time DATETIME
+);
+
+-- 价格变更历史表
+CREATE TABLE rlz_price_history (
+ id BIGINT PRIMARY KEY AUTO_INCREMENT,
+ service_type_id BIGINT COMMENT '服务类型ID',
+ old_price DECIMAL(10,2) COMMENT '旧价格',
+ new_price DECIMAL(10,2) COMMENT '新价格',
+ change_reason VARCHAR(200) COMMENT '变更原因',
+ operator_id BIGINT COMMENT '操作人',
+ create_time DATETIME
+);
+```
+
+---
+
+### 第二优先级(运营管理增强)
+
+#### C. 用户管理增强
+
+| 功能 | 具体改动 | 说明 |
+|------|---------|------|
+| 用户类型筛选 | 添加下拉:全部/系统用户/患者(C)/陪护(B) | `SysUserController.list()` 已支持 userType 参数 |
+| 患者订单统计 | 用户详情页展示该患者的订单数量、总金额 | 前端增强 `user/profile` 或新增 tab |
+| 陪护服务统计 | 用户详情页展示该陪护的接单数量、完成率、收入 | 同上 |
+| 陪护等级 | 字段 `userLevel` 设置等级(初级/中级/高级) | 需 sys_user 增加字段或在字典中维护 |
+
+#### D. 医院管理增强
+
+| 功能 | 具体改动 | 说明 |
+|------|---------|------|
+| 字段对齐 PRD | 增加:医院等级(hospitalLevel)、医院简介(hospitalDesc)、医院图片 | 前端表单 + 后端 domain 同步 |
+| 图片上传 | 支持医院图片上传(复用 OSS 组件) | 使用已有 `/system/oss/uploadMinio` |
+| 冗余字段清理 | 隐藏/删除 hospitalcode(编码)、hospitalshortname(简称)、省市区编码等非核心字段 | 前端搜索/列表精简 |
+
+#### E. 认证管理增强
+
+| 功能 | 具体改动 | 说明 |
+|------|---------|------|
+| 审核操作优化 | 通过/驳回按钮 + 弹窗填写驳回原因 | 现有 `renzheng/index.vue` 仅有基础 CRUD |
+| 认证图片查看 | 点击查看身份证等认证图片 | 前端增加图片预览组件 |
+| 认证状态颜色 | 待审核(黄色)/已通过(绿色)/已驳回(红色) | 表格列使用 el-tag |
+
+---
+
+### 第三优先级(数据与财务)
+
+#### F. 财务管理(新增菜单组)
+
+| 子模块 | 路由 | 说明 |
+|--------|------|------|
+| 交易明细 | `/finance/detail` | 已有 `JiaoyiDetailController`,迁移到财务菜单下 |
+| 收入统计 | `/finance/income` | 按日/月/年统计平台收入,图表展示 |
+| 退款管理 | `/finance/refund` | 退款申请审核列表(status=5,6,7 的订单) |
+| 结算管理 | `/finance/settlement` | 陪护结算列表(status=8 的订单),支持批量结算 |
+
+#### G. 数据统计仪表盘增强
+
+| 统计项 | 图表类型 | 数据来源 |
+|--------|---------|---------|
+| 订单量趋势 | 折线图 | `rlz_order` 按日聚合 |
+| 订单状态分布 | 饼图 | `rlz_order` 按 status 分组 |
+| 服务类型占比 | 饼图 | `rlz_order` 按 yuliu10 分组 |
+| 医院服务量排名 | 柱状图 | `rlz_order` JOIN `sys_hospital` |
+| 收入趋势 | 折线图 | `rlz_order` 按日 sum(yuguMoney) |
+| 陪护服务排名 | 柱状图 | `rlz_order` 按 b_id 分组 count |
+
+---
+
+## 四、菜单结构调整建议
+
+```
+陪诊管理系统
+├── 首页 (仪表盘增强)
+├── 业务管理 (新菜单组)
+│ ├── 订单管理 /system/order [增强]
+│ ├── 医院管理 /system/hospital [增强]
+│ ├── 服务类型 /system/serviceType [新增]
+│ └── 认证审核 /system/renzheng [增强]
+├── 用户管理 (增强筛选)
+│ ├── 用户列表 /system/user
+│ ├── 角色管理 /system/role
+│ └── 部门管理 /system/dept
+├── 财务管理 (新菜单组)
+│ ├── 交易明细 /finance/detail [迁移]
+│ ├── 收入统计 /finance/income [新增]
+│ ├── 退款管理 /finance/refund [新增]
+│ └── 结算管理 /finance/settlement [新增]
+├── 系统管理
+│ ├── 菜单管理 /system/menu
+│ ├── 岗位管理 /system/post
+│ ├── 字典管理 /system/dict
+│ ├── 参数配置 /system/config
+│ └── 通知公告 /system/notice
+├── 系统监控
+│ ├── 在线用户 /monitor/online
+│ ├── 操作日志 /monitor/operlog
+│ ├── 登录日志 /monitor/logininfor
+│ ├── 定时任务 /monitor/job
+│ ├── 服务监控 /monitor/server
+│ └── 缓存监控 /monitor/cache
+└── 开发工具
+ ├── 代码生成 /tool/gen
+ ├── Swagger文档 /tool/swagger
+ └── 表单构建 /tool/build
+```
+
+---
+
+## 五、实施估算
+
+| 优先级 | 模块 | 工作量 | 说明 |
+|--------|------|--------|------|
+| P0 | 订单管理增强 | 2-3 天 | 状态筛选+搜索+详情+退款审核,前端为主 |
+| P0 | 服务类型管理 | 1-2 天 | 新建表+前后端 CRUD+字典联动 |
+| P1 | 医院管理增强 | 0.5-1 天 | 字段调整+图片上传 |
+| P1 | 用户管理增强 | 0.5-1 天 | 类型筛选+统计展示 |
+| P1 | 认证管理增强 | 0.5 天 | 审核操作+图片预览 |
+| P2 | 财务管理 | 2-3 天 | 4 个子模块,含统计图表 |
+| P2 | 仪表盘增强 | 1-2 天 | ECharts 图表开发 |
+| P2 | 菜单结构调整 | 0.5 天 | 数据库菜单表 UPDATE |
+
+---
+
+## 六、服务类型数据初始化
+
+当前 4 种服务类型通过 `yuliu9`(大类) 和 `yuliu10`(类型) 编码存储在订单中,建议纳入字典管理:
+
+```sql
+-- 字典类型
+INSERT INTO sys_dict_type VALUES (NULL, 'order_category', '订单大类', '0', 'admin', NOW(), '', NULL);
+INSERT INTO sys_dict_type VALUES (NULL, 'order_service_type', '服务类型', '0', 'admin', NOW(), '', NULL);
+
+-- 字典数据 - 订单大类
+INSERT INTO sys_dict_data VALUES (NULL, 1, '陪护', '1', 'order_category', '', '', 'N', '0', 'admin', NOW(), '', NULL);
+INSERT INTO sys_dict_data VALUES (NULL, 2, '陪诊', '2', 'order_category', '', '', 'N', '0', 'admin', NOW(), '', NULL);
+
+-- 字典数据 - 服务类型
+INSERT INTO sys_dict_data VALUES (NULL, 3, '全程陪诊', '1', 'order_service_type', '', '200.00', 'N', '0', 'admin', NOW(), '', NULL);
+INSERT INTO sys_dict_data VALUES (NULL, 4, '诊前约号', '2', 'order_service_type', '', '20.00', 'N', '0', 'admin', NOW(), '', NULL);
+INSERT INTO sys_dict_data VALUES (NULL, 5, '取送结果', '3', 'order_service_type', '', '50.00', 'N', '0', 'admin', NOW(), '', NULL);
+INSERT INTO sys_dict_data VALUES (NULL, 6, '代办问诊', '4', 'order_service_type', '', '100.00', 'N', '0', 'admin', NOW(), '', NULL);
+```
+
+---
+
+> **相关文档**:
+> - PRD 文档:`D:\androidPj\rlz\项目功能的prd文档.md`
+> - 需求文档:`D:\androidPj\rlz\陪诊项目需求文档.txt`
+> - 项目技术文档:`D:\androidPj\rlz\项目文档0511.md`
+> - 改进记录:`D:\androidPj\rlz\docs\改进完成记录.md`
diff --git a/docs/改进完成记录.md b/docs/改进完成记录.md
new file mode 100644
index 0000000..eb25f9a
--- /dev/null
+++ b/docs/改进完成记录.md
@@ -0,0 +1,96 @@
+# 开发环境改进完成记录
+
+> 日期:2026-05-14
+
+---
+
+## 已完成的改进
+
+### 1. Git 分支策略
+
+- 创建 `dev` 分支并推送到 Gitea (`origin/dev`)
+- `main` 保持稳定,日常开发在 `dev` 上进行
+
+### 2. 数据库环境隔离
+
+- 在腾讯云 CynosDB 创建 `rlz_dev` 开发库(28 张表,结构与生产 `rlz` 一致)
+- 开发环境连 `rlz_dev`,生产环境连 `rlz`,数据互不污染
+
+### 3. 后端配置分离
+
+**application-dev.yml** (本地开发):
+- 端口 8039,关闭 SSL
+- 数据库 → `rlz_dev` (云 MySQL)
+- Redis → localhost:6379 (需本地启动 Redis)
+- 密码通过 `${MYSQL_PASSWORD:"!Rjb12191"}` 注入,有默认值
+
+**application-docker.yml** (生产):
+- 所有配置通过环境变量注入,保持现有方式
+
+### 4. Drone CI 自动部署
+
+创建 `.drone.yml`:`git push main` → Drone 自动 `mvn package` → `docker build` → `docker compose up -d`
+
+> 需要在 Gitea Drone 面板激活 `admin/rlz` 仓库后生效
+
+### 5. Android API 地址自动切换
+
+- `app/build.gradle` 添加 `buildConfigField "API_BASE_URL"`
+ - Debug → `http://192.168.1.100:8039`(需改为本机IP)
+ - Release → `http://101.43.95.130:8039`
+- `MyApi.java` 和 `HttpConstants.java` 改用 `BuildConfig.API_BASE_URL`
+
+### 6. 微信小程序环境配置
+
+- 新建 `coupon/utils/config.js` 集中管理 API 地址
+- `coupon/app.js` 引用 `config.baseUrl`,同时修复 `domain`/`domaintwo` 未赋值问题
+
+### 7. 后端代码本地化
+
+- 移除失效的 Gitee 子模块引用
+- 从服务器复制后端代码 → `rlz/` 目录(作为普通目录纳入 Git)
+- 删除 `.gitmodules`
+
+---
+
+## 后续需要手动完成的
+
+| 事项 | 操作 |
+|------|------|
+| 修改 Android debug IP | `peizhen/app/build.gradle` → 将 `192.168.1.100` 改为本机实际 IP |
+| 修改小程序 debug URL | `coupon/utils/config.js` → 取消注释开发环境 URL |
+| 激活 Drone CI | Gitea → Drone 面板 → 激活 `admin/rlz` 仓库 |
+| 本地启动 Redis | `docker run -d --name redis-dev -p 6379:6379 redis:7-alpine` |
+| 提交代码到 Gitea | `git add -A && git commit && git push origin dev` |
+
+---
+
+## 环境对照表
+
+| 项目 | 开发环境 | 生产环境 |
+|------|----------|----------|
+| 数据库 | `rlz_dev` (云MySQL) | `rlz` (云MySQL) |
+| 后端端口 | 8039 (本地) | 8039 (Docker) |
+| 后端 profile | `dev` | `docker` |
+| Android API | Debug: 本机IP | Release: 101.43.95.130 |
+| 小程序 API | 可切换 config.js | 101.43.95.130 |
+| Git 分支 | `dev` | `main` |
+| 部署方式 | 手动 `mvn spring-boot:run` | Drone CI 自动部署 |
+
+---
+
+## 文件变更清单
+
+| 文件 | 变更类型 |
+|------|----------|
+| `.drone.yml` | 新增 |
+| `.gitmodules` | 删除 |
+| `rlz/` (整个后端) | 新增(从子模块改为普通目录) |
+| `rlz/.../application-dev.yml` | 修改(指向 rlz_dev) |
+| `peizhen/app/build.gradle` | 修改(添加 BuildConfig) |
+| `peizhen/.../MyApi.java` | 修改(使用 BuildConfig) |
+| `peizhen/.../HttpConstants.java` | 修改(使用 BuildConfig) |
+| `coupon/utils/config.js` | 新增 |
+| `coupon/app.js` | 修改(引用 config,修复 domain) |
+| `docs/开发环境方案.md` | 新增 |
+| `docs/改进完成记录.md` | 新增 |
diff --git a/rlz b/rlz
deleted file mode 160000
index 28e0b6f..0000000
--- a/rlz
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 28e0b6fc9fea01bfaf44bd76d79370dc8fc5167b
diff --git a/rlz-ui/src/api/system/serviceType.js b/rlz-ui/src/api/system/serviceType.js
new file mode 100644
index 0000000..edd6307
--- /dev/null
+++ b/rlz-ui/src/api/system/serviceType.js
@@ -0,0 +1,61 @@
+import request from '@/utils/request'
+
+// 查询服务类型列表
+export function listServiceType(query) {
+ return request({
+ url: '/system/serviceType/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 查询服务类型详细
+export function getServiceType(id) {
+ return request({
+ url: '/system/serviceType/' + id,
+ method: 'get'
+ })
+}
+
+// 新增服务类型
+export function addServiceType(data) {
+ return request({
+ url: '/system/serviceType',
+ method: 'post',
+ data: data
+ })
+}
+
+// 修改服务类型
+export function updateServiceType(data) {
+ return request({
+ url: '/system/serviceType',
+ method: 'put',
+ data: data
+ })
+}
+
+// 删除服务类型
+export function delServiceType(id) {
+ return request({
+ url: '/system/serviceType/' + id,
+ method: 'delete'
+ })
+}
+
+// 更新价格(记录变更历史)
+export function updatePrice(id, data) {
+ return request({
+ url: '/system/serviceType/price/' + id,
+ method: 'put',
+ data: data
+ })
+}
+
+// 查询价格变更历史
+export function getPriceHistory(serviceTypeId) {
+ return request({
+ url: '/system/serviceType/priceHistory/' + serviceTypeId,
+ method: 'get'
+ })
+}
diff --git a/rlz-ui/src/views/system/serviceType/index.vue b/rlz-ui/src/views/system/serviceType/index.vue
new file mode 100644
index 0000000..a8ac809
--- /dev/null
+++ b/rlz-ui/src/views/system/serviceType/index.vue
@@ -0,0 +1,413 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+
+
+
+
+ 新增
+
+
+ 修改
+
+
+ 删除
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.category == '2' ? '陪诊' : scope.row.category == '1' ? '陪护' : '-' }}
+
+
+
+
+
+ {{ serviceTypeMap[scope.row.typeCode] || scope.row.typeCode }}
+
+
+
+
+ {{ scope.row.price }}
+
+
+
+
+
+
+ {{ scope.row.status == '0' ? '启用' : '停用' }}
+
+
+
+
+
+ 修改
+ 调价
+ 价格历史
+ 删除
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 启用
+ 停用
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ currentServiceType.name }}
+
+
+ {{ currentServiceType.price }} 元
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ scope.row.newPrice }}
+
+
+
+
+
+
+
+ 暂无价格变更记录
+
+
+
+
+
+
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/controller/RlzServiceTypeController.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/controller/RlzServiceTypeController.java
new file mode 100644
index 0000000..4dce46c
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/controller/RlzServiceTypeController.java
@@ -0,0 +1,133 @@
+package com.ruoyi.system.controller;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.RlzServiceType;
+import com.ruoyi.system.domain.RlzPriceHistory;
+import com.ruoyi.system.service.IRlzServiceTypeService;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 服务类型Controller
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+@RestController
+@RequestMapping("/system/serviceType")
+public class RlzServiceTypeController extends BaseController
+{
+ @Autowired
+ private IRlzServiceTypeService rlzServiceTypeService;
+
+ /**
+ * 查询服务类型列表
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(RlzServiceType rlzServiceType)
+ {
+ startPage();
+ List list = rlzServiceTypeService.selectRlzServiceTypeList(rlzServiceType);
+ return getDataTable(list);
+ }
+
+ /**
+ * 导出服务类型列表
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:export')")
+ @Log(title = "服务类型", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, RlzServiceType rlzServiceType)
+ {
+ List list = rlzServiceTypeService.selectRlzServiceTypeList(rlzServiceType);
+ ExcelUtil util = new ExcelUtil(RlzServiceType.class);
+ util.exportExcel(response, list, "服务类型数据");
+ }
+
+ /**
+ * 获取服务类型详细信息
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id)
+ {
+ return AjaxResult.success(rlzServiceTypeService.selectRlzServiceTypeById(id));
+ }
+
+ /**
+ * 新增服务类型
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:add')")
+ @Log(title = "服务类型", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody RlzServiceType rlzServiceType)
+ {
+ return toAjax(rlzServiceTypeService.insertRlzServiceType(rlzServiceType));
+ }
+
+ /**
+ * 修改服务类型
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:edit')")
+ @Log(title = "服务类型", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody RlzServiceType rlzServiceType)
+ {
+ return toAjax(rlzServiceTypeService.updateRlzServiceType(rlzServiceType));
+ }
+
+ /**
+ * 删除服务类型
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:remove')")
+ @Log(title = "服务类型", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids)
+ {
+ return toAjax(rlzServiceTypeService.deleteRlzServiceTypeByIds(ids));
+ }
+
+ /**
+ * 更新服务类型价格(自动记录变更历史)
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:edit')")
+ @Log(title = "服务类型价格", businessType = BusinessType.UPDATE)
+ @PutMapping("/price/{id}")
+ public AjaxResult updatePrice(@PathVariable Long id, @RequestBody Map params)
+ {
+ BigDecimal newPrice = new BigDecimal(params.get("price").toString());
+ String reason = params.get("reason") != null ? params.get("reason").toString() : "";
+ Long operatorId = this.getLoginUser().getUserId();
+ String operatorName = this.getLoginUser().getUsername();
+ return toAjax(rlzServiceTypeService.updatePrice(id, newPrice, reason, operatorId, operatorName));
+ }
+
+ /**
+ * 查询价格变更历史
+ */
+ @PreAuthorize("@ss.hasPermi('system:serviceType:query')")
+ @GetMapping("/priceHistory/{serviceTypeId}")
+ public AjaxResult priceHistory(@PathVariable Long serviceTypeId)
+ {
+ List list = rlzServiceTypeService.selectPriceHistoryByServiceTypeId(serviceTypeId);
+ return AjaxResult.success(list);
+ }
+}
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/domain/RlzPriceHistory.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/domain/RlzPriceHistory.java
new file mode 100644
index 0000000..84afa43
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/domain/RlzPriceHistory.java
@@ -0,0 +1,127 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+
+/**
+ * 价格变更历史对象 rlz_price_history
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+public class RlzPriceHistory
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 主键 */
+ private Long id;
+
+ /** 服务类型ID */
+ private Long serviceTypeId;
+
+ /** 旧价格 */
+ @Excel(name = "旧价格")
+ private BigDecimal oldPrice;
+
+ /** 新价格 */
+ @Excel(name = "新价格")
+ private BigDecimal newPrice;
+
+ /** 变更原因 */
+ @Excel(name = "变更原因")
+ private String changeReason;
+
+ /** 操作人ID */
+ private Long operatorId;
+
+ /** 操作人名称 */
+ @Excel(name = "操作人名称")
+ private String operatorName;
+
+ /** 创建时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "创建时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setServiceTypeId(Long serviceTypeId)
+ {
+ this.serviceTypeId = serviceTypeId;
+ }
+
+ public Long getServiceTypeId()
+ {
+ return serviceTypeId;
+ }
+
+ public void setOldPrice(BigDecimal oldPrice)
+ {
+ this.oldPrice = oldPrice;
+ }
+
+ public BigDecimal getOldPrice()
+ {
+ return oldPrice;
+ }
+
+ public void setNewPrice(BigDecimal newPrice)
+ {
+ this.newPrice = newPrice;
+ }
+
+ public BigDecimal getNewPrice()
+ {
+ return newPrice;
+ }
+
+ public void setChangeReason(String changeReason)
+ {
+ this.changeReason = changeReason;
+ }
+
+ public String getChangeReason()
+ {
+ return changeReason;
+ }
+
+ public void setOperatorId(Long operatorId)
+ {
+ this.operatorId = operatorId;
+ }
+
+ public Long getOperatorId()
+ {
+ return operatorId;
+ }
+
+ public void setOperatorName(String operatorName)
+ {
+ this.operatorName = operatorName;
+ }
+
+ public String getOperatorName()
+ {
+ return operatorName;
+ }
+
+ public void setCreateTime(Date createTime)
+ {
+ this.createTime = createTime;
+ }
+
+ public Date getCreateTime()
+ {
+ return createTime;
+ }
+}
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/domain/RlzServiceType.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/domain/RlzServiceType.java
new file mode 100644
index 0000000..20cb6c8
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/domain/RlzServiceType.java
@@ -0,0 +1,147 @@
+package com.ruoyi.system.domain;
+
+import java.math.BigDecimal;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 服务类型对象 rlz_service_type
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+public class RlzServiceType extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 主键 */
+ private Long id;
+
+ /** 服务名称 */
+ @Excel(name = "服务名称")
+ private String name;
+
+ /** 类别: 1=陪护 2=陪诊 */
+ @Excel(name = "类别", readConverterExp = "1=陪护,2=陪诊")
+ private String category;
+
+ /** 类型编码: 1=全程陪诊 2=诊前约号 3=取送结果 4=代办问诊 */
+ @Excel(name = "类型编码")
+ private String typeCode;
+
+ /** 价格 */
+ @Excel(name = "价格")
+ private BigDecimal price;
+
+ /** 服务内容描述 */
+ @Excel(name = "服务内容描述")
+ private String description;
+
+ /** 状态: 0=启用 1=停用 */
+ @Excel(name = "状态", readConverterExp = "0=启用,1=停用")
+ private String status;
+
+ /** 排序 */
+ private Integer sortOrder;
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setCategory(String category)
+ {
+ this.category = category;
+ }
+
+ public String getCategory()
+ {
+ return category;
+ }
+
+ public void setTypeCode(String typeCode)
+ {
+ this.typeCode = typeCode;
+ }
+
+ public String getTypeCode()
+ {
+ return typeCode;
+ }
+
+ public void setPrice(BigDecimal price)
+ {
+ this.price = price;
+ }
+
+ public BigDecimal getPrice()
+ {
+ return price;
+ }
+
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setSortOrder(Integer sortOrder)
+ {
+ this.sortOrder = sortOrder;
+ }
+
+ public Integer getSortOrder()
+ {
+ return sortOrder;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("id", getId())
+ .append("name", getName())
+ .append("category", getCategory())
+ .append("typeCode", getTypeCode())
+ .append("price", getPrice())
+ .append("description", getDescription())
+ .append("status", getStatus())
+ .append("sortOrder", getSortOrder())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RlzPriceHistoryMapper.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RlzPriceHistoryMapper.java
new file mode 100644
index 0000000..39fb7d0
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RlzPriceHistoryMapper.java
@@ -0,0 +1,17 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.RlzPriceHistory;
+
+/**
+ * 价格变更历史Mapper接口
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+public interface RlzPriceHistoryMapper
+{
+ public List selectRlzPriceHistoryList(RlzPriceHistory rlzPriceHistory);
+
+ public int insertRlzPriceHistory(RlzPriceHistory rlzPriceHistory);
+}
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RlzServiceTypeMapper.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RlzServiceTypeMapper.java
new file mode 100644
index 0000000..bb1026e
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/mapper/RlzServiceTypeMapper.java
@@ -0,0 +1,25 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.RlzServiceType;
+
+/**
+ * 服务类型Mapper接口
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+public interface RlzServiceTypeMapper
+{
+ public RlzServiceType selectRlzServiceTypeById(Long id);
+
+ public List selectRlzServiceTypeList(RlzServiceType rlzServiceType);
+
+ public int insertRlzServiceType(RlzServiceType rlzServiceType);
+
+ public int updateRlzServiceType(RlzServiceType rlzServiceType);
+
+ public int deleteRlzServiceTypeById(Long id);
+
+ public int deleteRlzServiceTypeByIds(Long[] ids);
+}
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/service/IRlzServiceTypeService.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/service/IRlzServiceTypeService.java
new file mode 100644
index 0000000..2bdc2d9
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/service/IRlzServiceTypeService.java
@@ -0,0 +1,37 @@
+package com.ruoyi.system.service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import com.ruoyi.system.domain.RlzServiceType;
+import com.ruoyi.system.domain.RlzPriceHistory;
+
+/**
+ * 服务类型Service接口
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+public interface IRlzServiceTypeService
+{
+ public RlzServiceType selectRlzServiceTypeById(Long id);
+
+ public List selectRlzServiceTypeList(RlzServiceType rlzServiceType);
+
+ public int insertRlzServiceType(RlzServiceType rlzServiceType);
+
+ public int updateRlzServiceType(RlzServiceType rlzServiceType);
+
+ public int deleteRlzServiceTypeByIds(Long[] ids);
+
+ public int deleteRlzServiceTypeById(Long id);
+
+ /**
+ * 更新服务类型价格(自动记录价格变更历史)
+ */
+ public int updatePrice(Long id, BigDecimal newPrice, String reason, Long operatorId, String operatorName);
+
+ /**
+ * 查询指定服务类型的价格变更历史
+ */
+ public List selectPriceHistoryByServiceTypeId(Long serviceTypeId);
+}
diff --git a/rlz/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RlzServiceTypeServiceImpl.java b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RlzServiceTypeServiceImpl.java
new file mode 100644
index 0000000..f989a48
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RlzServiceTypeServiceImpl.java
@@ -0,0 +1,107 @@
+package com.ruoyi.system.service.impl;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import com.ruoyi.common.utils.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.system.mapper.RlzServiceTypeMapper;
+import com.ruoyi.system.mapper.RlzPriceHistoryMapper;
+import com.ruoyi.system.domain.RlzServiceType;
+import com.ruoyi.system.domain.RlzPriceHistory;
+import com.ruoyi.system.service.IRlzServiceTypeService;
+
+/**
+ * 服务类型Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2026-05-14
+ */
+@Service
+public class RlzServiceTypeServiceImpl implements IRlzServiceTypeService
+{
+ @Autowired
+ private RlzServiceTypeMapper rlzServiceTypeMapper;
+
+ @Autowired
+ private RlzPriceHistoryMapper rlzPriceHistoryMapper;
+
+ @Override
+ public RlzServiceType selectRlzServiceTypeById(Long id)
+ {
+ return rlzServiceTypeMapper.selectRlzServiceTypeById(id);
+ }
+
+ @Override
+ public List selectRlzServiceTypeList(RlzServiceType rlzServiceType)
+ {
+ return rlzServiceTypeMapper.selectRlzServiceTypeList(rlzServiceType);
+ }
+
+ @Override
+ public int insertRlzServiceType(RlzServiceType rlzServiceType)
+ {
+ rlzServiceType.setCreateTime(DateUtils.getNowDate());
+ return rlzServiceTypeMapper.insertRlzServiceType(rlzServiceType);
+ }
+
+ @Override
+ public int updateRlzServiceType(RlzServiceType rlzServiceType)
+ {
+ rlzServiceType.setUpdateTime(DateUtils.getNowDate());
+ return rlzServiceTypeMapper.updateRlzServiceType(rlzServiceType);
+ }
+
+ @Override
+ public int deleteRlzServiceTypeByIds(Long[] ids)
+ {
+ return rlzServiceTypeMapper.deleteRlzServiceTypeByIds(ids);
+ }
+
+ @Override
+ public int deleteRlzServiceTypeById(Long id)
+ {
+ return rlzServiceTypeMapper.deleteRlzServiceTypeById(id);
+ }
+
+ @Override
+ @Transactional
+ public int updatePrice(Long id, BigDecimal newPrice, String reason, Long operatorId, String operatorName)
+ {
+ RlzServiceType serviceType = rlzServiceTypeMapper.selectRlzServiceTypeById(id);
+ if (serviceType == null) {
+ return 0;
+ }
+ BigDecimal oldPrice = serviceType.getPrice();
+
+ // 更新价格
+ RlzServiceType update = new RlzServiceType();
+ update.setId(id);
+ update.setPrice(newPrice);
+ update.setUpdateTime(DateUtils.getNowDate());
+ int rows = rlzServiceTypeMapper.updateRlzServiceType(update);
+
+ // 记录价格变更历史
+ RlzPriceHistory history = new RlzPriceHistory();
+ history.setServiceTypeId(id);
+ history.setOldPrice(oldPrice);
+ history.setNewPrice(newPrice);
+ history.setChangeReason(reason);
+ history.setOperatorId(operatorId);
+ history.setOperatorName(operatorName);
+ history.setCreateTime(new Date());
+ rlzPriceHistoryMapper.insertRlzPriceHistory(history);
+
+ return rows;
+ }
+
+ @Override
+ public List selectPriceHistoryByServiceTypeId(Long serviceTypeId)
+ {
+ RlzPriceHistory query = new RlzPriceHistory();
+ query.setServiceTypeId(serviceTypeId);
+ return rlzPriceHistoryMapper.selectRlzPriceHistoryList(query);
+ }
+}
diff --git a/rlz/ruoyi-system/src/main/resources/mapper/system/RlzPriceHistoryMapper.xml b/rlz/ruoyi-system/src/main/resources/mapper/system/RlzPriceHistoryMapper.xml
new file mode 100644
index 0000000..c28df7d
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/resources/mapper/system/RlzPriceHistoryMapper.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select id, service_type_id, old_price, new_price, change_reason,
+ operator_id, operator_name, create_time
+ from rlz_price_history
+
+
+
+
+
+ insert into rlz_price_history
+
+ service_type_id,
+ old_price,
+ new_price,
+ change_reason,
+ operator_id,
+ operator_name,
+ create_time,
+
+
+ #{serviceTypeId},
+ #{oldPrice},
+ #{newPrice},
+ #{changeReason},
+ #{operatorId},
+ #{operatorName},
+ #{createTime},
+
+
+
diff --git a/rlz/ruoyi-system/src/main/resources/mapper/system/RlzServiceTypeMapper.xml b/rlz/ruoyi-system/src/main/resources/mapper/system/RlzServiceTypeMapper.xml
new file mode 100644
index 0000000..327a882
--- /dev/null
+++ b/rlz/ruoyi-system/src/main/resources/mapper/system/RlzServiceTypeMapper.xml
@@ -0,0 +1,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select id, name, category, type_code, price, description, status, sort_order,
+ create_by, create_time, update_by, update_time, remark
+ from rlz_service_type
+
+
+
+
+
+
+
+ insert into rlz_service_type
+
+ name,
+ category,
+ type_code,
+ price,
+ description,
+ status,
+ sort_order,
+ create_by,
+ create_time,
+ remark,
+
+
+ #{name},
+ #{category},
+ #{typeCode},
+ #{price},
+ #{description},
+ #{status},
+ #{sortOrder},
+ #{createBy},
+ #{createTime},
+ #{remark},
+
+
+
+
+ update rlz_service_type
+
+ name = #{name},
+ category = #{category},
+ type_code = #{typeCode},
+ price = #{price},
+ description = #{description},
+ status = #{status},
+ sort_order = #{sortOrder},
+ update_by = #{updateBy},
+ update_time = #{updateTime},
+ remark = #{remark},
+
+ where id = #{id}
+
+
+
+ delete from rlz_service_type where id = #{id}
+
+
+
+ delete from rlz_service_type where id in
+
+ #{id}
+
+
+