diff --git a/openhis-ui-vue3/src/views/charge/outpatientregistration/components/reprintDialog.vue b/openhis-ui-vue3/src/views/charge/outpatientregistration/components/reprintDialog.vue index d4777d3a..0259123c 100644 --- a/openhis-ui-vue3/src/views/charge/outpatientregistration/components/reprintDialog.vue +++ b/openhis-ui-vue3/src/views/charge/outpatientregistration/components/reprintDialog.vue @@ -547,47 +547,21 @@ function formatDateTime(date) { return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; } -// 计算流水号:格式为 YYYYMMDD-XXX,其中 XXX 为后端按"科室+医生+当日"自增的 displayOrder -// 确保同一科室同一医生同一天内是 001、002、003... 递增 +// 计算流水号:直接使用挂号记录表的主键ID(encounterId) function calculateSerialNo(row) { if (!row) { return '-'; } - // 获取挂号日期(YYYYMMDD格式) - let dateStr = ''; - if (row.registerTime) { - const date = new Date(row.registerTime); - const year = date.getFullYear(); - const month = String(date.getMonth() + 1).padStart(2, '0'); - const day = String(date.getDate()).padStart(2, '0'); - dateStr = `${year}${month}${day}`; + // 直接使用主键ID作为流水号 + if (row.encounterId != null && row.encounterId !== undefined) { + return String(row.encounterId); + } else if (row.id != null && row.id !== undefined) { + // 兼容其他可能的ID字段名 + return String(row.id); } else { - // 如果没有挂号时间,使用当前日期 - const now = new Date(); - const year = now.getFullYear(); - const month = String(now.getMonth() + 1).padStart(2, '0'); - const day = String(now.getDate()).padStart(2, '0'); - dateStr = `${year}${month}${day}`; + return '-'; } - - // 获取序号部分(3位数字,001-999) - // 直接使用后端返回的 displayOrder,自增逻辑在后端按"科室+医生+当日"保证 - let serialNum = 1; - if (row.displayOrder != null && row.displayOrder !== undefined) { - const num = Number(row.displayOrder) || 0; - serialNum = num > 0 ? num : 1; - } else if (row.serialNo) { - // 兼容旧数据:如果有已有的 serialNo 字段 - const num = Number(row.serialNo) || 0; - serialNum = num > 0 ? num : 1; - } else { - // 兜底:没有任何序号信息时,给 1 - serialNum = 1; - } - - // 格式:YYYYMMDD-XXX(例如:20250113-001) - return `${dateStr}-${String(serialNum).padStart(3, '0')}`; } // 提交补打挂号 diff --git a/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue b/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue new file mode 100644 index 00000000..ebb9d1aa --- /dev/null +++ b/openhis-ui-vue3/src/views/triageandqueuemanage/cardiology/index.vue @@ -0,0 +1,378 @@ + + + + + + diff --git a/sql/query_encounter_id.sql b/sql/query_encounter_id.sql new file mode 100644 index 00000000..dd12db12 --- /dev/null +++ b/sql/query_encounter_id.sql @@ -0,0 +1,116 @@ +-- 查询挂号记录表主键的SQL语句 +-- 表名:adm_encounter +-- 主键字段:id (bigint,雪花算法生成) + +-- ======================================== +-- 1. 查询所有挂号记录的主键(简单查询) +-- ======================================== +SELECT id +FROM adm_encounter +WHERE delete_flag = '0' +ORDER BY id DESC; + +-- ======================================== +-- 2. 查询最近N条挂号记录的主键 +-- ======================================== +SELECT id +FROM adm_encounter +WHERE delete_flag = '0' +ORDER BY start_time DESC +LIMIT 10; + +-- ======================================== +-- 3. 查询指定日期范围内的挂号记录主键 +-- ======================================== +SELECT id +FROM adm_encounter +WHERE delete_flag = '0' + AND DATE(start_time) >= '2026-01-01' + AND DATE(start_time) <= '2026-01-31' +ORDER BY start_time DESC; + +-- ======================================== +-- 4. 查询指定科室的挂号记录主键 +-- ======================================== +SELECT id +FROM adm_encounter +WHERE delete_flag = '0' + AND organization_id = 123 -- 替换为实际的科室ID +ORDER BY start_time DESC; + +-- ======================================== +-- 5. 查询指定患者的挂号记录主键 +-- ======================================== +SELECT id +FROM adm_encounter +WHERE delete_flag = '0' + AND patient_id = 456 -- 替换为实际的患者ID +ORDER BY start_time DESC; + +-- ======================================== +-- 6. 查询主键及基本信息(常用) +-- ======================================== +SELECT + id AS 主键ID, + bus_no AS 就诊编码, + patient_id AS 患者ID, + organization_id AS 科室ID, + registrar_id AS 医生ID, + display_order AS 流水号序号, + start_time AS 挂号时间, + status_enum AS 状态 +FROM adm_encounter +WHERE delete_flag = '0' +ORDER BY start_time DESC +LIMIT 20; + +-- ======================================== +-- 7. 统计主键数量(按日期分组) +-- ======================================== +SELECT + DATE(start_time) AS 日期, + COUNT(id) AS 挂号记录数, + MIN(id) AS 最小主键ID, + MAX(id) AS 最大主键ID +FROM adm_encounter +WHERE delete_flag = '0' +GROUP BY DATE(start_time) +ORDER BY 日期 DESC +LIMIT 30; + +-- ======================================== +-- 8. 查询主键的最大值、最小值、总数 +-- ======================================== +SELECT + COUNT(*) AS 总记录数, + MIN(id) AS 最小主键ID, + MAX(id) AS 最大主键ID, + MAX(id) - MIN(id) AS 主键ID范围 +FROM adm_encounter +WHERE delete_flag = '0'; + +-- ======================================== +-- 9. 根据主键查询单条记录(精确查询) +-- ======================================== +SELECT * +FROM adm_encounter +WHERE id = 1996923066055286785 -- 替换为实际的主键ID + AND delete_flag = '0'; + +-- ======================================== +-- 10. 查询主键及关联的患者信息 +-- ======================================== +SELECT + e.id AS 挂号记录主键ID, + e.bus_no AS 就诊编码, + e.display_order AS 流水号序号, + e.start_time AS 挂号时间, + p.id AS 患者ID, + p.name AS 患者姓名, + p.bus_no AS 患者业务号 +FROM adm_encounter e +INNER JOIN adm_patient p ON e.patient_id = p.id AND p.delete_flag = '0' +WHERE e.delete_flag = '0' +ORDER BY e.start_time DESC +LIMIT 20; + diff --git a/sql/sequence_explanation.md b/sql/sequence_explanation.md new file mode 100644 index 00000000..a48cc017 --- /dev/null +++ b/sql/sequence_explanation.md @@ -0,0 +1,161 @@ +# PostgreSQL SEQUENCE(序列)详解 + +## 语句解析 + +```sql +DROP SEQUENCE IF EXISTS "public"."adm_encounter_id_seq"; +CREATE SEQUENCE "public"."adm_encounter_id_seq" +INCREMENT 1 +MINVALUE 1 +MAXVALUE 99999999 +START 200 +CACHE 1; +``` + +## 逐行解释 + +### 1. `DROP SEQUENCE IF EXISTS "public"."adm_encounter_id_seq";` +- **作用**:如果序列已存在,先删除它 +- **`IF EXISTS`**:如果序列不存在,不会报错,直接跳过 +- **`"public"."adm_encounter_id_seq"`**:序列的完整名称 + - `public`:模式(schema)名,默认模式 + - `adm_encounter_id_seq`:序列名称 + +### 2. `CREATE SEQUENCE "public"."adm_encounter_id_seq"` +- **作用**:创建一个新的序列 +- **序列名称**:`adm_encounter_id_seq`(用于 `adm_encounter` 表的主键自增) + +### 3. `INCREMENT 1` +- **作用**:每次递增的步长 +- **含义**:每次调用 `nextval()` 时,序列值增加 1 +- **示例**:如果当前值是 200,下次调用 `nextval()` 返回 201 + +### 4. `MINVALUE 1` +- **作用**:序列的最小值 +- **含义**:序列值不能小于 1 +- **注意**:如果序列达到最小值后继续递减,会报错(除非设置了 `CYCLE`) + +### 5. `MAXVALUE 99999999` +- **作用**:序列的最大值 +- **含义**:序列值不能超过 99999999(8位数) +- **注意**:如果序列达到最大值后继续递增,会报错(除非设置了 `CYCLE`) + +### 6. `START 200` +- **作用**:序列的起始值 +- **含义**:序列从 200 开始 +- **示例**:第一次调用 `nextval()` 返回 200,第二次返回 201,以此类推 + +### 7. `CACHE 1` +- **作用**:缓存大小 +- **含义**:每次从数据库获取序列值时,预分配 1 个值到内存 +- **说明**: + - `CACHE 1`:每次只缓存 1 个值(最安全,但性能较低) + - `CACHE 20`:每次缓存 20 个值(性能更好,但可能跳号) + - **注意**:如果数据库重启,缓存中未使用的序列值会丢失,导致跳号 + +## 使用示例 + +### 1. 在表定义中使用(自动自增) +```sql +CREATE TABLE "adm_encounter" ( + "id" int8 NOT NULL DEFAULT nextval('adm_encounter_id_seq'::regclass), + ... +); +``` + +### 2. 手动获取下一个值 +```sql +-- 获取下一个序列值 +SELECT nextval('adm_encounter_id_seq'); +-- 返回:200(第一次调用) + +SELECT nextval('adm_encounter_id_seq'); +-- 返回:201(第二次调用) +``` + +### 3. 查看当前值(不递增) +```sql +SELECT currval('adm_encounter_id_seq'); +-- 返回:当前序列值(不会增加) +``` + +### 4. 重置序列 +```sql +-- 将序列重置为指定值 +SELECT setval('adm_encounter_id_seq', 200); +``` + +## 实际应用场景 + +### 场景1:插入数据时自动生成ID +```sql +INSERT INTO adm_encounter (patient_id, organization_id, ...) +VALUES (123, 456, ...); +-- id 字段会自动使用序列的下一个值(如 200, 201, 202...) +``` + +### 场景2:手动指定ID(不推荐) +```sql +INSERT INTO adm_encounter (id, patient_id, ...) +VALUES (999, 123, ...); +-- 注意:如果手动插入的ID与序列值冲突,可能导致问题 +``` + +## 注意事项 + +### 1. 序列与雪花算法的区别 +- **序列**:简单的数字递增(1, 2, 3...) +- **雪花算法**:分布式ID生成算法(如:1996923066055286785) +- **当前项目**:虽然定义了序列,但实际使用的是雪花算法(`IdType.ASSIGN_ID`) + +### 2. 序列跳号的原因 +- 事务回滚:如果事务回滚,序列值不会回退 +- 缓存:`CACHE > 1` 时,数据库重启可能导致跳号 +- 手动插入:手动插入ID后,序列不会自动调整 + +### 3. 序列的优缺点 +**优点**: +- 简单易用 +- 性能好(预分配) +- 保证唯一性 + +**缺点**: +- 可能跳号 +- 不适合分布式环境 +- 最大值有限制 + +## 相关查询语句 + +### 查看序列信息 +```sql +-- 查看序列的详细信息 +SELECT + sequence_name AS 序列名称, + last_value AS 当前值, + start_value AS 起始值, + increment_by AS 递增步长, + max_value AS 最大值, + min_value AS 最小值, + cache_size AS 缓存大小 +FROM information_schema.sequences +WHERE sequence_name = 'adm_encounter_id_seq'; +``` + +### 查看序列的下一个值(不实际使用) +```sql +SELECT last_value, is_called +FROM adm_encounter_id_seq; +``` + +### 修改序列 +```sql +-- 修改序列的起始值 +ALTER SEQUENCE adm_encounter_id_seq RESTART WITH 1000; + +-- 修改序列的最大值 +ALTER SEQUENCE adm_encounter_id_seq MAXVALUE 999999999; + +-- 修改序列的缓存大小 +ALTER SEQUENCE adm_encounter_id_seq CACHE 20; +``` +