Compare commits

...
10 Commits
171 changed files with 317524 additions and 3603 deletions
Binary file not shown.
@@ -0,0 +1 @@
../../../shierfeng-fastapi-app
@@ -132,3 +132,21 @@ DONE_WITH_CONCERNS。review 指出的生产缺陷已修复,并创建了退回
- 本轮新增的 TEST scope 入口成功回归目前集中于退回申请;入库、装填、发货和使用的既有业务成功回归仍以 `TestBatchScope.formal()` 为主。生产路径、DAO SQL scope 条件和六文件回归均已验证,但尚未为这四条链路分别补齐 TEST batch 成功、跨批次拒绝、CLOSED 拒绝、派生字段和 rollback 的专门用例。
- 目录级 Ruff format 和全仓 `git diff --check` 的既有非白名单阻塞仍按上文保留,未修改用户文件。
## Task 5 接管后补充(2026-09-23)
### 本轮修复
- 为正式模式 `SimpleNamespace` 仓库替身补齐 `test_batch_id=None`,保留服务层对已加载对象的强制 scope 校验。
- 入库、装填、发货扫码路径对仓库/现场、托盘、库存和活动装填记录增加显式 `assert_record_in_scope` 防御校验;不放宽 DAO 过滤。
- 装填与发货各增加 TEST scope 跨批次写入回滚回归;装填与发货扫码各增加跨批次对象拒绝回归。
### 最新验证
1. 红测:装填与发货跨批次扫码用例在新增服务校验前分别以 `ServiceException not raised` 失败;两条写入用例同时确认回滚路径可用。
2. 绿测:四条新增回归:`Ran 4 tests ... OK`。
3. 六文件合并:`PYTHONDONTWRITEBYTECODE=1 OPENBLAS_NUM_THREADS=1 OMP_NUM_THREADS=1 /Users/jiaolongyan/miniconda3/envs/ShiErFeng/bin/python -u -m unittest tests.module_business.test_inbound_service tests.module_business.test_filling_service tests.module_business.test_shipment_service tests.module_business.test_usage_service tests.module_business.test_return_service tests.module_business.test_inventory_dao -v`:`Ran 290 tests ... OK`。
4. 18 文件 `ruff format --check`:`18 files already formatted`;`ruff check`:`All checks passed!`。
5. 18 文件范围 `git diff --check`:无输出,exit 0。
当前 Task 5 代码已具备提交条件;本报告仍只保留为本地审查材料,不应纳入业务提交。
+12 -18
View File
@@ -8,7 +8,7 @@
* 前端采用Vue3、Element Plus。
* 移动端采用uni-app、Vue3、Vite,内置tailwindcss。
* 后端采用FastAPI、sqlalchemy、MySQL(PostgreSQL)、Redis、OAuth2 & Jwt。
* 后端采用FastAPI、sqlalchemy、MySQL、Redis、OAuth2 & Jwt。
* 权限认证使用OAuth2 & Jwt,支持多终端认证系统。
* 支持加载动态权限菜单,多方式轻松权限控制。
* 纯Python版本:
@@ -43,14 +43,16 @@
* 基础资料:菌种、客户、客户现场、产线、仓库、托盘。
* 业务流程:仓库入库、工厂装填、发货出库、客户现场使用、退回仓库。
* 只读报表:托盘库存、装填记录、发货出库、产线消耗、退回仓库、托盘追溯。
* Android PDA 可直接通过浏览器使用响应式 Web 页面,并支持 HID 扫码枪扫码后回车提交。
* Android PDA 可通过基于 uni-app 的 H5 页面使用,并支持 HID 扫码枪扫码后回车提交。
本轮交付不是 APP/uni-app 原生端,也未调用设备摄像头。上线前请阅读[托盘流转业务部署说明](./docs/pallet-workflow-deployment.md)。
本轮交付包含 PDA H5 页面,但暂不打包 APK 或其他原生安装包,也未调用设备摄像头。上线前请阅读[托盘流转业务部署说明](./docs/pallet-workflow-deployment.md)。
测试数据批次的创建、授权、历史数据纳入和清理流程请阅读[测试数据批次操作说明](./docs/test-data-batch-operations.md)。
## 在线体验
* *账号:admin*
* *密码:admin123*
* *密码:请通过授权渠道获取,不在仓库中记录*
* 演示地址:<a href="https://vfadmin.insistence.tech">vfadmin管理系统<a>
## 项目开发及发布相关
@@ -110,17 +112,15 @@ pnpm dev:mp-weixin
# 进入后端目录
cd shierfeng-fastapi-backend
# 如果使用的是MySQL数据库,请执行以下命令安装项目依赖环境
# 安装项目依赖环境(统一使用 MySQL)
pip3 install -r requirements.txt
# 如果使用的是PostgreSQL数据库,请执行以下命令安装项目依赖环境
pip3 install -r requirements-pg.txt
# 配置环境
在.env.dev文件中配置开发环境的数据库和redis
# 运行sql文件
1.新建数据库shierfeng-fastapi(默认,可修改)
2.如果使用的是MySQL数据库,使用命令或数据库连接工具运行sql文件夹下的shierfeng-fastapi.sql;如果使用的是PostgreSQL数据库,使用命令或数据库连接工具运行sql文件夹下的shierfeng-fastapi-pg.sql
# 运行 SQL 文件
1. 新建数据库 shierfeng-fastapi(默认,可修改)
2. 使用命令或数据库连接工具运行 sql 文件夹下的 shierfeng-fastapi.sql
# 运行后端
shierfeng app run --env=dev
@@ -131,9 +131,9 @@ shierfeng app run --env=dev
#### 访问
```bash
# 默认账号密码
# 本地账号
账号:admin
密码:admin123
密码:请在目标环境安全配置中设置后手工输入,不在仓库中记录
# 浏览器访问
地址:http://localhost:80
@@ -170,9 +170,3 @@ shierfeng app run --env=prod
```bash
docker compose -f shierfeng-fastapi-test/docker-compose.test.my.yml up -d --build
```
#### PostgreSQL版本
```bash
docker compose -f shierfeng-fastapi-test/docker-compose.test.pg.yml up -d --build
```
@@ -0,0 +1,106 @@
# PDA 托盘业务验收与培训手册
## 1. 文档目的
本手册用于服务器、数据库和 PDA 设备准备完成后的现场验收与客户培训。它不替代部署、数据库迁移或 APK 打包,也不把本地构建结果视为真机验收结果。
当前代码交付物是 uni-app PDA 页面、接口封装、HID 扫码组件和可验证 H5 构建;APK 按当前范围暂不生成。
## 2. 验收前置条件
- 后端服务已部署并可从 PDA 访问,已确定 `VITE_APP_BASE_API` 对应地址。
- 数据库已执行与目标数据库类型匹配的初始化 SQL/业务补丁,并完成备份。
- Redis、JWT、传输加密和验证码配置已按目标环境确认。
- 已准备管理员、仓库操作员、客户现场操作员三类账号,并分别配置仓库/现场数据范围。
- 已准备至少两个空托盘、一个已装填托盘、一个可部分使用托盘和一个可退回托盘;每个托盘二维码唯一且可扫描。
- PDA 与扫码头处于 HID 键盘输入模式,扫码结束符配置为回车;网络稳定性和离线恢复策略已确认。
- 验收记录表包含:用例编号、账号、托盘码、时间、预期结果、实际结果、截图/日志、问题编号和签字人。
## 3. 角色验收
| 角色 | 应能操作 | 不应能操作 |
| --- | --- | --- |
| 管理员 | 在授权范围内查看基础资料、业务单、报表和追溯 | 不应绕过后端权限与数据范围 |
| 仓库操作员 | 入库、装填、发货、退回收货 | 不应操作未授权仓库或客户现场 |
| 客户现场操作员 | 扫码查看托盘、绑定产线、录入使用、发起退回 | 不应确认仓库收货或访问未授权现场 |
登录页默认填充用户名 `admin`;密码必须由操作员现场手工输入,不记录在测试单、日志或源码中。
## 4. 核心业务验收用例
### 4.1 基础资料与二维码
1. Web 后台新增菌种、客户、现场、产线、仓库和托盘。
2. 为托盘设置容量,生成并查看固定二维码。
3. 重复托盘编号或二维码应被拒绝;停用托盘不能进入业务流程。
4. 为仓库和现场分配用户,使用受限账号确认数据范围。
### 4.2 入库
1. 仓库用户选择授权仓库,扫描 `UNSTOCKED` 托盘。
2. 重复扫描同一托盘应被前端提示并不会重复加入。
3. 创建入库草稿,移除一条明细后保存并重新进入详情。
4. 确认入库,检查库存状态变为仓库空托盘,并检查托盘事件。
5. 在响应丢失后使用同一操作重试,确认不会重复入库。
### 4.3 装填
1. 扫描仓库空托盘,确认页面显示仓库、容量和当前余量。
2. 选择菌种,录入批次、规格和正整数包数。
3. 使用 0、负数、超容量和未授权仓库数据验证后端拒绝。
4. 提交成功后检查状态、菌种、批次、初始包数和装填事件。
### 4.4 发货
1. 选择授权来源仓库和目标客户现场,连续扫描可发货托盘。
2. 检查页面展示的菌种、批次和剩余包数为服务端数据。
3. 创建草稿并确认,检查来源库存扣减、现场位置和发货事件。
4. 用同一幂等键重试确认,确认不会重复扣减库存。
### 4.5 客户现场使用
1. 现场用户扫描已发货托盘,确认菌种、批次和剩余包数可读。
2. 首次使用选择当前现场产线,录入正整数使用包数。
3. 使用小于余量的包数,确认状态为部分使用且剩余包数正确。
4. 使用剩余全部包数,确认状态为现场空托盘且剩余包数为 0。
5. 尝试切换已绑定的其他产线、超出余量或使用 0 包,确认请求被拒绝。
### 4.6 退回
1. 现场用户选择目标仓库并扫描可退回托盘,提交退回申请。
2. 检查托盘状态进入退回中,不能再次发货或重复申请。
3. 仓库用户查看退回详情,扫描整集合托盘并确认收货。
4. 漏扫、错扫、重复扫和余量快照变化均应阻止确认。
5. 确认成功后检查仓库库存、托盘状态和退回事件。
## 5. 报表、权限与异常验收
- 查看托盘库存、装填、发货、产线消耗、退回和托盘追溯六类报表。
- 用受限账号验证未授权菜单不显示,直接调用接口返回 403。
- 检查关键写操作包含操作人、时间、业务单和托盘事件。
- 在扫码请求期间连续回车,确认输入锁生效且不会并发提交。
- 断网后重试,确认使用原幂等键;网络恢复后不会重复扣减库存。
- 使用非法状态、库存不足、错误仓库/现场和旧详情快照,确认错误可见且状态不被部分写入。
## 6. 培训顺序
1. 讲解托盘二维码、状态和“服务端结果为准”原则。
2. 仓库操作员练习入库、装填、发货和退回收货。
3. 客户现场操作员练习扫码、产线选择、部分/全部使用和退回申请。
4. 管理员练习基础资料、用户数据范围、报表和托盘追溯。
5. 演练重复扫码、断网重试、无权限和库存不足,不使用真实业务数据做首次演示。
6. 培训结束后由各角色完成一条完整闭环:入库 → 装填 → 发货 → 使用 → 退回。
## 7. 当前不包含事项
- 本阶段不打包、签名、安装或发布 APK。
- 本阶段不调用摄像头扫码,不新增原生扫码 SDK;扫码方式为 HID 扫码头加手工输入兜底。
- 本手册不执行生产部署、数据库迁移、密码重置或客户培训;这些动作需在目标环境中按前置条件执行并留存记录。
## 8. 代码证据
- 设计与需求覆盖矩阵:`docs/superpowers/specs/2026-09-20-pda-business-workflow-design.md`
- PDA 页面与接口:`shierfeng-fastapi-app/src/pages/business`、`shierfeng-fastapi-app/src/api/business`
- Web 基础资料、业务和报表:`shierfeng-fastapi-frontend/src/views`
- 后端业务与状态机:`shierfeng-fastapi-backend/module_business`
- 数据库结构:`shierfeng-fastapi-backend/sql`
@@ -294,7 +294,7 @@ git commit --only -m '新增:PDA HID 扫码输入组件' -- \
- [ ] **Step 1: 写路由、权限和凭据安全测试并确认 RED**
测试必须断言五个页面路径和标题存在,工作台包含五类业务权限字符串,且 `src/pages/login.vue` 不再包含 `admin123` 或其他密码字面量。测试也要断言入口跳转路径与页面路径一致。
测试必须断言五个页面路径和标题存在,工作台包含五类业务权限字符串,且 `src/pages/login.vue` 不再包含旧默认密码或其他密码字面量。测试也要断言入口跳转路径与页面路径一致。
- [ ] **Step 2: 注册五个页面并实现入口过滤**
@@ -702,7 +702,7 @@ ruff check module_business tests/module_business
```bash
git diff --check HEAD~9..HEAD
rg -n --fixed-strings 'admin123' shierfeng-fastapi-app/src shierfeng-fastapi-app/tests
rg -n --fixed-strings '旧默认密码' shierfeng-fastapi-app/src shierfeng-fastapi-app/tests
rg -n 'Bearer[[:space:]]+[A-Za-z0-9._-]+' shierfeng-fastapi-app/src shierfeng-fastapi-app/tests
git status --short
```
@@ -148,6 +148,32 @@ return.js
## 9. 当前基线与风险
- Web/FastAPI 核心业务已存在并有业务测试;本次重点是 uni-app PDA 缺失能力。
- 当前 PDA 工程只有通用登录、首页、工作台和个人中心,尚无业务页面与业务 API 模块。
- 后端接口已存在,但 PDA 的实际设备联调、服务器访问地址和真实角色授权仍需运行环境配合。
- 当前 PDA 工程已包含通用登录、首页、工作台、个人中心,以及入库、装填、发货、现场使用、退回五类业务页面和对应 API 模块。
- 后端接口、Web 管理页面和数据库 SQL 已存在;PDA 的实际设备联调、服务器访问地址、数据库迁移和真实角色授权仍需运行环境配合。
- APK 暂不打包,因此本次交付物是源码、接口封装、页面和可验证开发版本,不包含安装包。
## 10. 需求覆盖矩阵(代码审计结果)
下表区分“代码已实现”和“真实环境已交付”,避免把静态测试或本地构建误认为部署、安装或培训完成。
| 序号 | 需求 | 当前结论 | 主要证据 |
| ---: | --- | --- | --- |
| 1 | 业务流程、功能边界、角色、交付内容和不包含事项 | 已确认 | 本设计第 1~3、8~9 节 |
| 2 | 托盘、菌种、产线、仓库、装填、发货、使用、退回字段 | 已梳理 | `module_business/entity`、SQL 脚本 |
| 3 | 后台、接口、数据库结构和基础运行环境 | 代码已完成;实际环境未部署 | `module_business`、`sql/`、前后端工程 |
| 4 | 菌种、产线、仓库、用户等基础资料维护 | 已实现 | Web `views/master`、系统用户/角色模块 |
| 5 | 托盘唯一标识、固定二维码、状态和档案 | 已实现 | `biz_pallet` 唯一约束、状态机、托盘管理页 |
| 6 | 入库登记、入库单、库存更新 | 已实现 | `inbound_controller.py`、`inbound_service.py` |
| 7 | 扫码装填菌种、批次、规格、包数并更新状态 | 已实现 | `filling_service.py`、Web/PDA 装填页 |
| 8 | 发货单、托盘扫码/选择、明细和库存扣减 | 已实现 | `shipment_service.py`、Web/PDA 发货页 |
| 9 | PDA 登录、扫码识别和读取菌种/余量 | 已实现;未打包 APK | `shierfeng-fastapi-app/src/pages/business`、PDA API |
| 10 | 客户扫码、产线绑定、使用包数、操作人和时间 | 已实现 | `usage_service.py`、使用记录模型和页面 |
| 11 | 全部/部分使用、剩余包数、退回和状态流转 | 已实现 | `pallet_state_machine.py`、使用/退回服务 |
| 12 | 六类库存、装填、发货、消耗、退回、追溯报表 | 已实现 | `report_controller.py`、Web 六类报表页 |
| 13 | 权限、操作记录、流转追溯和异常留痕 | 已实现 | 权限依赖、`Log`、`biz_pallet_event`、追溯报表 |
| 14 | Android 页面、接口、PDA 适配和 APK | 页面/API/HID 已实现;APK 按要求暂缓 | PDA H5 构建与扫码组件 |
| 15 | 后台、接口、PDA、库存、退回整体联调 | 代码级验证完成;真实设备联调未完成 | 契约测试通过;缺少真实设备/服务地址 |
| 16 | 服务器、数据库、后台/接口服务和访问地址部署 | 未完成 | 缺少目标服务器和部署授权 |
| 17 | App 安装、扫码验收和客户培训 | 未完成 | 缺少 PDA 设备及培训安排 |
登录页默认只填充用户名 `admin`;密码保持空白并由操作员手工输入,不将真实密码写入源码、测试或日志。
+54
View File
@@ -0,0 +1,54 @@
# 测试数据批次操作说明
测试数据采用批次隔离。正式数据的 `test_batch_id` 为 `NULL`,测试数据必须归属于一个 `biz_test_batch` 批次。系统不会因为安装迁移脚本而自动把历史数据标记为测试数据;历史数据需要由超级管理员逐项预览并纳入批次。
## 权限边界
- 批次创建、编辑、授权、关闭/重新开启、旧数据纳入和批次清理均由后端校验超级管理员身份。
- 普通用户不能通过前端隐藏、菜单权限或直接调用接口绕过后端校验。
- 普通用户只能看到被授权且状态为 `ACTIVE` 的批次,并在 PDA 或 Web 测试模式中使用该批次。
- 物理删除不再通过菌种、客户、现场、产线、仓库、托盘、入库和发货页面提供。清理必须以批次为单位执行。
## 上线前准备
1. 先备份数据库,并确认当前没有正在进行的入库、装填、发货、使用或退回操作。
2. MySQL 执行 `shierfeng-fastapi-backend/sql/patches/20260922_test_data_batch_mysql.sql`。
3. 迁移完成后检查 `biz_test_batch`、`biz_test_batch_user` 和各业务表的 `test_batch_id` 字段及外键。
4. 配置在线清理上限。默认 `TEST_BATCH_ONLINE_PURGE_MAX_ROWS=0`,表示禁止在线清理;只有明确配置为正整数且批次影响总数不超过上限时,管理页才允许执行清理。预览令牌默认有效期为 `TEST_BATCH_PREVIEW_TTL_SECONDS=600` 秒。
迁移脚本是一次性增量脚本,重复执行前必须由数据库管理员确认目标表和字段是否已经存在。本文档不替代备份、变更审批和回滚预案。
## 新建并授权批次
1. 超级管理员登录 Web 管理端,进入“系统管理 -> 测试数据批次”,创建批次并记录批次名称。
2. 在“用户”操作中填写需要参与测试的用户 ID。保存时会完整替换该批次的授权用户列表;留空表示取消全部授权。
3. 用户在 PDA 工作台选择“测试”并选择已授权的 ACTIVE 批次。切换模式会重新打开工作台,清空当前页面未提交的表单和扫码状态。
4. 测试模式下的请求自动携带 `X-Test-Batch-Id`。批次关闭、清理、撤销授权或失效后,客户端会清除本地批次并回到正式模式。
## 将历史数据纳入批次
历史数据默认仍是正式数据。只有超级管理员可以在菌种、客户、现场、产线、仓库、托盘以及五类业务页面选择根记录,点击“纳入测试批次”。
纳入操作分为两步:
1. **预览**:系统根据根记录计算完整关联闭包,展示将被标记的记录和数量,并生成短时有效的预览令牌。
2. **执行**:管理员核对批次名称和影响范围后提交。服务端会重新加锁并计算闭包;范围变化、记录已归属于其他批次、批次关闭或令牌过期时,整个操作失败并回滚。
不要直接修改业务表的 `test_batch_id`。这样会跳过关联闭包、并发校验和审计记录,可能造成跨批次数据无法清理。
## 关闭与清理批次
1. 批次完成测试后先点击“关闭”。关闭后不能继续写入该批次,但可以重新开启;重新开启会使已有的清理预览失效。
2. 对 CLOSED 批次点击“清理”,先查看预览中的分类、数量和编号。
3. 只有在线清理上限允许时,输入完整批次名称并确认执行。服务端会校验预览令牌、批次名称、影响范围和当前行数,然后按依赖顺序在一个事务中删除批次闭包。
4. 成功后批次状态变为 `PURGED`,保留清理时间、执行人和数量摘要;已清理批次不可重新开启或再次写入。
清理是不可逆的数据删除操作。影响总数超过在线上限时,应按运维审批流程执行离线清理,不要通过 SQL 手工绕过系统约束。
## 验证清单
- 正式模式看不到 `test_batch_id` 非空的测试记录。
- 普通用户无法看到批次管理页的管理操作,也无法调用纳入和清理接口。
- PDA 测试模式的请求带有正确批次 ID,退出登录后本地批次缓存被清除。
- 关闭批次后新建和确认操作被拒绝;清理预览与实际执行之间的数据变化会使执行失败而不是误删。
- 清理完成后,批次闭包中的主数据、单据、明细、库存和事件记录数量与审计摘要一致。
+12
View File
@@ -23,6 +23,18 @@
>
> 另外谨慎升级 `package.json` 中锁定的 `pinia`/`vue`/`@vue/*` 相关包的版本,新版本可能 `uni-app` 没有兼容,造成一些奇怪的 bug
### 配置 PDA 后端地址
PDA 默认请求本机 `http://localhost:9099`,仅适用于后端运行在同一设备的本地开发。部署到独立 PDA 或局域网服务器时,在构建环境注入 `VITE_APP_BASE_API`:
```bash
VITE_APP_BASE_API=http://<服务器地址>:9099 pnpm run build:h5
```
不要把包含真实凭据的环境文件或地址配置提交到仓库。
PDA 测试模式、批次授权和失效回退规则请阅读[测试数据批次操作说明](../docs/test-data-batch-operations.md)。PDA 只允许选择后端返回的 ACTIVE 授权批次,退出登录会清除本地批次上下文。
### vscode
使用 `vscode` 的开发者,请先安装 [Tailwind CSS IntelliSense](https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss) 智能提示与感应插件
+1
View File
@@ -2,6 +2,7 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/static/favicon.ico" />
<script>
var coverSupport =
'CSS' in window &&
+1
View File
@@ -3,6 +3,7 @@
"version": "1.9.0",
"packageManager": "pnpm@10.28.1",
"scripts": {
"test:business": "node --test tests/business-contract.test.mjs",
"dev": "uni -p mp-weixin",
"build": "npm run build:mp-weixin",
"dev:app": "uni -p app",
@@ -0,0 +1,38 @@
import request from "@/utils/request";
export function listFilling(query) {
return request({
url: "/business/filling/list",
method: "get",
params: query,
});
}
export function getFillingStrainOptions() {
return request({
url: "/business/filling/strain-options",
method: "get",
});
}
export function scanFillingPallet(qrToken) {
return request({
url: "/business/filling/scan/" + qrToken,
method: "get",
});
}
export function getFilling(fillingId) {
return request({
url: "/business/filling/" + fillingId,
method: "get",
});
}
export function addFilling(data) {
return request({
url: "/business/filling",
method: "post",
data,
});
}
@@ -0,0 +1,56 @@
import request from "@/utils/request";
export function listInbound(query) {
return request({
url: "/business/inbound/list",
method: "get",
params: query,
});
}
export function getInboundWarehouseOptions() {
return request({
url: "/business/inbound/warehouse-options",
method: "get",
});
}
export function scanInboundPallet(qrToken, query) {
return request({
url: "/business/inbound/scan/" + qrToken,
method: "get",
params: query,
});
}
export function getInbound(inboundId) {
return request({
url: "/business/inbound/" + inboundId,
method: "get",
});
}
export function addInbound(data) {
return request({
url: "/business/inbound",
method: "post",
data,
});
}
export function updateInbound(data) {
return request({
url: "/business/inbound",
method: "put",
data,
});
}
export function confirmInbound(inboundId, data) {
return request({
url: "/business/inbound/" + inboundId + "/confirm",
method: "put",
data,
headers: { repeatSubmit: false },
});
}
@@ -0,0 +1,47 @@
import request from "@/utils/request";
export function listReturn(query) {
return request({
url: "/business/return/list",
method: "get",
params: query,
});
}
export function getReturnWarehouseOptions() {
return request({
url: "/business/return/warehouse-options",
method: "get",
});
}
export function scanReturnPallet(qrToken, query) {
return request({
url: "/business/return/scan/" + qrToken,
method: "get",
params: query,
});
}
export function requestReturn(data) {
return request({
url: "/business/return/request",
method: "post",
data,
});
}
export function getReturn(returnId) {
return request({
url: "/business/return/" + returnId,
method: "get",
});
}
export function confirmReturn(returnId, data) {
return request({
url: "/business/return/" + returnId + "/confirm",
method: "put",
data,
});
}
@@ -0,0 +1,62 @@
import request from "@/utils/request";
export function listShipment(query) {
return request({
url: "/business/shipment/list",
method: "get",
params: query,
});
}
export function getShipmentWarehouseOptions() {
return request({
url: "/business/shipment/warehouse-options",
method: "get",
});
}
export function getShipmentSiteOptions() {
return request({
url: "/business/shipment/site-options",
method: "get",
});
}
export function scanShipmentPallet(qrToken, query) {
return request({
url: "/business/shipment/scan/" + qrToken,
method: "get",
params: query,
});
}
export function getShipment(shipmentId) {
return request({
url: "/business/shipment/" + shipmentId,
method: "get",
});
}
export function addShipment(data) {
return request({
url: "/business/shipment",
method: "post",
data,
});
}
export function updateShipment(data) {
return request({
url: "/business/shipment",
method: "put",
data,
});
}
export function confirmShipment(shipmentId, data) {
return request({
url: "/business/shipment/" + shipmentId + "/confirm",
method: "put",
data,
});
}
@@ -0,0 +1,39 @@
import request from "@/utils/request";
export function listUsage(query) {
return request({
url: "/business/usage/list",
method: "get",
params: query,
});
}
export function getUsageLineOptions(siteId) {
return request({
url: "/business/usage/line-options",
method: "get",
params: { siteId },
});
}
export function scanUsagePallet(qrToken) {
return request({
url: "/business/usage/scan/" + qrToken,
method: "get",
});
}
export function getUsage(usageId) {
return request({
url: "/business/usage/" + usageId,
method: "get",
});
}
export function addUsage(data) {
return request({
url: "/business/usage",
method: "post",
data,
});
}
@@ -0,0 +1,9 @@
import request from "@/utils/request";
// PDA 只读取当前登录用户被授权且仍处于 ACTIVE 状态的批次。
export function listAvailableTestBatches() {
return request({
url: "/system/test-batch/options",
method: "get",
});
}
@@ -0,0 +1,115 @@
<template>
<view class="w-full">
<view class="flex items-center rounded-xl bg-white p-2 shadow-sm">
<input
v-model="scanValue"
class="h-11 min-w-0 flex-1 px-3 text-sm text-gray-700"
type="text"
confirm-type="done"
maxlength="128"
:focus="focusRequested"
:disabled="disabled || loading"
placeholder="请扫描或输入托盘二维码后按回车"
@confirm="handleSubmit"
@input="clearError"
/>
<button
class="ml-2 h-10 rounded-lg bg-blue-500 px-3 text-xs text-white active:opacity-80 disabled:bg-gray-300"
:disabled="disabled || loading"
@click="handleSubmit"
>
{{ loading ? "校验中" : "提交扫描" }}
</button>
</view>
<text v-if="errorMessage" class="mt-2 block text-xs text-red-500">
{{ errorMessage }}
</text>
</view>
</template>
<script setup>
import { nextTick, onMounted, ref, watch } from "vue";
import { isDuplicateScan, normalizeScanValue } from "@/utils/palletScan";
const props = defineProps({
disabled: {
type: Boolean,
default: false,
},
loading: {
type: Boolean,
default: false,
},
duplicateWindowMs: {
type: Number,
default: 500,
},
});
const emit = defineEmits(["scan", "invalid", "duplicate"]);
const scanValue = ref("");
const errorMessage = ref("");
const focusRequested = ref(false);
let lastScanValue = "";
let lastScanAt = 0;
function focusInput() {
if (props.disabled || props.loading) return;
focusRequested.value = false;
nextTick(() => {
if (!props.disabled && !props.loading) {
focusRequested.value = true;
}
});
}
function clearError() {
errorMessage.value = "";
}
function handleSubmit() {
if (props.disabled || props.loading) return;
let normalizedValue;
try {
normalizedValue = normalizeScanValue(scanValue.value);
} catch (error) {
errorMessage.value = error.message;
emit("invalid", error.message);
focusInput();
return;
}
const scannedAt = Date.now();
if (
isDuplicateScan(
normalizedValue,
lastScanValue,
scannedAt,
lastScanAt,
props.duplicateWindowMs,
)
) {
scanValue.value = "";
emit("duplicate", normalizedValue);
focusInput();
return;
}
lastScanValue = normalizedValue;
lastScanAt = scannedAt;
scanValue.value = "";
errorMessage.value = "";
emit("scan", normalizedValue);
focusInput();
}
onMounted(focusInput);
watch(
() => [props.disabled, props.loading],
([disabled, loading]) => {
if (!disabled && !loading) focusInput();
},
);
</script>
@@ -0,0 +1,22 @@
<template>
<view
v-if="testBatchStore.isTestMode"
class="flex items-start gap-3 rounded-xl border border-red-300 bg-red-50 px-3 py-3"
>
<view class="mt-0.5 flex size-6 shrink-0 items-center justify-center rounded-full bg-red-500 text-white">
<view class="i-mdi-flask-outline text-sm"></view>
</view>
<view class="min-w-0">
<text class="block text-sm font-bold text-red-700">测试数据</text>
<text class="mt-0.5 block break-all text-xs leading-5 text-red-600">
当前批次:{{ testBatchStore.currentBatchName || "已选测试批次" }}
</text>
</view>
</view>
</template>
<script setup>
import { useTestBatchStore } from "@/store";
const testBatchStore = useTestBatchStore();
</script>
@@ -0,0 +1,153 @@
<template>
<view class="space-y-3 rounded-2xl bg-white p-4 shadow-sm">
<view class="flex items-center justify-between gap-3">
<view class="min-w-0">
<text class="block text-sm font-bold text-gray-800">数据模式</text>
<text class="mt-1 block text-xs text-gray-500">
{{ testBatchStore.isTestMode ? "当前操作隔离在测试批次" : "当前使用正式数据" }}
</text>
</view>
<text
:class="testBatchStore.isTestMode ? 'border-red-300 bg-red-50 text-red-700' : 'border-gray-200 bg-gray-50 text-gray-600'"
class="shrink-0 rounded-full border px-2.5 py-1 text-xs font-semibold"
>
{{ testBatchStore.isTestMode ? "测试数据" : "正式数据" }}
</text>
</view>
<view class="flex rounded-xl bg-gray-100 p-1">
<button
class="flex-1 rounded-lg py-2 text-xs transition-colors"
:class="!testBatchStore.isTestMode ? 'bg-white font-semibold text-gray-800 shadow-sm' : 'text-gray-500'"
:disabled="loading"
size="mini"
@click="handleModeClick('formal')"
>
正式
</button>
<button
class="flex-1 rounded-lg py-2 text-xs transition-colors"
:class="testBatchStore.isTestMode ? 'bg-red-500 font-semibold text-white shadow-sm' : 'text-gray-500'"
:disabled="loading || !activeOptions.length"
size="mini"
@click="handleModeClick('test')"
>
测试
</button>
</view>
<view v-if="testBatchStore.isTestMode || activeOptions.length" class="space-y-1">
<text class="block text-xs text-gray-500">测试批次</text>
<picker
:range="activeOptions"
range-key="batchName"
:value="selectedBatchIndex"
:disabled="loading || !activeOptions.length"
@change="handleBatchChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedBatch?.batchName || (loading ? "加载中..." : "暂无可用测试批次") }}
</view>
</picker>
</view>
<view v-if="loadError" class="flex items-center justify-between gap-2 rounded-lg bg-orange-50 px-3 py-2">
<text class="min-w-0 text-xs leading-5 text-orange-700">{{ loadError }}</text>
<button class="shrink-0 text-xs text-orange-700" size="mini" :disabled="loading" @click="loadOptions">
重试
</button>
</view>
</view>
</template>
<script setup>
import { computed, onMounted, ref } from "vue";
import { useTestBatchStore } from "@/store";
const testBatchStore = useTestBatchStore();
const loading = ref(false);
const loadError = ref("");
const activeOptions = computed(() =>
testBatchStore.options.filter((item) => item.status === "ACTIVE"),
);
const selectedBatch = computed(() =>
activeOptions.value.find(
(item) => String(item.batchId) === String(testBatchStore.currentBatchId),
),
);
const selectedBatchIndex = computed(() => {
const index = activeOptions.value.findIndex(
(item) => String(item.batchId) === String(testBatchStore.currentBatchId),
);
return index >= 0 ? index : 0;
});
function errorMessage(error) {
return error?.response?.data?.msg || error?.message || "测试批次加载失败,请稍后重试";
}
async function loadOptions() {
loading.value = true;
loadError.value = "";
try {
await testBatchStore.refreshOptions();
} catch (error) {
if (error?.reason !== "TEST_BATCH_UNAVAILABLE") {
loadError.value = errorMessage(error);
}
} finally {
loading.value = false;
}
}
function confirmModeSwitch() {
return new Promise((resolve) => {
uni.showModal({
title: "切换数据模式",
content: "切换后会清空当前页面未提交的扫码和表单内容,确定继续吗?",
cancelText: "取消",
confirmText: "确定",
success: (result) => resolve(result.confirm === true),
fail: () => resolve(false),
});
});
}
async function handleModeClick(mode) {
if (loading.value) return;
if (mode === "formal") {
if (!testBatchStore.isTestMode || !(await confirmModeSwitch())) return;
testBatchStore.leaveTestMode();
uni.reLaunch({ url: "/pages/work/index" });
return;
}
if (testBatchStore.isTestMode) return;
const batch = activeOptions.value[0];
if (!batch) {
uni.showToast({ title: "暂无可用测试批次", icon: "none" });
return;
}
if (!(await confirmModeSwitch())) return;
try {
testBatchStore.selectBatch(batch);
uni.reLaunch({ url: "/pages/work/index" });
} catch (error) {
uni.showToast({ title: error.message || "测试批次不可用", icon: "none" });
}
}
async function handleBatchChange(event) {
const batch = activeOptions.value[Number(event.detail.value)];
if (!batch || String(batch.batchId) === String(testBatchStore.currentBatchId)) return;
if (!(await confirmModeSwitch())) return;
try {
testBatchStore.selectBatch(batch);
uni.reLaunch({ url: "/pages/work/index" });
} catch (error) {
uni.showToast({ title: error.message || "测试批次不可用", icon: "none" });
}
}
onMounted(loadOptions);
</script>
+3 -2
View File
@@ -1,6 +1,7 @@
// 应用全局配置
export default {
baseUrl: "http://localhost:9099",
// PDA 部署到独立设备时由构建环境注入服务器地址;本地开发保留回环地址。
baseUrl: import.meta.env.VITE_APP_BASE_API || "http://localhost:9099",
// 应用信息
appInfo: {
// 应用名称
@@ -8,7 +9,7 @@ export default {
// 应用版本
version: "1.9.0",
// 应用logo
logo: "/static/logo.png",
logo: "/static/sylvan-logo.png",
// 官方网站
site_url: "https://vfadmin.insistence.tech",
// 政策协议
+14
View File
@@ -5,10 +5,24 @@ import store from "./store"; // store
import { install } from "./plugins"; // plugins
import "./permission"; // permission
import { useDict } from "@/utils/dict";
import { useTestBatchStore } from "./store";
let testBatchUnavailableListenerRegistered = false;
function registerTestBatchUnavailableListener() {
if (testBatchUnavailableListenerRegistered || typeof uni.$on !== "function") {
return;
}
testBatchUnavailableListenerRegistered = true;
uni.$on("test-batch-unavailable", () => {
useTestBatchStore().leaveTestMode();
});
}
export function createApp() {
const app = createSSRApp(App);
app.use(store);
registerTestBatchUnavailableListener();
app.config.globalProperties.useDict = useDict;
install(app);
return {
+30
View File
@@ -25,6 +25,36 @@
"navigationBarTitleText": "工作台"
}
},
{
"path": "pages/business/inbound/index",
"style": {
"navigationBarTitleText": "仓库入库"
}
},
{
"path": "pages/business/filling/index",
"style": {
"navigationBarTitleText": "托盘装填"
}
},
{
"path": "pages/business/shipment/index",
"style": {
"navigationBarTitleText": "发货出库"
}
},
{
"path": "pages/business/usage/index",
"style": {
"navigationBarTitleText": "现场使用"
}
},
{
"path": "pages/business/return/index",
"style": {
"navigationBarTitleText": "退回仓库"
}
},
{
"path": "pages/mine/index",
"style": {
@@ -0,0 +1,364 @@
<template>
<view class="min-h-screen bg-gray-50">
<scroll-view scroll-y class="h-screen">
<view class="space-y-4 p-4 pb-24">
<view>
<text class="block text-xl font-bold text-gray-800">托盘装填</text>
<text class="mt-1 block text-xs text-gray-500">
扫描空托盘,录入菌种、批次、规格和初始包数
</text>
</view>
<TestBatchBanner />
<view v-if="!canPage" class="rounded-2xl bg-white p-6 text-center shadow-sm">
<text class="text-sm text-gray-500">当前账号没有装填操作权限</text>
</view>
<template v-else>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">扫描待装填托盘</text>
<button
class="text-xs text-gray-500"
size="mini"
:disabled="operationPending"
@click="resetOperation"
>
清空
</button>
</view>
<PalletScanInput
:disabled="operationPending || optionLoading"
:loading="scanLoading"
@scan="handleFillingScan"
@invalid="handleScanInvalid"
@duplicate="handleScanDuplicate"
/>
<text class="mt-2 block text-xs text-gray-400">
仅接受 EMPTY_IN_WAREHOUSE 状态托盘。
</text>
<text v-if="scanError" class="mt-2 block text-xs text-red-500">{{ scanError }}</text>
<view v-if="scannedPallet" class="mt-4 rounded-xl bg-green-50 p-3">
<view class="flex items-center justify-between">
<text class="font-medium text-gray-700">
{{ scannedPallet.palletCode || `#${scannedPallet.palletId}` }}
</text>
<text class="text-xs text-green-600">{{ scannedPallet.flowState }}</text>
</view>
<text class="mt-1 block text-xs text-gray-500">
仓库:{{ scannedPallet.warehouseName || `#${scannedPallet.warehouseId}` }} · 容量:{{ scannedPallet.capacityPackages }} 包
</text>
</view>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<text class="mb-3 block font-bold text-gray-800">装填信息</text>
<view class="space-y-3">
<view>
<text class="mb-2 block text-xs text-gray-500">菌种</text>
<picker
:range="strainOptions"
range-key="name"
:value="strainIndex"
:disabled="operationPending || optionLoading || !scannedPallet"
@change="handleStrainChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedStrainName || "请选择启用菌种" }}
</view>
</picker>
</view>
<view>
<text class="mb-2 block text-xs text-gray-500">生产批次</text>
<input
v-model="form.batchNo"
class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700"
maxlength="64"
placeholder="请输入生产批次"
:disabled="operationPending || !scannedPallet"
@input="markPayloadChanged"
/>
</view>
<view>
<text class="mb-2 block text-xs text-gray-500">包装规格</text>
<input
v-model="form.packageSpec"
class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700"
maxlength="64"
placeholder="例如:500g/包"
:disabled="operationPending || !scannedPallet"
@input="markPayloadChanged"
/>
</view>
<view>
<text class="mb-2 block text-xs text-gray-500">初始包数</text>
<input
v-model="form.initialPackages"
class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700"
type="number"
placeholder="请输入正整数"
:disabled="operationPending || !scannedPallet"
@input="markPayloadChanged"
/>
<text v-if="scannedPallet" class="mt-1 block text-xs text-gray-400">
托盘容量 {{ scannedPallet.capacityPackages }} 包,最终容量由服务端校验
</text>
</view>
</view>
<text v-if="formError" class="mt-3 block text-xs text-red-500">{{ formError }}</text>
<button
class="mt-4 w-full rounded-xl bg-green-500 py-3 text-sm text-white active:opacity-80 disabled:bg-gray-300"
:disabled="!canOperate || operationPending || scanLoading || !scannedPallet"
@click="submitFilling"
>
{{ submitLoading ? "提交中" : "确认装填" }}
</button>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">最近装填记录</text>
<button class="text-xs text-blue-500" size="mini" :disabled="loading" @click="loadFillingList">
刷新
</button>
</view>
<text v-if="listError" class="mb-3 block text-xs text-red-500">{{ listError }}</text>
<view v-if="loading" class="py-6 text-center text-xs text-gray-400">加载中...</view>
<view v-else-if="!fillingList.length" class="py-6 text-center text-xs text-gray-400">
暂无装填记录
</view>
<view
v-for="row in fillingList"
v-else
:key="row.fillingId"
class="mb-3 rounded-xl border border-gray-100 p-3 last:mb-0"
>
<text class="block font-medium text-gray-700">{{ row.fillingNo || `#${row.fillingId}` }}</text>
<text class="mt-1 block text-xs text-gray-500">
{{ row.strainNameSnapshot || row.strainCodeSnapshot }} · {{ row.batchNo }} · {{ row.initialPackages }} 包
</text>
<text class="mt-1 block text-xs text-gray-400">托盘 #{{ row.palletId }} · {{ row.operatedAt || row.createTime || "—" }}</text>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, getCurrentInstance, reactive, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PalletScanInput from "@/components/business/PalletScanInput.vue";
import TestBatchBanner from "@/components/business/TestBatchBanner.vue";
import {
addFilling,
getFillingStrainOptions,
listFilling,
scanFillingPallet,
} from "@/api/business/filling";
import { createIdempotencyKey } from "@/utils/palletScan";
const { proxy } = getCurrentInstance();
const fillingList = ref([]);
const strainOptions = ref([]);
const scannedPallet = ref(null);
const loading = ref(false);
const optionLoading = ref(false);
const scanLoading = ref(false);
const submitLoading = ref(false);
const listError = ref("");
const scanError = ref("");
const formError = ref("");
const idempotencyKey = ref("");
const form = reactive({
qrToken: "",
warehouseId: null,
strainId: null,
batchNo: "",
packageSpec: "",
initialPackages: "",
});
let listGeneration = 0;
let scanGeneration = 0;
const canPage = computed(() =>
proxy.$auth.hasPermiOr([
"business:filling:list",
"business:filling:query",
"business:filling:add",
]),
);
const canList = computed(() => proxy.$auth.hasPermi("business:filling:list"));
const canOperate = computed(() =>
proxy.$auth.hasPermiAnd(["business:filling:query", "business:filling:add"]),
);
const operationPending = computed(() => submitLoading.value);
const strainIndex = computed(() => {
const index = strainOptions.value.findIndex((item) => item.id === form.strainId);
return index >= 0 ? index : 0;
});
const selectedStrainName = computed(
() => strainOptions.value.find((item) => item.id === form.strainId)?.name || "",
);
function errorMessage(error, fallback) {
return error?.response?.data?.msg || error?.message || fallback;
}
function loadFillingList() {
if (!canList.value) return;
const generation = ++listGeneration;
loading.value = true;
listError.value = "";
listFilling({ pageNum: 1, pageSize: 20 })
.then((response) => {
if (generation !== listGeneration) return;
fillingList.value = Array.isArray(response.rows) ? response.rows : [];
})
.catch((error) => {
if (generation !== listGeneration) return;
fillingList.value = [];
listError.value = errorMessage(error, "装填记录加载失败,请稍后重试");
})
.finally(() => {
if (generation === listGeneration) loading.value = false;
});
}
function loadStrainOptions() {
if (!proxy.$auth.hasPermi("business:filling:query")) return;
optionLoading.value = true;
getFillingStrainOptions()
.then((response) => {
strainOptions.value = Array.isArray(response.data) ? response.data : [];
})
.catch((error) => {
strainOptions.value = [];
formError.value = errorMessage(error, "菌种选项加载失败,请稍后重试");
})
.finally(() => {
optionLoading.value = false;
});
}
function resetOperation() {
scanGeneration += 1;
scannedPallet.value = null;
idempotencyKey.value = "";
form.qrToken = "";
form.warehouseId = null;
form.strainId = null;
form.batchNo = "";
form.packageSpec = "";
form.initialPackages = "";
scanError.value = "";
formError.value = "";
scanLoading.value = false;
}
function handleFillingScan(qrToken) {
if (operationPending.value || scanLoading.value || optionLoading.value) return;
resetOperation();
const generation = ++scanGeneration;
scanLoading.value = true;
scanError.value = "";
scanFillingPallet(qrToken)
.then((response) => {
if (generation !== scanGeneration) return;
const pallet = response.data;
if (pallet?.flowState !== "EMPTY_IN_WAREHOUSE") {
scanError.value = "该托盘当前不可装填";
return;
}
scannedPallet.value = {
palletId: pallet.palletId,
palletCode: pallet.palletCode || `#${pallet.palletId}`,
warehouseId: pallet.warehouseId,
warehouseName: pallet.warehouseName,
flowState: pallet.flowState,
capacityPackages: pallet.capacityPackages,
};
form.qrToken = qrToken;
form.warehouseId = pallet.warehouseId;
loadStrainOptions();
})
.catch((error) => {
if (generation === scanGeneration) {
scanError.value = errorMessage(error, "托盘扫码校验失败,请检查后重试");
}
})
.finally(() => {
if (generation === scanGeneration) scanLoading.value = false;
});
}
function handleScanInvalid(message) {
resetOperation();
scanError.value = message;
}
function handleScanDuplicate() {
proxy.$modal.msg("扫码过快,请勿重复扫描");
}
function handleStrainChange(event) {
const option = strainOptions.value[Number(event.detail.value)];
form.strainId = option?.id || null;
markPayloadChanged();
}
function markPayloadChanged() {
if (!submitLoading.value) idempotencyKey.value = "";
}
function ensureIdempotencyKey() {
if (!idempotencyKey.value) idempotencyKey.value = createIdempotencyKey();
return idempotencyKey.value;
}
function submitFilling() {
if (!canOperate.value || operationPending.value || scanLoading.value || optionLoading.value) return;
const initialPackages = Number(form.initialPackages);
if (!scannedPallet.value || !form.qrToken || !form.warehouseId) {
formError.value = "请先扫描待装填托盘";
return;
}
if (!form.strainId || !form.batchNo.trim() || !form.packageSpec.trim()) {
formError.value = "请完整填写菌种、批次和包装规格";
return;
}
if (!Number.isInteger(initialPackages) || initialPackages <= 0) {
formError.value = "初始包数必须为正整数";
return;
}
submitLoading.value = true;
formError.value = "";
addFilling({
qrToken: form.qrToken,
warehouseId: form.warehouseId,
strainId: form.strainId,
batchNo: form.batchNo.trim(),
packageSpec: form.packageSpec.trim(),
initialPackages,
idempotencyKey: ensureIdempotencyKey(),
})
.then((response) => {
idempotencyKey.value = "";
proxy.$modal.msgSuccess(response.msg || "托盘装填成功");
resetOperation();
loadFillingList();
})
.catch((error) => {
formError.value = `${errorMessage(error, "装填提交失败")};直接重试将复用本次幂等键,修改输入后会生成新键`;
})
.finally(() => {
submitLoading.value = false;
});
}
onShow(() => {
loadFillingList();
});
</script>
@@ -0,0 +1,486 @@
<template>
<view class="min-h-screen bg-gray-50">
<scroll-view scroll-y class="h-screen">
<view class="space-y-4 p-4 pb-24">
<view class="flex items-center justify-between">
<view>
<text class="block text-xl font-bold text-gray-800">仓库入库</text>
<text class="mt-1 block text-xs text-gray-500">
扫描尚未首次入库的空托盘,保存草稿后确认
</text>
</view>
<button
v-if="canDraft"
class="rounded-lg bg-blue-500 px-3 py-2 text-xs text-white active:opacity-80"
size="mini"
:disabled="operationPending"
@click="startNewDraft"
>
新建草稿
</button>
</view>
<TestBatchBanner />
<view v-if="!canPage" class="rounded-2xl bg-white p-6 text-center shadow-sm">
<text class="text-sm text-gray-500">当前账号没有入库操作权限</text>
</view>
<template v-else>
<view v-if="editorVisible" class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-4 flex items-center justify-between">
<text class="font-bold text-gray-800">
{{ editing ? "编辑入库草稿" : "新建入库草稿" }}
</text>
<text class="text-xs text-gray-400">托盘数量 {{ scannedPallets.length }}</text>
</view>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">入库仓库</text>
<picker
:range="warehouseOptions"
range-key="name"
:value="warehouseIndex"
:disabled="optionLoading || detailLoading || operationPending"
@change="handleWarehouseChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedWarehouseName || "请选择授权仓库" }}
</view>
</picker>
</view>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">连续扫码</text>
<PalletScanInput
:disabled="!form.warehouseId || detailLoading || operationPending"
:loading="scanLoading"
@scan="handleInboundScan"
@invalid="handleScanInvalid"
@duplicate="handleScanDuplicate"
/>
<text class="mt-2 block text-xs text-gray-400">
仅接受 UNSTOCKED 托盘;同一托盘不会重复加入。
</text>
</view>
<text v-if="scanError" class="mb-3 block text-xs text-red-500">{{ scanError }}</text>
<text v-if="formError" class="mb-3 block text-xs text-red-500">{{ formError }}</text>
<view v-if="scannedPallets.length" class="mb-4 space-y-2">
<view
v-for="pallet in scannedPallets"
:key="pallet.palletId"
class="flex items-center justify-between rounded-xl bg-blue-50 px-3 py-2"
>
<view>
<text class="block text-sm font-medium text-gray-700">
{{ pallet.palletCode || `#${pallet.palletId}` }}
</text>
<text class="block text-xs text-gray-500">{{ pallet.flowState }}</text>
</view>
<button
class="text-xs text-red-500"
size="mini"
:disabled="operationPending || detailLoading"
@click="removeScannedPallet(pallet.palletId)"
>
移除
</button>
</view>
</view>
<view class="flex gap-3">
<button
class="flex-1 rounded-xl bg-blue-500 py-3 text-sm text-white active:opacity-80 disabled:bg-gray-300"
:disabled="!canSaveDraft || operationPending || scanLoading || detailLoading"
@click="saveDraft"
>
{{ submitLoading ? "保存中" : editing ? "保存修改" : "保存草稿" }}
</button>
<button
class="flex-1 rounded-xl bg-gray-100 py-3 text-sm text-gray-600 active:opacity-80"
:disabled="operationPending"
@click="cancelEditor"
>
取消
</button>
</view>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">入库单</text>
<button
class="text-xs text-blue-500"
size="mini"
:disabled="loading || operationPending"
@click="loadInboundList"
>
刷新
</button>
</view>
<text v-if="listError" class="mb-3 block text-xs text-red-500">{{ listError }}</text>
<text v-if="confirmError" class="mb-3 block text-xs text-red-500">{{ confirmError }}</text>
<view v-if="loading" class="py-6 text-center text-xs text-gray-400">加载中...</view>
<view v-else-if="!inboundList.length" class="py-6 text-center text-xs text-gray-400">
暂无入库单
</view>
<view
v-for="row in inboundList"
v-else
:key="row.inboundId"
class="mb-3 rounded-xl border border-gray-100 p-3 last:mb-0"
>
<view class="flex items-center justify-between">
<text class="font-medium text-gray-700">{{ row.inboundNo || `#${row.inboundId}` }}</text>
<text :class="row.status === 'DRAFT' ? 'text-orange-500' : 'text-green-500'" class="text-xs">
{{ row.status === "DRAFT" ? "草稿" : "已确认" }}
</text>
</view>
<text class="mt-1 block text-xs text-gray-500">
仓库:{{ warehouseName(row.warehouseId) }} · 托盘:{{ row.items?.length || 0 }} 个
</text>
<view v-if="row.status === 'DRAFT'" class="mt-3 flex gap-2">
<button
v-if="canEdit"
class="flex-1 rounded-lg bg-blue-50 py-2 text-xs text-blue-600"
size="mini"
:disabled="operationPending"
@click="startEditDraft(row)"
>
编辑
</button>
<button
v-if="canConfirm"
class="flex-1 rounded-lg bg-green-50 py-2 text-xs text-green-600"
size="mini"
:disabled="operationPending"
@click="confirmDraft(row)"
>
{{ confirmLoading ? "确认中" : "确认" }}
</button>
</view>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, getCurrentInstance, reactive, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PalletScanInput from "@/components/business/PalletScanInput.vue";
import TestBatchBanner from "@/components/business/TestBatchBanner.vue";
import {
addInbound,
confirmInbound,
getInbound,
getInboundWarehouseOptions,
listInbound,
scanInboundPallet,
updateInbound,
} from "@/api/business/inbound";
import { createIdempotencyKey } from "@/utils/palletScan";
const { proxy } = getCurrentInstance();
const inboundList = ref([]);
const warehouseOptions = ref([]);
const scannedPallets = ref([]);
const editorVisible = ref(false);
const editing = ref(false);
const loading = ref(false);
const optionLoading = ref(false);
const detailLoading = ref(false);
const scanLoading = ref(false);
const submitLoading = ref(false);
const confirmLoading = ref(false);
const listError = ref("");
const formError = ref("");
const scanError = ref("");
const confirmError = ref("");
const form = reactive({ inboundId: null, warehouseId: null });
const confirmState = reactive({ inboundId: null, key: "" });
let listGeneration = 0;
let scanGeneration = 0;
const canPage = computed(() =>
proxy.$auth.hasPermiOr([
"business:inbound:list",
"business:inbound:query",
"business:inbound:add",
"business:inbound:edit",
"business:inbound:confirm",
]),
);
const canList = computed(() => proxy.$auth.hasPermi("business:inbound:list"));
const canDraft = computed(() =>
proxy.$auth.hasPermiAnd(["business:inbound:query", "business:inbound:add"]),
);
const canEdit = computed(() =>
proxy.$auth.hasPermiAnd(["business:inbound:query", "business:inbound:edit"]),
);
const canConfirm = computed(() =>
proxy.$auth.hasPermi("business:inbound:confirm"),
);
const canSaveDraft = computed(() => (editing.value ? canEdit.value : canDraft.value));
const operationPending = computed(
() =>
submitLoading.value ||
confirmLoading.value ||
detailLoading.value,
);
const warehouseIndex = computed(() => {
const index = warehouseOptions.value.findIndex(
(item) => item.id === form.warehouseId,
);
return index >= 0 ? index : 0;
});
const selectedWarehouseName = computed(
() => warehouseOptions.value.find((item) => item.id === form.warehouseId)?.name || "",
);
function errorMessage(error, fallback) {
return error?.response?.data?.msg || error?.message || fallback;
}
function warehouseName(id) {
return warehouseOptions.value.find((item) => item.id === id)?.name || `#${id || "-"}`;
}
function resetEditor() {
scanGeneration += 1;
editorVisible.value = false;
editing.value = false;
form.inboundId = null;
form.warehouseId = null;
scannedPallets.value = [];
detailLoading.value = false;
scanLoading.value = false;
formError.value = "";
scanError.value = "";
}
function loadInboundList() {
if (!canList.value) return;
const generation = ++listGeneration;
loading.value = true;
listError.value = "";
listInbound({ pageNum: 1, pageSize: 20 })
.then((response) => {
if (generation !== listGeneration) return;
inboundList.value = Array.isArray(response.rows) ? response.rows : [];
})
.catch((error) => {
if (generation !== listGeneration) return;
inboundList.value = [];
listError.value = errorMessage(error, "入库单列表加载失败,请稍后重试");
})
.finally(() => {
if (generation === listGeneration) loading.value = false;
});
}
function loadWarehouseOptions() {
if (!proxy.$auth.hasPermi("business:inbound:query")) return;
optionLoading.value = true;
getInboundWarehouseOptions()
.then((response) => {
warehouseOptions.value = Array.isArray(response.data) ? response.data : [];
})
.catch((error) => {
warehouseOptions.value = [];
formError.value = errorMessage(error, "仓库选项加载失败,请稍后重试");
})
.finally(() => {
optionLoading.value = false;
});
}
function startNewDraft() {
if (!canDraft.value || operationPending.value) return;
resetEditor();
editorVisible.value = true;
loadWarehouseOptions();
}
function startEditDraft(row) {
if (!canEdit.value || row.status !== "DRAFT" || operationPending.value) return;
resetEditor();
editorVisible.value = true;
editing.value = true;
form.inboundId = row.inboundId;
loadWarehouseOptions();
detailLoading.value = true;
getInbound(row.inboundId)
.then((response) => {
const detail = response.data;
if (!detail || detail.status !== "DRAFT") {
formError.value = "该入库单已不是草稿状态,不能编辑";
return;
}
form.warehouseId = detail.warehouseId;
scannedPallets.value = (Array.isArray(detail.items) ? detail.items : []).map(
(item) => ({
palletId: item.palletId,
palletCode: item.palletCode || `#${item.palletId}`,
flowState: item.flowState || "UNSTOCKED",
}),
);
})
.catch((error) => {
formError.value = errorMessage(error, "入库单详情加载失败,请稍后重试");
})
.finally(() => {
detailLoading.value = false;
});
}
function cancelEditor() {
if (operationPending.value) return;
resetEditor();
}
function handleWarehouseChange(event) {
const option = warehouseOptions.value[Number(event.detail.value)];
if (!option || option.id === form.warehouseId) return;
form.warehouseId = option.id;
scannedPallets.value = [];
scanError.value = "";
scanGeneration += 1;
}
function handleInboundScan(qrToken) {
if (!form.warehouseId || operationPending.value || scanLoading.value) {
scanError.value = "请先选择入库仓库";
return;
}
const generation = ++scanGeneration;
scanLoading.value = true;
scanError.value = "";
scanInboundPallet(qrToken, { warehouseId: form.warehouseId })
.then((response) => {
if (generation !== scanGeneration) return;
const pallet = response.data;
if (pallet?.flowState !== "UNSTOCKED") {
scanError.value = "该托盘不是未入库状态,不能加入入库草稿";
return;
}
if (scannedPallets.value.some((item) => item.palletId === pallet.palletId)) {
proxy.$modal.msg("该托盘已在当前草稿中");
return;
}
scannedPallets.value.push({
palletId: pallet.palletId,
palletCode: pallet.palletCode || `#${pallet.palletId}`,
flowState: pallet.flowState,
});
})
.catch((error) => {
if (generation === scanGeneration) {
scanError.value = errorMessage(error, "托盘扫码校验失败,请检查后重试");
}
})
.finally(() => {
if (generation === scanGeneration) scanLoading.value = false;
});
}
function handleScanInvalid(message) {
scanError.value = message;
}
function handleScanDuplicate() {
proxy.$modal.msg("扫码过快,请勿重复扫描");
}
function removeScannedPallet(palletId) {
if (operationPending.value) return;
scannedPallets.value = scannedPallets.value.filter(
(item) => item.palletId !== palletId,
);
}
function saveDraft() {
if (!canSaveDraft.value || operationPending.value || scanLoading.value) return;
if (!form.warehouseId) {
formError.value = "请选择入库仓库";
return;
}
if (!scannedPallets.value.length) {
formError.value = "请至少扫描一个托盘";
return;
}
submitLoading.value = true;
formError.value = "";
const payload = {
warehouseId: form.warehouseId,
palletIds: scannedPallets.value.map((item) => item.palletId),
};
const submitRequest = editing.value
? updateInbound({ ...payload, inboundId: form.inboundId })
: addInbound(payload);
submitRequest
.then((response) => {
proxy.$modal.msgSuccess(response.msg || "入库草稿保存成功");
resetEditor();
loadInboundList();
})
.catch((error) => {
formError.value = errorMessage(error, "入库草稿保存失败,请根据提示修正后重试");
})
.finally(() => {
submitLoading.value = false;
});
}
function askConfirm(content) {
return new Promise((resolve) => {
uni.showModal({
title: "系统提示",
content,
cancelText: "取消",
confirmText: "确定",
success: (result) => resolve(Boolean(result.confirm)),
});
});
}
function ensureConfirmIdempotencyKey(inboundId) {
if (confirmState.inboundId !== inboundId) {
confirmState.inboundId = inboundId;
confirmState.key = "";
}
if (!confirmState.key) confirmState.key = createIdempotencyKey();
return confirmState.key;
}
function clearConfirmIdempotency() {
confirmState.inboundId = null;
confirmState.key = "";
}
async function confirmDraft(row) {
if (!canConfirm.value || row.status !== "DRAFT" || operationPending.value) return;
if (!(await askConfirm(`确认入库单“${row.inboundNo || `#${row.inboundId}`}”?`))) return;
confirmLoading.value = true;
confirmError.value = "";
try {
await confirmInbound(row.inboundId, {
idempotencyKey: ensureConfirmIdempotencyKey(row.inboundId),
});
clearConfirmIdempotency();
proxy.$modal.msgSuccess("入库确认成功");
loadInboundList();
} catch (error) {
confirmError.value = `${errorMessage(error, "入库确认失败")};再次确认将复用本次幂等键`;
} finally {
confirmLoading.value = false;
}
}
onShow(() => {
loadInboundList();
});
</script>
@@ -0,0 +1,560 @@
<template>
<view class="min-h-screen bg-gray-50">
<scroll-view scroll-y class="h-screen">
<view class="space-y-4 p-4 pb-24">
<view>
<text class="block text-xl font-bold text-gray-800">退回仓库</text>
<text class="mt-1 block text-xs text-gray-500">
客户现场发起退回申请,仓库逐托扫描后确认收货
</text>
</view>
<TestBatchBanner />
<view v-if="!canPage" class="rounded-2xl bg-white p-6 text-center shadow-sm">
<text class="text-sm text-gray-500">当前账号没有退回操作权限</text>
</view>
<template v-else>
<view v-if="canRequest" class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">发起退回申请</text>
<button class="text-xs text-gray-500" size="mini" :disabled="requestPending" @click="resetRequestOperation">
清空
</button>
</view>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">目标仓库</text>
<picker
:range="warehouseOptions"
range-key="name"
:value="warehouseIndex"
:disabled="optionLoading || requestPending"
@change="handleWarehouseChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedWarehouseName || "请选择目标仓库" }}
</view>
</picker>
</view>
<PalletScanInput
:disabled="!requestForm.targetWarehouseId || requestPending"
:loading="scanLoading.request"
@scan="handleRequestScan"
@invalid="handleRequestScanInvalid"
@duplicate="handleScanDuplicate"
/>
<text class="mt-2 block text-xs text-gray-400">
同一申请只能包含同一客户现场的托盘;扫码成功后托盘由服务端冻结。
</text>
<text v-if="requestError" class="mt-2 block text-xs text-red-500">{{ requestError }}</text>
<view v-if="requestScannedPallets.length" class="mt-3 space-y-2">
<view
v-for="pallet in requestScannedPallets"
:key="pallet.palletId"
class="flex items-center justify-between rounded-xl bg-blue-50 px-3 py-2"
>
<view>
<text class="block text-sm text-gray-700">{{ pallet.palletCode || `#${pallet.palletId}` }}</text>
<text class="block text-xs text-gray-500">现场 #{{ pallet.siteId }} · 剩余 {{ pallet.remainingPackages }} 包</text>
</view>
<button class="text-xs text-red-500" size="mini" :disabled="requestPending" @click="removeRequestPallet(pallet.palletId)">
移除
</button>
</view>
</view>
<text v-if="requestForm.sourceSiteId" class="mt-3 block text-xs text-gray-500">
来源现场:#{{ requestForm.sourceSiteId }} · {{ requestScannedPallets.length }} 个托盘
</text>
<button
class="mt-4 w-full rounded-xl bg-blue-500 py-3 text-sm text-white active:opacity-80 disabled:bg-gray-300"
:disabled="!requestScannedPallets.length || requestPending || scanLoading.request"
@click="submitReturnRequest"
>
{{ requestSubmitLoading ? "申请中" : "提交退回申请" }}
</button>
</view>
<view v-if="canConfirm" class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">仓库确认退回</text>
<text class="text-xs text-gray-400">必须完整扫描单据托盘</text>
</view>
<picker
:range="requestedReturns"
range-key="returnNo"
:value="requestedReturnIndex"
:disabled="confirmPending || detailLoading"
@change="handleConfirmSelection"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedReturnLabel || "请选择待确认退回单" }}
</view>
</picker>
<text v-if="confirmError" class="mt-2 block text-xs text-red-500">{{ confirmError }}</text>
<view v-if="confirmExpectedRows.length" class="mt-3 rounded-xl bg-orange-50 p-3">
<text class="block text-xs text-gray-500">
预期托盘 {{ confirmExpectedRows.length }} 个,已扫描 {{ confirmScannedPallets.length }} 个
</text>
<view class="mt-2 space-y-1">
<text v-for="row in confirmExpectedRows" :key="row.palletId" class="block text-xs text-gray-600">
{{ row.palletCode || `#${row.palletId}` }}
<text v-if="isConfirmPalletScanned(row.palletId)" class="text-green-600"> · 已扫描</text>
</text>
</view>
</view>
<PalletScanInput
class="mt-3"
:disabled="!confirmForm.returnId || !confirmExpectedRows.length || confirmPending || detailLoading"
:loading="scanLoading.confirm"
@scan="handleConfirmScan"
@invalid="handleConfirmScanInvalid"
@duplicate="handleScanDuplicate"
/>
<button
class="mt-4 w-full rounded-xl bg-orange-500 py-3 text-sm text-white active:opacity-80 disabled:bg-gray-300"
:disabled="!confirmForm.returnId || !confirmExpectedRows.length || confirmPending || scanLoading.confirm || detailLoading"
@click="submitReturnConfirm"
>
{{ confirmSubmitLoading ? "确认中" : "确认退回收货" }}
</button>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">退回单</text>
<button class="text-xs text-blue-500" size="mini" :disabled="loading" @click="loadReturnList">
刷新
</button>
</view>
<text v-if="listError" class="mb-3 block text-xs text-red-500">{{ listError }}</text>
<view v-if="loading" class="py-6 text-center text-xs text-gray-400">加载中...</view>
<view v-else-if="!returnList.length" class="py-6 text-center text-xs text-gray-400">
暂无退回单
</view>
<view
v-for="row in returnList"
v-else
:key="row.returnId"
class="mb-3 rounded-xl border border-gray-100 p-3 last:mb-0"
>
<view class="flex items-center justify-between">
<text class="font-medium text-gray-700">{{ row.returnNo || `#${row.returnId}` }}</text>
<text :class="row.status === 'REQUESTED' ? 'text-orange-500' : 'text-green-500'" class="text-xs">
{{ row.status === "REQUESTED" ? "待确认" : "已确认" }}
</text>
</view>
<text class="mt-1 block text-xs text-gray-500">
现场 #{{ row.sourceSiteId }} → {{ warehouseName(row.targetWarehouseId) }} · 托盘 {{ row.items?.length || 0 }} 个
</text>
<button
v-if="row.status === 'REQUESTED' && canConfirm"
class="mt-3 w-full rounded-lg bg-orange-50 py-2 text-xs text-orange-600"
size="mini"
:disabled="confirmPending"
@click="selectReturnRow(row)"
>
选择并确认
</button>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, getCurrentInstance, reactive, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PalletScanInput from "@/components/business/PalletScanInput.vue";
import TestBatchBanner from "@/components/business/TestBatchBanner.vue";
import {
confirmReturn,
getReturn,
getReturnWarehouseOptions,
listReturn,
requestReturn,
scanReturnPallet,
} from "@/api/business/return";
import { createIdempotencyKey } from "@/utils/palletScan";
const { proxy } = getCurrentInstance();
const returnList = ref([]);
const warehouseOptions = ref([]);
const requestScannedPallets = ref([]);
const confirmExpectedRows = ref([]);
const confirmExpectedPalletIds = ref([]);
const confirmScannedPallets = ref([]);
const loading = ref(false);
const optionLoading = ref(false);
const detailLoading = ref(false);
const listError = ref("");
const requestError = ref("");
const confirmError = ref("");
const scanLoading = reactive({ request: false, confirm: false });
const requestSubmitLoading = ref(false);
const confirmSubmitLoading = ref(false);
const requestIdempotencyKey = ref("");
const confirmIdempotencyKey = ref("");
const requestForm = reactive({ sourceSiteId: null, targetWarehouseId: null });
const confirmForm = reactive({ returnId: null });
let listGeneration = 0;
let requestScanGeneration = 0;
let confirmScanGeneration = 0;
let detailGeneration = 0;
let requestSession = 0;
let confirmSession = 0;
const canPage = computed(() =>
proxy.$auth.hasPermiOr([
"business:return:list",
"business:return:query",
"business:return:request",
"business:return:confirm",
]),
);
const canList = computed(() => proxy.$auth.hasPermi("business:return:list"));
const canRequest = computed(() =>
proxy.$auth.hasPermiAnd(["business:return:query", "business:return:request"]),
);
const canConfirm = computed(() =>
proxy.$auth.hasPermiAnd(["business:return:query", "business:return:confirm"]),
);
const requestPending = computed(() => requestSubmitLoading.value);
const confirmPending = computed(() => confirmSubmitLoading.value);
const warehouseIndex = computed(() => {
const index = warehouseOptions.value.findIndex(
(item) => item.id === requestForm.targetWarehouseId,
);
return index >= 0 ? index : 0;
});
const selectedWarehouseName = computed(
() => warehouseOptions.value.find((item) => item.id === requestForm.targetWarehouseId)?.name || "",
);
const requestedReturns = computed(() =>
returnList.value.filter((item) => item.status === "REQUESTED"),
);
const requestedReturnIndex = computed(() => {
const index = requestedReturns.value.findIndex(
(item) => item.returnId === confirmForm.returnId,
);
return index >= 0 ? index : 0;
});
const selectedReturnLabel = computed(() => {
const item = requestedReturns.value.find((row) => row.returnId === confirmForm.returnId);
return item ? `${item.returnNo || `#${item.returnId}`} · 现场 #${item.sourceSiteId}` : "";
});
function errorMessage(error, fallback) {
return error?.response?.data?.msg || error?.message || fallback;
}
function warehouseName(id) {
return warehouseOptions.value.find((item) => item.id === id)?.name || `仓库 #${id || "-"}`;
}
function loadReturnList() {
if (!canList.value) return;
const generation = ++listGeneration;
loading.value = true;
listError.value = "";
listReturn({ pageNum: 1, pageSize: 30 })
.then((response) => {
if (generation !== listGeneration) return;
returnList.value = Array.isArray(response.rows) ? response.rows : [];
})
.catch((error) => {
if (generation !== listGeneration) return;
returnList.value = [];
listError.value = errorMessage(error, "退回单列表加载失败,请稍后重试");
})
.finally(() => {
if (generation === listGeneration) loading.value = false;
});
}
function loadWarehouseOptions() {
if (!proxy.$auth.hasPermi("business:return:query")) return;
optionLoading.value = true;
getReturnWarehouseOptions()
.then((response) => {
warehouseOptions.value = Array.isArray(response.data) ? response.data : [];
})
.catch((error) => {
warehouseOptions.value = [];
requestError.value = errorMessage(error, "目标仓库选项加载失败,请稍后重试");
})
.finally(() => {
optionLoading.value = false;
});
}
function resetRequestOperation() {
requestSession += 1;
requestScanGeneration += 1;
requestForm.sourceSiteId = null;
requestForm.targetWarehouseId = null;
requestScannedPallets.value = [];
requestIdempotencyKey.value = "";
requestError.value = "";
scanLoading.request = false;
}
function handleWarehouseChange(event) {
const option = warehouseOptions.value[Number(event.detail.value)];
if (!option || option.id === requestForm.targetWarehouseId) return;
requestForm.targetWarehouseId = option.id;
requestForm.sourceSiteId = null;
requestScannedPallets.value = [];
requestIdempotencyKey.value = "";
requestError.value = "";
requestScanGeneration += 1;
}
function handleRequestScan(qrToken) {
if (!requestForm.targetWarehouseId || requestPending.value || scanLoading.request) {
requestError.value = "请先选择目标仓库";
return;
}
const session = requestSession;
const generation = ++requestScanGeneration;
scanLoading.request = true;
requestError.value = "";
scanReturnPallet(qrToken, { mode: "request" })
.then((response) => {
if (session !== requestSession || generation !== requestScanGeneration) return;
const pallet = response.data;
if (!pallet?.siteId) {
requestError.value = "该托盘不在客户现场,不能发起退回";
return;
}
if (requestForm.sourceSiteId && pallet.siteId !== requestForm.sourceSiteId) {
requestError.value = "同一退回申请只能包含同一客户现场的托盘";
return;
}
if (requestScannedPallets.value.some((item) => item.palletId === pallet.palletId)) {
proxy.$modal.msg("该托盘已在退回申请中");
return;
}
requestForm.sourceSiteId = requestForm.sourceSiteId || pallet.siteId;
requestScannedPallets.value.push({
palletId: pallet.palletId,
palletCode: pallet.palletCode || `#${pallet.palletId}`,
siteId: pallet.siteId,
remainingPackages: pallet.remainingPackages,
});
requestIdempotencyKey.value = "";
})
.catch((error) => {
if (session === requestSession && generation === requestScanGeneration) {
requestError.value = errorMessage(error, "退回托盘扫码校验失败,请检查后重试");
}
})
.finally(() => {
if (session === requestSession && generation === requestScanGeneration) {
scanLoading.request = false;
}
});
}
function handleRequestScanInvalid(message) {
requestError.value = message;
}
function removeRequestPallet(palletId) {
if (requestPending.value) return;
requestScannedPallets.value = requestScannedPallets.value.filter(
(item) => item.palletId !== palletId,
);
if (!requestScannedPallets.value.length) requestForm.sourceSiteId = null;
requestIdempotencyKey.value = "";
}
function ensureRequestIdempotencyKey() {
if (!requestIdempotencyKey.value) requestIdempotencyKey.value = createIdempotencyKey();
return requestIdempotencyKey.value;
}
async function submitReturnRequest() {
if (requestPending.value || scanLoading.request || !requestScannedPallets.value.length) return;
if (!requestForm.sourceSiteId || !requestForm.targetWarehouseId) {
requestError.value = "请选择目标仓库并扫描退回托盘";
return;
}
requestSubmitLoading.value = true;
requestError.value = "";
try {
await requestReturn({
sourceSiteId: requestForm.sourceSiteId,
targetWarehouseId: requestForm.targetWarehouseId,
palletIds: requestScannedPallets.value.map((item) => item.palletId),
idempotencyKey: ensureRequestIdempotencyKey(),
});
requestIdempotencyKey.value = "";
proxy.$modal.msgSuccess("退回申请已提交");
resetRequestOperation();
loadReturnList();
} catch (error) {
requestError.value = `${errorMessage(error, "退回申请提交失败")};直接重试将复用本次幂等键`;
} finally {
requestSubmitLoading.value = false;
}
}
function resetConfirmOperation() {
confirmSession += 1;
confirmScanGeneration += 1;
detailGeneration += 1;
confirmForm.returnId = null;
confirmExpectedRows.value = [];
confirmExpectedPalletIds.value = [];
confirmScannedPallets.value = [];
confirmIdempotencyKey.value = "";
confirmError.value = "";
detailLoading.value = false;
scanLoading.confirm = false;
}
function handleConfirmSelection(event) {
const row = requestedReturns.value[Number(event.detail.value)];
selectReturnRow(row);
}
function selectReturnRow(row) {
if (!row || row.status !== "REQUESTED" || confirmPending.value) return;
resetConfirmOperation();
const session = confirmSession;
const generation = ++detailGeneration;
confirmForm.returnId = row.returnId;
detailLoading.value = true;
getReturn(row.returnId)
.then((response) => {
if (session !== confirmSession || generation !== detailGeneration) return;
const detail = response.data;
if (!detail || detail.status !== "REQUESTED") {
confirmError.value = "该退回单已不是待确认状态";
return;
}
confirmExpectedRows.value = (Array.isArray(detail.items) ? detail.items : []).map(
(item) => ({
palletId: item.palletId,
palletCode: item.palletCode || `#${item.palletId}`,
}),
);
confirmExpectedPalletIds.value = confirmExpectedRows.value.map((item) => item.palletId);
if (!confirmExpectedPalletIds.value.length) confirmError.value = "该退回单没有托盘明细";
})
.catch((error) => {
if (session === confirmSession && generation === detailGeneration) {
confirmError.value = errorMessage(error, "退回单详情加载失败,请稍后重试");
}
})
.finally(() => {
if (session === confirmSession && generation === detailGeneration) {
detailLoading.value = false;
}
});
}
function handleConfirmScan(qrToken) {
if (!confirmForm.returnId || !confirmExpectedPalletIds.value.length || confirmPending.value || scanLoading.confirm) return;
const session = confirmSession;
const generation = ++confirmScanGeneration;
scanLoading.confirm = true;
confirmError.value = "";
scanReturnPallet(qrToken, { mode: "confirm", returnId: confirmForm.returnId })
.then((response) => {
if (session !== confirmSession || generation !== confirmScanGeneration) return;
const pallet = response.data;
if (!confirmExpectedPalletIds.value.includes(pallet.palletId)) {
confirmError.value = "该托盘不属于所选退回单";
return;
}
if (confirmScannedPallets.value.some((item) => item.palletId === pallet.palletId)) {
proxy.$modal.msg("该托盘已完成扫码");
return;
}
confirmScannedPallets.value.push({
palletId: pallet.palletId,
palletCode: pallet.palletCode || `#${pallet.palletId}`,
});
confirmIdempotencyKey.value = "";
})
.catch((error) => {
if (session === confirmSession && generation === confirmScanGeneration) {
confirmError.value = errorMessage(error, "到仓托盘扫码校验失败,请检查后重试");
}
})
.finally(() => {
if (session === confirmSession && generation === confirmScanGeneration) {
scanLoading.confirm = false;
}
});
}
function handleConfirmScanInvalid(message) {
confirmError.value = message;
}
function handleScanDuplicate() {
proxy.$modal.msg("扫码过快,请勿重复扫描");
}
function isConfirmPalletScanned(palletId) {
return confirmScannedPallets.value.some((item) => item.palletId === palletId);
}
function sameIdSet(left, right) {
if (left.length !== right.length) return false;
const leftSet = new Set(left);
const rightSet = new Set(right);
return (
leftSet.size === left.length &&
rightSet.size === right.length &&
right.every((id) => leftSet.has(id))
);
}
function ensureConfirmIdempotencyKey(returnId) {
if (!confirmIdempotencyKey.value) confirmIdempotencyKey.value = createIdempotencyKey();
return confirmIdempotencyKey.value;
}
async function submitReturnConfirm() {
if (confirmPending.value || detailLoading.value || scanLoading.confirm) return;
const returnId = confirmForm.returnId;
const expectedIds = [...confirmExpectedPalletIds.value];
const scannedIds = confirmScannedPallets.value.map((item) => item.palletId);
if (!returnId || !sameIdSet(expectedIds, scannedIds)) {
confirmError.value = "必须逐个扫描并完整匹配退回单全部托盘";
return;
}
confirmSubmitLoading.value = true;
confirmError.value = "";
try {
const latest = (await getReturn(returnId)).data;
const latestIds = (Array.isArray(latest.items) ? latest.items : []).map((item) => item.palletId);
if (latest.status !== "REQUESTED" || !sameIdSet(latestIds, scannedIds)) {
confirmError.value = "退回单状态或托盘明细已变化,请重新选择并扫码";
return;
}
await confirmReturn(returnId, {
scannedPalletIds: scannedIds,
idempotencyKey: ensureConfirmIdempotencyKey(returnId),
});
confirmIdempotencyKey.value = "";
proxy.$modal.msgSuccess("退回确认成功");
resetConfirmOperation();
loadReturnList();
} catch (error) {
confirmError.value = `${errorMessage(error, "退回确认失败")};直接重试将复用本次幂等键`;
} finally {
confirmSubmitLoading.value = false;
}
}
onShow(() => {
loadReturnList();
loadWarehouseOptions();
});
</script>
@@ -0,0 +1,549 @@
<template>
<view class="min-h-screen bg-gray-50">
<scroll-view scroll-y class="h-screen">
<view class="space-y-4 p-4 pb-24">
<view class="flex items-center justify-between">
<view>
<text class="block text-xl font-bold text-gray-800">发货出库</text>
<text class="mt-1 block text-xs text-gray-500">
选择来源仓库和目标现场,扫码创建整托发货单
</text>
</view>
<button
v-if="canDraft"
class="rounded-lg bg-orange-500 px-3 py-2 text-xs text-white active:opacity-80"
size="mini"
:disabled="operationPending"
@click="startNewDraft"
>
新建草稿
</button>
</view>
<TestBatchBanner />
<view v-if="!canPage" class="rounded-2xl bg-white p-6 text-center shadow-sm">
<text class="text-sm text-gray-500">当前账号没有发货操作权限</text>
</view>
<template v-else>
<view v-if="editorVisible" class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-4 flex items-center justify-between">
<text class="font-bold text-gray-800">
{{ editing ? "编辑发货草稿" : "新建发货草稿" }}
</text>
<text class="text-xs text-gray-400">托盘数量 {{ scannedPallets.length }}</text>
</view>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">来源仓库</text>
<picker
:range="warehouseOptions"
range-key="name"
:value="warehouseIndex"
:disabled="optionLoading || detailLoading || operationPending"
@change="handleWarehouseChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedWarehouseName || "请选择来源仓库" }}
</view>
</picker>
</view>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">目标客户现场</text>
<picker
:range="siteOptions"
range-key="name"
:value="siteIndex"
:disabled="optionLoading || detailLoading || operationPending"
@change="handleSiteChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedSiteName || "请选择目标现场" }}
</view>
</picker>
</view>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">连续扫码</text>
<PalletScanInput
:disabled="!form.sourceWarehouseId || !form.targetSiteId || detailLoading || operationPending"
:loading="scanLoading"
@scan="handleShipmentScan"
@invalid="handleScanInvalid"
@duplicate="handleScanDuplicate"
/>
<text class="mt-2 block text-xs text-gray-400">
仅接受来源仓库内有剩余包数的 FILLED_IN_WAREHOUSE 托盘。
</text>
</view>
<text v-if="scanError" class="mb-3 block text-xs text-red-500">{{ scanError }}</text>
<text v-if="formError" class="mb-3 block text-xs text-red-500">{{ formError }}</text>
<view v-if="scannedPallets.length" class="mb-4 space-y-2">
<view
v-for="pallet in scannedPallets"
:key="pallet.palletId"
class="rounded-xl bg-orange-50 px-3 py-2"
>
<view class="flex items-center justify-between">
<view>
<text class="block text-sm font-medium text-gray-700">
{{ pallet.palletCode || `#${pallet.palletId}` }}
</text>
<text class="block text-xs text-gray-500">
{{ pallet.strainName || pallet.strainCode || "未提供菌种" }} · 剩余 {{ pallet.remainingPackages }} 包
</text>
</view>
<button
class="text-xs text-red-500"
size="mini"
:disabled="operationPending || detailLoading"
@click="removeScannedPallet(pallet.palletId)"
>
移除
</button>
</view>
<text class="mt-1 block text-xs text-gray-400">
批次:{{ pallet.batchNo || "—" }}
</text>
</view>
</view>
<view class="flex gap-3">
<button
class="flex-1 rounded-xl bg-orange-500 py-3 text-sm text-white active:opacity-80 disabled:bg-gray-300"
:disabled="!canSaveDraft || operationPending || scanLoading || detailLoading"
@click="saveDraft"
>
{{ submitLoading ? "保存中" : editing ? "保存修改" : "保存草稿" }}
</button>
<button
class="flex-1 rounded-xl bg-gray-100 py-3 text-sm text-gray-600 active:opacity-80"
:disabled="operationPending"
@click="cancelEditor"
>
取消
</button>
</view>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">发货单</text>
<button
class="text-xs text-blue-500"
size="mini"
:disabled="loading || operationPending"
@click="loadShipmentList"
>
刷新
</button>
</view>
<text v-if="listError" class="mb-3 block text-xs text-red-500">{{ listError }}</text>
<text v-if="confirmError" class="mb-3 block text-xs text-red-500">{{ confirmError }}</text>
<view v-if="loading" class="py-6 text-center text-xs text-gray-400">加载中...</view>
<view v-else-if="!shipmentList.length" class="py-6 text-center text-xs text-gray-400">
暂无发货单
</view>
<view
v-for="row in shipmentList"
v-else
:key="row.shipmentId"
class="mb-3 rounded-xl border border-gray-100 p-3 last:mb-0"
>
<view class="flex items-center justify-between">
<text class="font-medium text-gray-700">{{ row.shipmentNo || `#${row.shipmentId}` }}</text>
<text :class="row.status === 'DRAFT' ? 'text-orange-500' : 'text-green-500'" class="text-xs">
{{ row.status === "DRAFT" ? "草稿" : "已确认" }}
</text>
</view>
<text class="mt-1 block text-xs text-gray-500">
{{ warehouseName(row.sourceWarehouseId) }} → {{ siteName(row.targetSiteId) }} · 托盘 {{ row.items?.length || 0 }} 个
</text>
<view v-if="row.status === 'DRAFT'" class="mt-3 flex gap-2">
<button
v-if="canEdit"
class="flex-1 rounded-lg bg-blue-50 py-2 text-xs text-blue-600"
size="mini"
:disabled="operationPending"
@click="startEditDraft(row)"
>
编辑
</button>
<button
v-if="canConfirm"
class="flex-1 rounded-lg bg-green-50 py-2 text-xs text-green-600"
size="mini"
:disabled="operationPending"
@click="confirmDraft(row)"
>
{{ confirmLoading ? "确认中" : "确认" }}
</button>
</view>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, getCurrentInstance, reactive, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PalletScanInput from "@/components/business/PalletScanInput.vue";
import TestBatchBanner from "@/components/business/TestBatchBanner.vue";
import {
addShipment,
confirmShipment,
getShipment,
getShipmentSiteOptions,
getShipmentWarehouseOptions,
listShipment,
scanShipmentPallet,
updateShipment,
} from "@/api/business/shipment";
import { createIdempotencyKey } from "@/utils/palletScan";
const { proxy } = getCurrentInstance();
const shipmentList = ref([]);
const warehouseOptions = ref([]);
const siteOptions = ref([]);
const scannedPallets = ref([]);
const editorVisible = ref(false);
const editing = ref(false);
const loading = ref(false);
const optionLoading = ref(false);
const detailLoading = ref(false);
const scanLoading = ref(false);
const submitLoading = ref(false);
const confirmLoading = ref(false);
const listError = ref("");
const formError = ref("");
const scanError = ref("");
const confirmError = ref("");
const form = reactive({ shipmentId: null, sourceWarehouseId: null, targetSiteId: null });
const confirmState = reactive({ shipmentId: null, key: "" });
let listGeneration = 0;
let scanGeneration = 0;
const canPage = computed(() =>
proxy.$auth.hasPermiOr([
"business:shipment:list",
"business:shipment:query",
"business:shipment:add",
"business:shipment:edit",
"business:shipment:confirm",
]),
);
const canList = computed(() => proxy.$auth.hasPermi("business:shipment:list"));
const canDraft = computed(() =>
proxy.$auth.hasPermiAnd(["business:shipment:query", "business:shipment:add"]),
);
const canEdit = computed(() =>
proxy.$auth.hasPermiAnd(["business:shipment:query", "business:shipment:edit"]),
);
const canConfirm = computed(() => proxy.$auth.hasPermi("business:shipment:confirm"));
const canSaveDraft = computed(() => (editing.value ? canEdit.value : canDraft.value));
const operationPending = computed(
() =>
submitLoading.value ||
confirmLoading.value ||
detailLoading.value,
);
const warehouseIndex = computed(() => {
const index = warehouseOptions.value.findIndex(
(item) => item.id === form.sourceWarehouseId,
);
return index >= 0 ? index : 0;
});
const siteIndex = computed(() => {
const index = siteOptions.value.findIndex((item) => item.id === form.targetSiteId);
return index >= 0 ? index : 0;
});
const selectedWarehouseName = computed(
() => warehouseOptions.value.find((item) => item.id === form.sourceWarehouseId)?.name || "",
);
const selectedSiteName = computed(
() => siteOptions.value.find((item) => item.id === form.targetSiteId)?.name || "",
);
function errorMessage(error, fallback) {
return error?.response?.data?.msg || error?.message || fallback;
}
function warehouseName(id) {
return warehouseOptions.value.find((item) => item.id === id)?.name || `仓库 #${id || "-"}`;
}
function siteName(id) {
return siteOptions.value.find((item) => item.id === id)?.name || `现场 #${id || "-"}`;
}
function resetEditor() {
scanGeneration += 1;
editorVisible.value = false;
editing.value = false;
form.shipmentId = null;
form.sourceWarehouseId = null;
form.targetSiteId = null;
scannedPallets.value = [];
detailLoading.value = false;
scanLoading.value = false;
formError.value = "";
scanError.value = "";
}
function loadShipmentList() {
if (!canList.value) return;
const generation = ++listGeneration;
loading.value = true;
listError.value = "";
listShipment({ pageNum: 1, pageSize: 20 })
.then((response) => {
if (generation !== listGeneration) return;
shipmentList.value = Array.isArray(response.rows) ? response.rows : [];
})
.catch((error) => {
if (generation !== listGeneration) return;
shipmentList.value = [];
listError.value = errorMessage(error, "发货单列表加载失败,请稍后重试");
})
.finally(() => {
if (generation === listGeneration) loading.value = false;
});
}
function loadOptions() {
if (!proxy.$auth.hasPermi("business:shipment:query")) return;
optionLoading.value = true;
Promise.all([getShipmentWarehouseOptions(), getShipmentSiteOptions()])
.then(([warehouseResponse, siteResponse]) => {
warehouseOptions.value = Array.isArray(warehouseResponse.data)
? warehouseResponse.data
: [];
siteOptions.value = Array.isArray(siteResponse.data) ? siteResponse.data : [];
})
.catch((error) => {
warehouseOptions.value = [];
siteOptions.value = [];
formError.value = errorMessage(error, "仓库或现场选项加载失败,请稍后重试");
})
.finally(() => {
optionLoading.value = false;
});
}
function startNewDraft() {
if (!canDraft.value || operationPending.value) return;
resetEditor();
editorVisible.value = true;
loadOptions();
}
function startEditDraft(row) {
if (!canEdit.value || row.status !== "DRAFT" || operationPending.value) return;
resetEditor();
editorVisible.value = true;
editing.value = true;
form.shipmentId = row.shipmentId;
loadOptions();
detailLoading.value = true;
getShipment(row.shipmentId)
.then((response) => {
const detail = response.data;
if (!detail || detail.status !== "DRAFT") {
formError.value = "该发货单已不是草稿状态,不能编辑";
return;
}
form.sourceWarehouseId = detail.sourceWarehouseId;
form.targetSiteId = detail.targetSiteId;
scannedPallets.value = (Array.isArray(detail.items) ? detail.items : []).map(
(item) => ({
palletId: item.palletId,
palletCode: item.palletCode || `#${item.palletId}`,
strainName: item.strainName || item.strainCode,
batchNo: item.batchNo,
remainingPackages: item.remainingPackages ?? item.packageQty ?? 0,
}),
);
})
.catch((error) => {
formError.value = errorMessage(error, "发货单详情加载失败,请稍后重试");
})
.finally(() => {
detailLoading.value = false;
});
}
function cancelEditor() {
if (operationPending.value) return;
resetEditor();
}
function clearScannedPallets() {
scannedPallets.value = [];
scanError.value = "";
scanGeneration += 1;
}
function handleWarehouseChange(event) {
const option = warehouseOptions.value[Number(event.detail.value)];
if (!option || option.id === form.sourceWarehouseId) return;
form.sourceWarehouseId = option.id;
clearScannedPallets();
}
function handleSiteChange(event) {
const option = siteOptions.value[Number(event.detail.value)];
if (!option || option.id === form.targetSiteId) return;
form.targetSiteId = option.id;
clearScannedPallets();
}
function handleShipmentScan(qrToken) {
if (
!form.sourceWarehouseId ||
!form.targetSiteId ||
operationPending.value ||
scanLoading.value
) {
scanError.value = "请先选择来源仓库和目标现场";
return;
}
const generation = ++scanGeneration;
scanLoading.value = true;
scanError.value = "";
scanShipmentPallet(qrToken, {
sourceWarehouseId: form.sourceWarehouseId,
targetSiteId: form.targetSiteId,
})
.then((response) => {
if (generation !== scanGeneration) return;
const pallet = response.data;
if (pallet?.flowState !== "FILLED_IN_WAREHOUSE" || pallet.remainingPackages <= 0) {
scanError.value = "该托盘不是来源仓库内的有料托盘,不能发货";
return;
}
if (scannedPallets.value.some((item) => item.palletId === pallet.palletId)) {
proxy.$modal.msg("该托盘已在当前发货草稿中");
return;
}
scannedPallets.value.push({
palletId: pallet.palletId,
palletCode: pallet.palletCode || `#${pallet.palletId}`,
strainName: pallet.strainName || pallet.strainCode,
batchNo: pallet.batchNo,
remainingPackages: pallet.remainingPackages,
});
})
.catch((error) => {
if (generation === scanGeneration) {
scanError.value = errorMessage(error, "托盘扫码校验失败,请检查后重试");
}
})
.finally(() => {
if (generation === scanGeneration) scanLoading.value = false;
});
}
function handleScanInvalid(message) {
scanError.value = message;
}
function handleScanDuplicate() {
proxy.$modal.msg("扫码过快,请勿重复扫描");
}
function removeScannedPallet(palletId) {
if (operationPending.value) return;
scannedPallets.value = scannedPallets.value.filter(
(item) => item.palletId !== palletId,
);
}
function saveDraft() {
if (!canSaveDraft.value || operationPending.value || scanLoading.value) return;
if (!form.sourceWarehouseId || !form.targetSiteId) {
formError.value = "请选择来源仓库和目标现场";
return;
}
if (!scannedPallets.value.length) {
formError.value = "请至少扫描一个有料托盘";
return;
}
submitLoading.value = true;
formError.value = "";
const payload = {
sourceWarehouseId: form.sourceWarehouseId,
targetSiteId: form.targetSiteId,
palletIds: scannedPallets.value.map((item) => item.palletId),
};
const submitRequest = editing.value
? updateShipment({ ...payload, shipmentId: form.shipmentId })
: addShipment(payload);
submitRequest
.then((response) => {
proxy.$modal.msgSuccess(response.msg || "发货草稿保存成功");
resetEditor();
loadShipmentList();
})
.catch((error) => {
formError.value = errorMessage(error, "发货草稿保存失败,请根据提示修正后重试");
})
.finally(() => {
submitLoading.value = false;
});
}
function askConfirm(content) {
return new Promise((resolve) => {
uni.showModal({
title: "系统提示",
content,
cancelText: "取消",
confirmText: "确定",
success: (result) => resolve(Boolean(result.confirm)),
});
});
}
function ensureConfirmIdempotencyKey(shipmentId) {
if (confirmState.shipmentId !== shipmentId) {
confirmState.shipmentId = shipmentId;
confirmState.key = "";
}
if (!confirmState.key) confirmState.key = createIdempotencyKey();
return confirmState.key;
}
function clearConfirmIdempotency() {
confirmState.shipmentId = null;
confirmState.key = "";
}
async function confirmDraft(row) {
if (!canConfirm.value || row.status !== "DRAFT" || operationPending.value) return;
if (!(await askConfirm(`确认发货单“${row.shipmentNo || `#${row.shipmentId}`}”?`))) return;
confirmLoading.value = true;
confirmError.value = "";
try {
await confirmShipment(row.shipmentId, {
idempotencyKey: ensureConfirmIdempotencyKey(row.shipmentId),
});
clearConfirmIdempotency();
proxy.$modal.msgSuccess("发货确认成功");
loadShipmentList();
} catch (error) {
confirmError.value = `${errorMessage(error, "发货确认失败")};再次确认将复用本次幂等键`;
} finally {
confirmLoading.value = false;
}
}
onShow(() => {
loadShipmentList();
});
</script>
@@ -0,0 +1,380 @@
<template>
<view class="min-h-screen bg-gray-50">
<scroll-view scroll-y class="h-screen">
<view class="space-y-4 p-4 pb-24">
<view>
<text class="block text-xl font-bold text-gray-800">客户现场使用</text>
<text class="mt-1 block text-xs text-gray-500">
扫描现场托盘,首次使用绑定产线并记录本次消耗包数
</text>
</view>
<TestBatchBanner />
<view v-if="!canPage" class="rounded-2xl bg-white p-6 text-center shadow-sm">
<text class="text-sm text-gray-500">当前账号没有现场使用权限</text>
</view>
<template v-else>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">扫描待使用托盘</text>
<button class="text-xs text-gray-500" size="mini" :disabled="operationPending" @click="resetUsageOperation">
重新扫描
</button>
</view>
<PalletScanInput
:disabled="operationPending || optionLoading"
:loading="scanLoading"
@scan="handleUsageScan"
@invalid="handleScanInvalid"
@duplicate="handleScanDuplicate"
/>
<text class="mt-2 block text-xs text-gray-400">
仅接受 AT_SITE_UNUSED 或 AT_SITE_PARTIAL 且仍有余量的托盘。
</text>
<text v-if="operationError" class="mt-2 block text-xs text-red-500">{{ operationError }}</text>
<view v-if="scannedPallet" class="mt-4 rounded-xl bg-purple-50 p-3">
<view class="flex items-center justify-between">
<text class="font-medium text-gray-700">
{{ scannedPallet.palletCode || `#${scannedPallet.palletId}` }}
</text>
<text class="text-xs text-purple-600">{{ scannedPallet.flowState }}</text>
</view>
<text class="mt-1 block text-xs text-gray-500">
{{ scannedPallet.strainName || scannedPallet.strainCode || "未提供菌种" }} · 批次 {{ scannedPallet.batchNo || "—" }}
</text>
<text class="mt-1 block text-xs text-gray-500">
当前剩余:{{ scannedPallet.remainingPackages }} 包 · 现场 #{{ scannedPallet.siteId }}
</text>
</view>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<text class="mb-3 block font-bold text-gray-800">使用信息</text>
<view class="mb-3">
<text class="mb-2 block text-xs text-gray-500">使用产线</text>
<view v-if="lineLocked" class="rounded-xl bg-gray-100 px-3 py-3 text-sm text-gray-600">
{{ selectedLineName }}(已由托盘绑定)
</view>
<picker
v-else
:range="lineOptions"
range-key="name"
:value="lineIndex"
:disabled="operationPending || optionLoading || !scannedPallet"
@change="handleLineChange"
>
<view class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700">
{{ selectedLineName || "请选择现场产线" }}
</view>
</picker>
</view>
<view>
<text class="mb-2 block text-xs text-gray-500">本次使用包数</text>
<input
v-model="form.usedPackages"
class="rounded-xl bg-gray-50 px-3 py-3 text-sm text-gray-700"
type="number"
placeholder="请输入正整数"
:disabled="operationPending || !scannedPallet"
@input="markPayloadChanged"
/>
<text v-if="scannedPallet" class="mt-1 block text-xs text-gray-400">
不能超过当前剩余 {{ scannedPallet.remainingPackages }} 包,最终以服务端校验为准
</text>
</view>
<text v-if="submitError" class="mt-3 block text-xs text-red-500">{{ submitError }}</text>
<view v-if="usageResult" class="mt-3 rounded-xl bg-green-50 p-3">
<text class="block text-sm font-medium text-green-700">使用记录已提交</text>
<text class="mt-1 block text-xs text-gray-600">
使用后剩余 {{ usageResult.remainingPackages }} 包 · 状态 {{ usageResult.flowState }}
</text>
</view>
<button
class="mt-4 w-full rounded-xl bg-purple-500 py-3 text-sm text-white active:opacity-80 disabled:bg-gray-300"
:disabled="!canOperate || operationPending || scanLoading || optionLoading || !scannedPallet || !!usageResult"
@click="submitUsage"
>
{{ submitLoading ? "提交中" : "确认使用" }}
</button>
</view>
<view class="rounded-2xl bg-white p-4 shadow-sm">
<view class="mb-3 flex items-center justify-between">
<text class="font-bold text-gray-800">最近使用记录</text>
<button class="text-xs text-blue-500" size="mini" :disabled="loading" @click="loadUsageList">
刷新
</button>
</view>
<text v-if="listError" class="mb-3 block text-xs text-red-500">{{ listError }}</text>
<view v-if="loading" class="py-6 text-center text-xs text-gray-400">加载中...</view>
<view v-else-if="!usageList.length" class="py-6 text-center text-xs text-gray-400">
暂无使用记录
</view>
<view
v-for="row in usageList"
v-else
:key="row.usageId"
class="mb-3 rounded-xl border border-gray-100 p-3 last:mb-0"
>
<text class="block font-medium text-gray-700">{{ row.usageNo || `#${row.usageId}` }}</text>
<text class="mt-1 block text-xs text-gray-500">
托盘 #{{ row.palletId }} · 产线 #{{ row.lineId }} · 使用 {{ row.usedPackages }} 包
</text>
<text class="mt-1 block text-xs text-gray-400">
剩余 {{ row.remainingPackagesAfter }} 包 · {{ row.occurredAt || "—" }}
</text>
</view>
</view>
</template>
</view>
</scroll-view>
</view>
</template>
<script setup>
import { computed, getCurrentInstance, reactive, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import PalletScanInput from "@/components/business/PalletScanInput.vue";
import TestBatchBanner from "@/components/business/TestBatchBanner.vue";
import {
addUsage,
getUsageLineOptions,
listUsage,
scanUsagePallet,
} from "@/api/business/usage";
import { createIdempotencyKey } from "@/utils/palletScan";
const { proxy } = getCurrentInstance();
const usageList = ref([]);
const lineOptions = ref([]);
const scannedPallet = ref(null);
const usageResult = ref(null);
const lineLocked = ref(false);
const loading = ref(false);
const optionLoading = ref(false);
const scanLoading = ref(false);
const submitLoading = ref(false);
const listError = ref("");
const operationError = ref("");
const submitError = ref("");
const idempotencyKey = ref("");
const form = reactive({ qrToken: "", lineId: null, usedPackages: "" });
let listGeneration = 0;
let scanGeneration = 0;
let optionGeneration = 0;
let operationSession = 0;
const canPage = computed(() =>
proxy.$auth.hasPermiOr([
"business:usage:list",
"business:usage:query",
"business:usage:add",
]),
);
const canList = computed(() => proxy.$auth.hasPermi("business:usage:list"));
const canOperate = computed(() =>
proxy.$auth.hasPermiAnd(["business:usage:query", "business:usage:add"]),
);
const operationPending = computed(() => submitLoading.value);
const lineIndex = computed(() => {
const index = lineOptions.value.findIndex((item) => item.id === form.lineId);
return index >= 0 ? index : 0;
});
const selectedLineName = computed(
() => lineOptions.value.find((item) => item.id === form.lineId)?.name || "",
);
function errorMessage(error, fallback) {
return error?.response?.data?.msg || error?.message || fallback;
}
function loadUsageList() {
if (!canList.value) return;
const generation = ++listGeneration;
loading.value = true;
listError.value = "";
listUsage({ pageNum: 1, pageSize: 20 })
.then((response) => {
if (generation !== listGeneration) return;
usageList.value = Array.isArray(response.rows) ? response.rows : [];
})
.catch((error) => {
if (generation !== listGeneration) return;
usageList.value = [];
listError.value = errorMessage(error, "使用记录加载失败,请稍后重试");
})
.finally(() => {
if (generation === listGeneration) loading.value = false;
});
}
function resetUsageOperation() {
operationSession += 1;
scanGeneration += 1;
optionGeneration += 1;
scannedPallet.value = null;
usageResult.value = null;
lineOptions.value = [];
lineLocked.value = false;
idempotencyKey.value = "";
form.qrToken = "";
form.lineId = null;
form.usedPackages = "";
operationError.value = "";
submitError.value = "";
scanLoading.value = false;
optionLoading.value = false;
}
function loadLineOptions(siteId, session, scanRequestGeneration) {
const generation = ++optionGeneration;
optionLoading.value = true;
getUsageLineOptions(siteId)
.then((response) => {
if (
generation !== optionGeneration ||
session !== operationSession ||
scanRequestGeneration !== scanGeneration
) {
return;
}
lineOptions.value = Array.isArray(response.data) ? response.data : [];
if (!lineOptions.value.length) operationError.value = "该现场暂无可用产线";
})
.catch((error) => {
if (generation !== optionGeneration || session !== operationSession) return;
lineOptions.value = [];
operationError.value = errorMessage(error, "产线选项加载失败,请稍后重新扫码");
})
.finally(() => {
if (generation === optionGeneration && session === operationSession) {
optionLoading.value = false;
}
});
}
function handleUsageScan(qrToken) {
if (operationPending.value || scanLoading.value || optionLoading.value) return;
resetUsageOperation();
const session = operationSession;
const generation = ++scanGeneration;
scanLoading.value = true;
scanUsagePallet(qrToken)
.then((response) => {
if (generation !== scanGeneration || session !== operationSession) return;
const pallet = response.data;
if (
!["AT_SITE_UNUSED", "AT_SITE_PARTIAL"].includes(pallet?.flowState) ||
pallet.remainingPackages <= 0
) {
operationError.value = "该托盘当前不可记录使用";
return;
}
scannedPallet.value = {
palletId: pallet.palletId,
palletCode: pallet.palletCode || `#${pallet.palletId}`,
siteId: pallet.siteId,
currentLineId: pallet.currentLineId,
strainCode: pallet.strainCode,
strainName: pallet.strainName,
batchNo: pallet.batchNo,
remainingPackages: pallet.remainingPackages,
flowState: pallet.flowState,
};
form.qrToken = qrToken;
if (pallet.currentLineId != null) {
lineLocked.value = true;
form.lineId = pallet.currentLineId;
lineOptions.value = [
{ id: pallet.currentLineId, code: `#${pallet.currentLineId}`, name: `产线 #${pallet.currentLineId}` },
];
} else {
lineLocked.value = false;
form.lineId = null;
loadLineOptions(pallet.siteId, session, generation);
}
})
.catch((error) => {
if (generation === scanGeneration && session === operationSession) {
operationError.value = errorMessage(error, "托盘扫码校验失败,请检查后重试");
}
})
.finally(() => {
if (generation === scanGeneration && session === operationSession) {
scanLoading.value = false;
}
});
}
function handleScanInvalid(message) {
resetUsageOperation();
operationError.value = message;
}
function handleScanDuplicate() {
proxy.$modal.msg("扫码过快,请勿重复扫描");
}
function handleLineChange(event) {
if (lineLocked.value) return;
const option = lineOptions.value[Number(event.detail.value)];
form.lineId = option?.id || null;
markPayloadChanged();
}
function markPayloadChanged() {
if (!submitLoading.value) idempotencyKey.value = "";
}
function ensureIdempotencyKey() {
if (!idempotencyKey.value) idempotencyKey.value = createIdempotencyKey();
return idempotencyKey.value;
}
function submitUsage() {
if (!canOperate.value || operationPending.value || scanLoading.value || optionLoading.value) return;
const usedPackages = Number(form.usedPackages);
if (!scannedPallet.value || !form.qrToken) {
submitError.value = "请先扫描待使用托盘";
return;
}
if (!form.lineId) {
submitError.value = "请选择使用产线";
return;
}
if (!Number.isInteger(usedPackages) || usedPackages <= 0) {
submitError.value = "使用包数必须为正整数";
return;
}
if (usedPackages > scannedPallet.value.remainingPackages) {
submitError.value = "使用包数不能超过当前剩余包数";
return;
}
submitLoading.value = true;
submitError.value = "";
addUsage({
qrToken: form.qrToken,
lineId: form.lineId,
usedPackages,
idempotencyKey: ensureIdempotencyKey(),
})
.then((response) => {
usageResult.value = response.data;
idempotencyKey.value = "";
proxy.$modal.msgSuccess(response.msg || "现场使用记录成功");
loadUsageList();
})
.catch((error) => {
submitError.value = `${errorMessage(error, "现场使用提交失败")};直接重试将复用本次幂等键,修改输入后会生成新键`;
})
.finally(() => {
submitLoading.value = false;
});
}
onShow(() => {
loadUsageList();
});
</script>
+4 -4
View File
@@ -5,12 +5,12 @@
<!-- Logo Section -->
<view class="mb-6 flex flex-col items-center">
<view
class="mb-4 flex size-16 items-center justify-center rounded-2xl bg-white shadow-lg"
class="mb-4 flex h-20 w-60 items-center justify-center rounded-2xl bg-gray-800 px-4 shadow-lg"
>
<image
class="size-10"
class="h-16 w-full"
:src="globalConfig.appInfo.logo"
mode="widthFix"
mode="aspectFit"
/>
</view>
<text class="text-xl font-bold tracking-wide text-gray-800"
@@ -135,7 +135,7 @@ const captchaEnabled = ref(true);
const register = ref(false);
const loginForm = ref({
username: "admin",
password: "admin123",
password: "",
code: "",
uuid: "",
});
@@ -2,11 +2,13 @@
<view class="flex h-full flex-col bg-gray-50 pb-10">
<!-- Header -->
<view class="flex flex-col items-center py-10">
<view class="flex h-24 w-64 items-center justify-center rounded-xl bg-gray-800 px-4 shadow-md">
<image
class="size-20 rounded-xl shadow-md"
src="/static/logo200.png"
mode="widthFix"
class="h-20 w-full"
src="/static/sylvan-logo.png"
mode="aspectFit"
/>
</view>
<text class="mt-4 text-xl font-bold text-gray-800"
>智链云枢管理系统</text
>
+3 -3
View File
@@ -5,12 +5,12 @@
<!-- Logo Section -->
<view class="mb-6 flex flex-col items-center">
<view
class="mb-4 flex size-16 items-center justify-center rounded-2xl bg-white shadow-lg"
class="mb-4 flex h-20 w-60 items-center justify-center rounded-2xl bg-gray-800 px-4 shadow-lg"
>
<image
class="size-10"
class="h-16 w-full"
:src="globalConfig.appInfo.logo"
mode="widthFix"
mode="aspectFit"
/>
</view>
<text class="text-xl font-bold tracking-wide text-gray-800"
+112 -1
View File
@@ -2,6 +2,8 @@
<view class="flex h-full flex-col bg-gray-50 overflow-hidden">
<scroll-view scroll-y class="flex-1" :show-scrollbar="false">
<view class="p-4 pb-24 space-y-6">
<TestBatchModeSwitch />
<!-- Banner -->
<view
class="relative h-40 w-full overflow-hidden rounded-2xl shadow-lg shadow-indigo-100"
@@ -82,6 +84,36 @@
</view>
</view>
<!-- PDA Business Section -->
<view v-if="visibleBusinessEntries.length">
<view class="mb-4 flex items-center space-x-2">
<view class="h-4 w-1 rounded-full bg-emerald-500"></view>
<text class="text-base font-bold text-gray-800">现场业务</text>
</view>
<view class="rounded-2xl bg-white p-5 shadow-sm">
<view class="grid grid-cols-3 gap-4">
<view
v-for="entry in visibleBusinessEntries"
:key="entry.path"
class="flex flex-col items-center space-y-1.5 active:opacity-60"
@click="handleBusinessEntry(entry)"
>
<view
class="flex size-10 items-center justify-center rounded-xl bg-emerald-50 text-emerald-600"
>
<view :class="entry.icon" class="text-xl"></view>
</view>
<text class="text-center text-[11px] font-medium text-gray-600">
{{ entry.title }}
</text>
<text class="text-center text-[10px] text-gray-400">
{{ entry.description }}
</text>
</view>
</view>
</view>
</view>
<!-- System Management Section -->
<view>
<view class="mb-4 flex items-center space-x-2">
@@ -202,7 +234,8 @@
</template>
<script setup>
import { ref, getCurrentInstance } from "vue";
import { computed, ref, getCurrentInstance } from "vue";
import TestBatchModeSwitch from "@/components/business/TestBatchModeSwitch.vue";
const { proxy } = getCurrentInstance();
const current = ref(0);
@@ -212,6 +245,76 @@ const data = ref([
{ image: "/static/images/banner/banner02.jpg" },
{ image: "/static/images/banner/banner03.jpg" },
]);
const businessEntries = [
{
path: "/pages/business/inbound/index",
title: "仓库入库",
description: "扫描托盘登记入库",
icon: "i-mdi-package-down",
color: "blue",
permissions: [
"business:inbound:list",
"business:inbound:query",
"business:inbound:add",
"business:inbound:edit",
"business:inbound:confirm",
],
},
{
path: "/pages/business/filling/index",
title: "托盘装填",
description: "录入菌种和包数",
icon: "i-mdi-package-variant-closed-plus",
color: "green",
permissions: [
"business:filling:list",
"business:filling:query",
"business:filling:add",
],
},
{
path: "/pages/business/shipment/index",
title: "发货出库",
description: "扫码创建发货单",
icon: "i-mdi-truck-delivery",
color: "orange",
permissions: [
"business:shipment:list",
"business:shipment:query",
"business:shipment:add",
"business:shipment:edit",
"business:shipment:confirm",
],
},
{
path: "/pages/business/usage/index",
title: "现场使用",
description: "绑定产线记录消耗",
icon: "i-mdi-factory",
color: "purple",
permissions: [
"business:usage:list",
"business:usage:query",
"business:usage:add",
],
},
{
path: "/pages/business/return/index",
title: "退回仓库",
description: "申请和确认退回",
icon: "i-mdi-undo-variant",
color: "red",
permissions: [
"business:return:list",
"business:return:query",
"business:return:request",
"business:return:confirm",
],
},
];
const visibleBusinessEntries = computed(() =>
businessEntries.filter((entry) => proxy.$auth.hasPermiOr(entry.permissions)),
);
function clickBannerItem(item) {
console.info(item);
@@ -229,6 +332,14 @@ function handleToUserList() {
handleBuilding();
}
function handleBusinessEntry(entry) {
if (!proxy.$auth.hasPermiOr(entry.permissions)) {
proxy.$modal.msgError("当前账号没有该业务权限");
return;
}
proxy.$tab.navigateTo(entry.path);
}
function handleBuilding() {
proxy.$modal.msg("模块建设中~");
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

@@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg id="_图层_2" data-name="图层 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 516.1 194.52">
<defs>
<style>
.cls-1 {
fill: #008596;
}
.cls-2 {
fill: #fff;
}
.cls-3 {
fill: #91cdb9;
}
.cls-4 {
fill: #43b69e;
}
.cls-5 {
fill: #554d8a;
}
.cls-6 {
fill: #50bcba;
}
.cls-7, .cls-8, .cls-9 {
fill: #28225c;
}
.cls-10 {
fill: #009a91;
opacity: .8;
}
.cls-10, .cls-11 {
fill-rule: evenodd;
}
.cls-11 {
fill: #a5d7d7;
}
.cls-8 {
opacity: .5;
}
.cls-9 {
opacity: .25;
}
</style>
</defs>
<g id="tekening">
<g>
<g>
<path class="cls-2" d="M302.33,61.89l-18.13,63.56c-3.35,11.65-7.77,17.59-23.63,17.59-3.99,0-10.36-.86-13.06-1.73-1.19-.43-2.27-.76-2.27-1.94v-8.74c0-1.19,.97-2.05,2.16-2.05h.22c3.56,.21,9.93,.86,13.49,.86,3.88,0,5.83-1.29,7.12-5.61l.97-3.35h-1.62c-3.99,0-7.34-.65-10.04-10.04l-14.24-48.56c-.11-.32-.11-.54-.11-.76,0-1.08,.65-1.73,2.16-1.73h14.35c1.08,0,1.83,.97,2.05,2.05l9.71,40.58c.32,1.51,.65,2.05,1.29,2.05h.97l10.04-42.63c.21-1.08,1.08-2.05,2.27-2.05h14.35c1.08,0,2.05,.86,2.05,1.94,0,.22-.11,.33-.11,.54Z"/>
<path class="cls-2" d="M326.72,121.44h-13.17c-1.19,0-2.27-1.08-2.27-2.27V40.83c0-1.19,1.08-2.16,2.27-2.16h13.17c1.19,0,2.05,.97,2.05,2.16V119.17c0,1.19-.86,2.27-2.05,2.27Z"/>
<path class="cls-2" d="M396,61.89l-13.6,48.99c-2.7,9.6-9.28,11.33-15.65,11.33s-12.84-1.73-15.54-11.33l-13.49-48.99c-.11-.21-.11-.43-.11-.65,0-1.08,.76-1.84,1.73-1.84h14.24c1.08,0,1.94,.97,2.27,2.27l9.28,42.3c.33,1.62,.86,2.27,1.62,2.27s1.4-.65,1.73-2.27l9.28-42.3c.32-1.3,1.19-2.27,2.27-2.27h14.24c.97,0,1.84,.76,1.84,1.84,0,.21,0,.43-.11,.65Z"/>
<path class="cls-2" d="M418.66,121.3c-9.39,0-18.45-4.53-18.45-18.56v-.97c0-12.63,8.09-18.24,26.55-18.24h5.83v-3.89c0-6.15-6.78-7.47-11.85-7.47,0,0-17.96,1.95-17.96-12.69,0,0,16.18-.15,23.3-.15,15.54,0,23.99,4.55,23.99,20.31v39.49c0,1.19-.97,2.16-2.16,2.16h-29.24Zm13.89-27.41h-6.15c-7.56,0-9.5,2.59-9.5,7.88v.97c0,4.53,2.27,5.39,6.8,5.39,3.24,0,8.68,0,8.68,0l.17-14.25Z"/>
<path class="cls-2" d="M497.01,58.61c15.65,0,19.1,10.9,19.1,24.5v35.93c0,1.19-1.08,2.27-2.27,2.27h-13.06c-1.19,0-2.16-1.08-2.16-2.27v-35.93c-.1-6.03,.45-8.65-6.13-8.65-3.22,0-8.33,.12-11.99,2.06v42.52c0,1.19-.97,2.27-2.16,2.27h-13.06c-1.19,0-2.27-1.08-2.27-2.27V61.63c0-1.19,.97-2.16,2.16-2.16l31.83-.86Z"/>
<path class="cls-2" d="M184.25,121.47c0-17.9,16.39-18.14,16.39-18.14,8.24,0,17.54-.5,17.98-6.18,.24-3.16-.41-4.44-6.02-7.82l-15.23-8.96c-10.04-6.01-12.73-12.89-12.73-20.87,0-12.02,6.69-21.3,27.63-21.3,1.66,0,23.24,.05,23.26,.07-.13,.14,.12,2.04,.12,3.24,0,14.93-20.16,13.71-20.16,13.71-6.15,0-9.85,2.38-9.85,6.31,0,3.06,1.26,4.7,7.09,7.87l13.81,6.38c11.22,6.12,12.5,12.79,12.5,21.64,0,11.58-6.73,24.27-24.96,24.11l-29.81-.05Z"/>
<g>
<path class="cls-2" d="M365.04,163.65h-1.67c-.32,0-.58-.29-.58-.64v-22.95c0-.32,.23-.61,.58-.61h1.67c.32,0,.58,.26,.58,.61v22.95c0,.32-.23,.64-.58,.64Z"/>
<path class="cls-2" d="M373.88,143.11h-1.64c-.35,0-.64-.29-.64-.64v-2.57c0-.35,.29-.64,.64-.64h1.64c.35,0,.64,.29,.64,.64v2.57c0,.35-.29,.64-.64,.64Zm-.06,20.53h-1.54c-.35,0-.64-.29-.64-.64v-16.42c0-.35,.29-.64,.64-.64h1.54c.35,0,.64,.29,.64,.64v16.42c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M393.77,146.72l-4.35,15.32c-.42,1.45-1.51,1.84-2.9,1.84s-2.48-.39-2.9-1.84l-4.34-15.32c-.03-.1-.03-.16-.03-.23,0-.32,.19-.55,.51-.55h1.77c.26,0,.48,.19,.61,.61l3.7,14.03c.19,.77,.35,.93,.68,.93,.29,0,.48-.16,.68-.93l3.7-14.03c.13-.42,.35-.61,.61-.61h1.77c.32,0,.51,.23,.51,.55,0,.06,0,.13-.03,.23Z"/>
<path class="cls-2" d="M400.81,143.11h-1.64c-.35,0-.64-.29-.64-.64v-2.57c0-.35,.29-.64,.64-.64h1.64c.35,0,.64,.29,.64,.64v2.57c0,.35-.29,.64-.64,.64Zm-.06,20.53h-1.54c-.35,0-.64-.29-.64-.64v-16.42c0-.35,.29-.64,.64-.64h1.54c.35,0,.64,.29,.64,.64v16.42c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M420.03,163.65h-1.54c-.35,0-.64-.29-.64-.64v-10.59c0-3.25-1.09-4.25-3.54-4.25-1.35,0-2.86,.51-4.34,1.26v13.58c0,.32-.29,.64-.64,.64h-1.58c-.32,0-.61-.29-.61-.64v-16.42c0-.35,.26-.64,.61-.64h1.61c.35,0,.61,.29,.61,.64v.61c1.77-1,3.22-1.48,5.12-1.48,3.86,0,5.6,2.41,5.6,6.69v10.59c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M440.07,148.1l-1.16,.22c.58,.61,1.09,1.58,1.09,3.32v.26c0,3.54-2.19,5.5-7.15,5.5-1.71,0-2.8-.26-3.73-.64-.55,.26-.8,.61-.8,1.09,0,.55,.26,.84,1,1.03l4.8,1.22c3.15,.8,6.18,1.71,6.18,4.73v.26c0,3.09-2.06,4.99-7.34,4.99s-7.4-1.96-7.4-5.12v-.29c0-1.8,.97-3.28,2.03-4.09l-.23-.1c-1.03-.45-1.48-1.51-1.48-2.51v-.03c0-.87,.42-1.8,1.32-2.32-1-.93-1.48-2.09-1.48-3.73v-.26c0-2.86,1.61-5.7,7.14-5.7h7.05c.39,0,.74,.32,.74,.71v.84c0,.42-.23,.55-.58,.61Zm-2.61,16.74c0-1.26-1.03-1.77-3.93-2.51l-3.64-.93c-.93,.8-1.58,1.61-1.58,3.28v.29c0,1.8,1.06,2.93,4.63,2.93s4.51-1.03,4.51-2.8v-.26Zm-.26-13.2c0-1.93-.87-3.44-4.35-3.44s-4.34,1.64-4.34,3.44v.26c0,1.42,.64,3.28,4.34,3.28,3.48,0,4.35-1.35,4.35-3.28v-.26Z"/>
<path class="cls-2" d="M365.07,173.76h-1.64c-.35,0-.64-.29-.64-.64v-2.57c0-.35,.29-.64,.64-.64h1.64c.35,0,.64,.29,.64,.64v2.57c0,.35-.29,.64-.64,.64Zm-.06,20.53h-1.54c-.35,0-.64-.29-.64-.64v-16.42c0-.35,.29-.64,.64-.64h1.54c.35,0,.64,.29,.64,.64v16.42c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M384.28,194.29h-1.54c-.35,0-.64-.29-.64-.64v-10.59c0-3.25-1.09-4.25-3.54-4.25-1.35,0-2.86,.51-4.34,1.26v13.58c0,.32-.29,.64-.64,.64h-1.58c-.32,0-.61-.29-.61-.64v-16.42c0-.35,.26-.64,.61-.64h1.61c.35,0,.61,.29,.61,.64v.61c1.77-1,3.22-1.48,5.12-1.48,3.86,0,5.6,2.41,5.6,6.69v10.59c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M403.17,194.29h-1.54c-.35,0-.64-.29-.64-.64v-10.59c0-3.25-1.09-4.25-3.54-4.25-1.35,0-2.86,.51-4.34,1.26v13.58c0,.32-.29,.64-.64,.64h-1.58c-.32,0-.61-.29-.61-.64v-16.42c0-.35,.26-.64,.61-.64h1.61c.35,0,.61,.29,.61,.64v.61c1.77-1,3.22-1.48,5.12-1.48,3.86,0,5.6,2.41,5.6,6.69v10.59c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M415.71,194.52c-4.73,0-7.14-3.12-7.14-7.85v-2.45c0-4.73,2.41-7.85,7.14-7.85s7.18,3.12,7.18,7.85v2.45c0,4.73-2.45,7.85-7.18,7.85Zm4.35-10.3c0-3.28-1.32-5.38-4.35-5.38s-4.31,2.06-4.31,5.38v2.45c0,3.28,1.29,5.38,4.31,5.38s4.35-2.06,4.35-5.38v-2.45Z"/>
<path class="cls-2" d="M440.52,177.36l-4.35,15.32c-.42,1.45-1.51,1.84-2.9,1.84s-2.48-.39-2.9-1.84l-4.35-15.32c-.03-.1-.03-.16-.03-.23,0-.32,.19-.55,.51-.55h1.77c.26,0,.48,.19,.61,.61l3.7,14.03c.19,.77,.35,.93,.68,.93,.29,0,.48-.16,.68-.93l3.7-14.03c.13-.42,.35-.61,.61-.61h1.77c.32,0,.51,.23,.51,.55,0,.06,0,.13-.03,.23Z"/>
<path class="cls-2" d="M455.97,194.29h-1.48c-.35,0-.64-.29-.64-.64v-.71c-1.54,.9-3.15,1.58-4.96,1.58-2.74,0-5.25-1.19-5.25-5.21v-.39c0-3.48,2.03-5.21,7.76-5.21h2.38v-1.29c0-2.7-.93-3.64-3.44-3.64-2.09,0-3.64,.13-4.92,.26h-.16c-.29,0-.58-.1-.58-.51v-1.13c0-.35,.23-.55,.68-.61,1.32-.23,2.8-.42,4.99-.42,4.47,0,6.28,2.25,6.28,6.05v11.23c0,.35-.29,.64-.64,.64Zm-2.19-8.56h-2.38c-3.9,0-4.93,.87-4.93,3.15v.39c0,2.32,1.09,2.93,2.96,2.93,1.48,0,2.8-.45,4.35-1.29v-5.18Z"/>
<path class="cls-2" d="M469.99,194.36c-.64,.1-1.48,.16-2.09,.16-2.96,0-4.38-.77-4.38-4.31v-11.23l-3.12-.35c-.35-.03-.61-.22-.61-.58v-.87c0-.35,.26-.58,.61-.58h3.12v-3.15c0-.32,.22-.58,.58-.64l1.67-.26h.1c.26,0,.48,.22,.48,.55v3.51h3.48c.35,0,.64,.29,.64,.64v1.09c0,.35-.29,.64-.64,.64h-3.48v11.23c0,1.77,.45,2.03,1.74,2.03h1.8c.45,0,.68,.13,.68,.45v1.13c0,.29-.16,.48-.58,.55Z"/>
<path class="cls-2" d="M477.14,173.76h-1.64c-.35,0-.64-.29-.64-.64v-2.57c0-.35,.29-.64,.64-.64h1.64c.35,0,.64,.29,.64,.64v2.57c0,.35-.29,.64-.64,.64Zm-.06,20.53h-1.54c-.35,0-.64-.29-.64-.64v-16.42c0-.35,.29-.64,.64-.64h1.54c.35,0,.64,.29,.64,.64v16.42c0,.35-.29,.64-.64,.64Z"/>
<path class="cls-2" d="M490.01,194.52c-4.73,0-7.14-3.12-7.14-7.85v-2.45c0-4.73,2.41-7.85,7.14-7.85s7.18,3.12,7.18,7.85v2.45c0,4.73-2.45,7.85-7.18,7.85Zm4.35-10.3c0-3.28-1.32-5.38-4.35-5.38s-4.31,2.06-4.31,5.38v2.45c0,3.28,1.29,5.38,4.31,5.38s4.35-2.06,4.35-5.38v-2.45Z"/>
<path class="cls-2" d="M514.85,194.29h-1.54c-.35,0-.64-.29-.64-.64v-10.59c0-3.25-1.09-4.25-3.54-4.25-1.35,0-2.86,.51-4.34,1.26v13.58c0,.32-.29,.64-.64,.64h-1.58c-.32,0-.61-.29-.61-.64v-16.42c0-.35,.26-.64,.61-.64h1.61c.35,0,.61,.29,.61,.64v.61c1.77-1,3.22-1.48,5.12-1.48,3.86,0,5.6,2.41,5.6,6.69v10.59c0,.35-.29,.64-.64,.64Z"/>
</g>
</g>
<g>
<path class="cls-11" d="M57.78,67.44c-.03,5.02-.86,9.86-2.35,14.39,0,0,.01,.01,.02,.02,0,0,0,0,.01,0,10.82-31.09,38.25-54.41,71.67-59.3C130.83,15.86,132.95,8.18,132.95,0h0s-46.67,0-46.67,0H46.67C30.78,0,16.76,7.94,8.33,20.07c.88-.04,1.76-.07,2.65-.06,26.02,.17,46.98,21.41,46.8,47.43Z"/>
<path class="cls-10" d="M0,46.67c0,5.62,1,11,2.82,15.99,5.22-.78,10.62-.87,16.11-.17,14.7,1.88,27.41,9.05,36.5,19.35,1.49-4.53,2.31-9.36,2.35-14.39,.17-26.02-20.78-47.26-46.8-47.43-.89,0-1.77,.02-2.65,.06C3.08,27.61,0,36.78,0,46.67H0Z"/>
<path class="cls-6" d="M0,46.67c0,5.62,1,11,2.82,15.99,5.22-.78,10.62-.87,16.11-.17,14.7,1.88,27.41,9.05,36.5,19.35,1.49-4.53,2.31-9.36,2.35-14.39,.17-26.02-20.78-47.26-46.8-47.43-.89,0-1.77,.02-2.65,.06C3.08,27.61,0,36.78,0,46.67H0Z"/>
<path class="cls-7" d="M55.46,81.85s-.01-.01-.02-.02c0,0,0,0,0,.01,0,0,.02,0,.02,0Z"/>
<path class="cls-10" d="M55.47,81.85s0,0-.01,0c0,0,0,0,.01,.01,0,0,0,0,0,0Z"/>
<path class="cls-8" d="M55.47,81.85s0,0-.01,0c0,0,0,0,.01,.01,0,0,0,0,0,0Z"/>
<path class="cls-7" d="M55.42,81.88s.03,0,.05-.01c0,0,0,0,0,0,0,0,0,0-.01-.01,0,0-.02,0-.02,0,0,.01,0,.02-.01,.03Z"/>
<path class="cls-8" d="M55.42,81.88s.03,0,.05-.01c0,0,0,0,0,0,0,0,0,0-.01-.01,0,0-.02,0-.02,0,0,.01,0,.02-.01,.03Z"/>
<path class="cls-10" d="M55.47,81.85s0,0,.01,0c5.58-1.58,11.47-2.44,17.56-2.44,24,0,44.92,13.13,56.01,32.6,2.5-5.72,3.9-12.04,3.9-18.68h0c0-24.43-18.78-44.48-42.69-46.5-.22-.02-.22-.31,0-.33,15.91-1.34,29.53-10.67,36.88-23.95-33.42,4.9-60.85,28.21-71.67,59.3Z"/>
<path class="cls-3" d="M55.47,81.85s0,0,.01,0c5.58-1.58,11.47-2.44,17.56-2.44,24,0,44.92,13.13,56.01,32.6,2.5-5.72,3.9-12.04,3.9-18.68h0c0-24.43-18.78-44.48-42.69-46.5-.22-.02-.22-.31,0-.33,15.91-1.34,29.53-10.67,36.88-23.95-33.42,4.9-60.85,28.21-71.67,59.3Z"/>
<path class="cls-10" d="M55.47,81.86s.01,0,.02,0c0,0,0,0-.01,0,0,0,0,0,0,0,0,0,0,0,0,0Z"/>
<path class="cls-8" d="M55.47,81.86s.01,0,.02,0c0,0,0,0-.01,0,0,0,0,0,0,0,0,0,0,0,0,0Z"/>
<path class="cls-9" d="M55.47,81.86s.01,0,.02,0c0,0,0,0-.01,0,0,0,0,0,0,0,0,0,0,0,0,0Z"/>
<polygon class="cls-7" points="55.47 81.86 55.47 81.86 55.47 81.86 55.47 81.86"/>
<polygon class="cls-8" points="55.47 81.86 55.47 81.86 55.47 81.86 55.47 81.86"/>
<polygon class="cls-9" points="55.47 81.86 55.47 81.86 55.47 81.86 55.47 81.86"/>
<path class="cls-10" d="M73.04,79.42c-6.09,0-11.97,.86-17.56,2.44,24.27,7.47,41.91,30.06,41.91,56.78,0,0,0,.01,0,.02,14.23-3.48,25.89-13.47,31.65-26.64-11.08-19.46-32-32.6-56.01-32.6Z"/>
<path class="cls-9" d="M73.04,79.42c-6.09,0-11.97,.86-17.56,2.44,24.27,7.47,41.91,30.06,41.91,56.78,0,0,0,.01,0,.02,14.23-3.48,25.89-13.47,31.65-26.64-11.08-19.46-32-32.6-56.01-32.6Z"/>
<path class="cls-4" d="M73.04,79.42c-6.09,0-11.97,.86-17.56,2.44,24.27,7.47,41.91,30.06,41.91,56.78,0,0,0,.01,0,.02,14.23-3.48,25.89-13.47,31.65-26.64-11.08-19.46-32-32.6-56.01-32.6Z"/>
<path class="cls-10" d="M55.48,81.86s-.01,0-.02,0c10.78,12.22,16.46,28.84,14.23,46.28-.53,4.12-1.59,8.08-3.11,11.86h19.69c3.83,0,7.55-.47,11.11-1.34,0,0,0-.01,0-.02,0-26.72-17.64-49.31-41.91-56.78Z"/>
<path class="cls-8" d="M55.48,81.86s-.01,0-.02,0c10.78,12.22,16.46,28.84,14.23,46.28-.53,4.12-1.59,8.08-3.11,11.86h19.69c3.83,0,7.55-.47,11.11-1.34,0,0,0-.01,0-.02,0-26.72-17.64-49.31-41.91-56.78Z"/>
<path class="cls-9" d="M55.48,81.86s-.01,0-.02,0c10.78,12.22,16.46,28.84,14.23,46.28-.53,4.12-1.59,8.08-3.11,11.86h19.69c3.83,0,7.55-.47,11.11-1.34,0,0,0-.01,0-.02,0-26.72-17.64-49.31-41.91-56.78Z"/>
<path class="cls-1" d="M55.48,81.86s-.01,0-.02,0c10.78,12.22,16.46,28.84,14.23,46.28-.53,4.12-1.59,8.08-3.11,11.86h19.69c3.83,0,7.55-.47,11.11-1.34,0,0,0-.01,0-.02,0-26.72-17.64-49.31-41.91-56.78Z"/>
<path class="cls-5" d="M55.47,81.86s0,0,0,0c-.02,0-.03,0-.05,.01,0-.01,0-.02,.01-.03,0,0,0,0,0-.01-9.09-10.29-21.81-17.47-36.5-19.35-5.49-.7-10.89-.6-16.11,.17,2.93,8.02,7.98,15.01,14.5,20.29,5.11,4.14,11.12,7.22,17.69,8.91,2.45,.63,4.96,1.08,7.55,1.3,.24,.02,.24,.34,0,.36-4.74,.41-9.26,1.54-13.49,3.27-8.71,3.55-16.1,9.65-21.25,17.38-4.93,7.4-7.82,16.28-7.82,25.84H0s8.74,0,8.74,0h57.85c1.51-3.77,2.58-7.74,3.11-11.86,2.23-17.44-3.45-34.06-14.23-46.28Z"/>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+2 -1
View File
@@ -1,9 +1,10 @@
import { createPinia } from "pinia";
import { useUserStore } from "./modules/user";
import { useConfigStore } from "./modules/config";
import { useTestBatchStore } from "./modules/testBatch";
const pinia = createPinia();
export default pinia;
export { useUserStore, useConfigStore };
export { useUserStore, useConfigStore, useTestBatchStore };
@@ -0,0 +1,83 @@
import { computed, ref } from "vue";
import { defineStore } from "pinia";
import { listAvailableTestBatches } from "@/api/system/testBatch";
import storage from "@/utils/storage";
import constant from "@/utils/constant";
export const useTestBatchStore = defineStore("testBatch", () => {
const options = ref([]);
const currentBatchId = ref(String(storage.get(constant.testBatchId) || ""));
const currentBatchName = ref(storage.get(constant.testBatchName) || "");
const scopeVersion = ref(0);
const isTestMode = computed(() => Boolean(currentBatchId.value));
function leaveTestMode() {
currentBatchId.value = "";
currentBatchName.value = "";
storage.remove(constant.testBatchId);
storage.remove(constant.testBatchName);
scopeVersion.value += 1;
}
async function refreshOptions() {
try {
const response = await listAvailableTestBatches();
const available = (Array.isArray(response.data) ? response.data : []).filter(
(item) => item && item.status === "ACTIVE" && item.batchId != null,
);
options.value = available;
const current = available.find(
(item) => String(item.batchId) === String(currentBatchId.value),
);
if (current) {
currentBatchId.value = String(current.batchId);
currentBatchName.value = current.batchName || "";
storage.set(constant.testBatchId, currentBatchId.value);
storage.set(constant.testBatchName, currentBatchName.value);
} else if (currentBatchId.value) {
// 本地缓存不能代替后端授权;选项接口未返回当前批次时立即回到正式模式。
leaveTestMode();
}
return available;
} catch (error) {
options.value = [];
leaveTestMode();
throw error;
}
}
function selectBatch(batch) {
const allowed = options.value.find(
(item) =>
String(item.batchId) === String(batch?.batchId) && item.status === "ACTIVE",
);
if (!allowed) {
throw new Error("所选测试批次当前不可用");
}
currentBatchId.value = String(allowed.batchId);
currentBatchName.value = allowed.batchName || "";
storage.set(constant.testBatchId, currentBatchId.value);
storage.set(constant.testBatchName, currentBatchName.value);
scopeVersion.value += 1;
}
function reset() {
options.value = [];
leaveTestMode();
}
return {
options,
currentBatchId,
currentBatchName,
scopeVersion,
isTestMode,
refreshOptions,
selectBatch,
leaveTestMode,
reset,
};
});
export default useTestBatchStore;
@@ -15,6 +15,7 @@ export const useUserStore = defineStore("user", () => {
const id = ref(storage.get(constant.id));
const name = ref(storage.get(constant.name));
const avatar = ref(storage.get(constant.avatar));
const admin = ref(storage.get(constant.admin) === true || storage.get(constant.admin) === "true");
const roles = ref(storage.get(constant.roles));
const permissions = ref(storage.get(constant.permissions));
@@ -33,6 +34,10 @@ export const useUserStore = defineStore("user", () => {
avatar.value = val;
storage.set(constant.avatar, val);
};
const SET_ADMIN = (val) => {
admin.value = val === true;
storage.set(constant.admin, admin.value);
};
const SET_ROLES = (val) => {
roles.value = val;
storage.set(constant.roles, val);
@@ -81,6 +86,7 @@ export const useUserStore = defineStore("user", () => {
} else {
SET_ROLES(["ROLE_DEFAULT"]);
}
SET_ADMIN(user.admin === true);
SET_ID(userid);
SET_NAME(username);
SET_AVATAR(avatar);
@@ -115,6 +121,7 @@ export const useUserStore = defineStore("user", () => {
id,
name,
avatar,
admin,
roles,
permissions,
SET_AVATAR,
@@ -2,8 +2,11 @@ const constant = {
avatar: "user_avatar",
id: "user_id",
name: "user_name",
admin: "user_admin",
roles: "user_roles",
permissions: "user_permissions",
testBatchId: "test_batch_id",
testBatchName: "test_batch_name",
};
export default constant;
@@ -0,0 +1,45 @@
export function normalizeScanValue(value) {
const normalizedValue = String(value ?? "").trim();
if (!normalizedValue) {
throw new Error("二维码不能为空");
}
if (normalizedValue.length > 128) {
throw new Error("二维码长度不能超过 128 个字符");
}
return normalizedValue;
}
export function isDuplicateScan(
value,
lastValue,
scannedAt,
lastScannedAt,
duplicateWindowMs,
) {
const elapsed = scannedAt - lastScannedAt;
return (
value === lastValue &&
elapsed >= 0 &&
elapsed <= duplicateWindowMs
);
}
export function createIdempotencyKey(
cryptoProvider =
typeof globalThis === "undefined" ? undefined : globalThis.crypto,
) {
if (typeof cryptoProvider?.randomUUID === "function") {
return cryptoProvider.randomUUID();
}
if (typeof cryptoProvider?.getRandomValues !== "function") {
throw new Error("当前环境不支持安全随机数,请使用 HTTPS 或 localhost 访问系统");
}
const bytes = cryptoProvider.getRandomValues(new Uint8Array(16));
bytes[6] = (bytes[6] & 0x0f) | 0x40;
bytes[8] = (bytes[8] & 0x3f) | 0x80;
const hex = Array.from(bytes, (byte) =>
byte.toString(16).padStart(2, "0"),
).join("");
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
}
+56 -5
View File
@@ -1,6 +1,8 @@
import config from "@/config";
import { getToken } from "@/utils/auth";
import errorCode from "@/utils/errorCode";
import constant from "@/utils/constant";
import storage from "@/utils/storage";
import { useUserStore } from "@/store/modules/user";
import { toast, showConfirm, tansParams } from "@/utils/common";
import {
@@ -14,6 +16,37 @@ import {
let timeout = 10000;
const baseUrl = config.baseUrl;
let testBatchRecoveryStarted = false;
function getResponseBody(payload) {
return payload?.data && typeof payload.data === "object" ? payload.data : payload || {};
}
function getResponseData(payload) {
const body = getResponseBody(payload);
return body.data && typeof body.data === "object" ? body.data : body;
}
function isTestBatchUnavailable(payload) {
return getResponseData(payload)?.reason === "TEST_BATCH_UNAVAILABLE";
}
function recoverUnavailableTestBatch(payload) {
if (testBatchRecoveryStarted) return;
testBatchRecoveryStarted = true;
const body = getResponseBody(payload);
const message = body.msg || "当前测试批次不可用,已切回正式数据模式";
storage.remove(constant.testBatchId);
storage.remove(constant.testBatchName);
if (typeof uni.$emit === "function") {
uni.$emit("test-batch-unavailable", message);
}
uni.showToast({ title: message, icon: "none", duration: 3500 });
uni.reLaunch({ url: "/pages/work/index" });
setTimeout(() => {
testBatchRecoveryStarted = false;
}, 1000);
}
const request = async (config) => {
// 是否需要设置 token
@@ -23,6 +56,10 @@ const request = async (config) => {
if (getToken() && !isToken) {
config.header["Authorization"] = "Bearer " + getToken();
}
const testBatchId = storage.get(constant.testBatchId);
if (getToken() && testBatchId) {
config.header["X-Test-Batch-Id"] = String(testBatchId);
}
try {
config = await encryptTransportRequest(config);
@@ -55,8 +92,17 @@ const request = async (config) => {
return;
}
const code = res.data.code || 200;
const msg = errorCode[code] || res.data.msg || errorCode["default"];
if (isTestBatchUnavailable(res)) {
recoverUnavailableTestBatch(res);
const error = new Error(getResponseBody(res).msg || "当前测试批次不可用");
error.response = res;
reject(error);
return;
}
const body = getResponseBody(res);
const code = body.code || 200;
const msg = errorCode[code] || body.msg || errorCode["default"];
if (code === 401) {
showConfirm(
"登录状态已过期,您可以继续留在该页面,或者重新登录?",
@@ -81,7 +127,7 @@ const request = async (config) => {
error.response = res;
reject(error);
} else {
resolve(res.data);
resolve(body);
}
} catch (error) {
reject(error);
@@ -100,10 +146,15 @@ const request = async (config) => {
return request(config);
}
if (isTestBatchUnavailable(error?.response)) {
recoverUnavailableTestBatch(error.response);
}
const response = error.response;
const responseStatus = response?.status ?? response?.statusCode;
const responseCode = response?.data?.code;
const responseMsg = response?.data?.msg;
const responseBody = getResponseBody(response);
const responseCode = responseBody?.code;
const responseMsg = responseBody?.msg;
if (responseMsg) {
uni.showToast({
title: responseMsg,
@@ -8,8 +8,11 @@ let storageNodeKeys = [
constant.avatar,
constant.id,
constant.name,
constant.admin,
constant.roles,
constant.permissions,
constant.testBatchId,
constant.testBatchName,
];
const storage = {
@@ -0,0 +1,333 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { test } from "node:test";
const appRoot = fileURLToPath(new URL("..", import.meta.url));
test("PDA 的 H5、App 和小程序统一使用 Sylvan 品牌标识", async () => {
const [config, loginPage, registerPage, aboutPage, indexHtml, fullLogo, markPng] =
await Promise.all([
readFile(path.join(appRoot, "src/config.js"), "utf8"),
readFile(path.join(appRoot, "src/pages/login.vue"), "utf8"),
readFile(path.join(appRoot, "src/pages/register.vue"), "utf8"),
readFile(path.join(appRoot, "src/pages/mine/about/index.vue"), "utf8"),
readFile(path.join(appRoot, "index.html"), "utf8"),
readFile(path.join(appRoot, "src/static/sylvan-logo.svg"), "utf8"),
readFile(path.join(appRoot, "src/static/sylvan-mark.png")),
]);
assert.match(config, /logo:\s*["']\/static\/sylvan-logo\.png["']/);
assert.match(loginPage, /globalConfig\.appInfo\.logo/);
assert.match(registerPage, /globalConfig\.appInfo\.logo/);
assert.match(aboutPage, /src=["']\/static\/sylvan-logo\.png["']/);
assert.match(indexHtml, /href=["']\/static\/favicon\.ico["']/);
assert.match(fullLogo, /viewBox="0 0 516\.1 194\.52"/);
assert.equal(markPng.subarray(1, 4).toString("ascii"), "PNG");
assert.doesNotMatch(`${config}\n${aboutPage}`, /\/static\/logo(?:200)?\.png/);
assert.doesNotMatch(fullLogo, /<script\b|<foreignObject\b|javascript:|\b(?:xlink:)?href=|\bonload=|\bonerror=/i);
});
const apiContracts = {
"src/api/business/inbound.js": [
["listInbound", "'/business/inbound/list'", "get"],
["getInboundWarehouseOptions", "'/business/inbound/warehouse-options'", "get"],
["scanInboundPallet", "'/business/inbound/scan/' + qrToken", "get"],
["getInbound", "'/business/inbound/' + inboundId", "get"],
["addInbound", "'/business/inbound'", "post"],
["updateInbound", "'/business/inbound'", "put"],
["confirmInbound", "'/business/inbound/' + inboundId + '/confirm'", "put"],
],
"src/api/business/filling.js": [
["listFilling", "'/business/filling/list'", "get"],
["getFillingStrainOptions", "'/business/filling/strain-options'", "get"],
["scanFillingPallet", "'/business/filling/scan/' + qrToken", "get"],
["getFilling", "'/business/filling/' + fillingId", "get"],
["addFilling", "'/business/filling'", "post"],
],
"src/api/business/shipment.js": [
["listShipment", "'/business/shipment/list'", "get"],
["getShipmentWarehouseOptions", "'/business/shipment/warehouse-options'", "get"],
["getShipmentSiteOptions", "'/business/shipment/site-options'", "get"],
["scanShipmentPallet", "'/business/shipment/scan/' + qrToken", "get"],
["getShipment", "'/business/shipment/' + shipmentId", "get"],
["addShipment", "'/business/shipment'", "post"],
["updateShipment", "'/business/shipment'", "put"],
["confirmShipment", "'/business/shipment/' + shipmentId + '/confirm'", "put"],
],
"src/api/business/usage.js": [
["listUsage", "'/business/usage/list'", "get"],
["getUsageLineOptions", "'/business/usage/line-options'", "get"],
["scanUsagePallet", "'/business/usage/scan/' + qrToken", "get"],
["getUsage", "'/business/usage/' + usageId", "get"],
["addUsage", "'/business/usage'", "post"],
],
"src/api/business/return.js": [
["listReturn", "'/business/return/list'", "get"],
["getReturnWarehouseOptions", "'/business/return/warehouse-options'", "get"],
["scanReturnPallet", "'/business/return/scan/' + qrToken", "get"],
["requestReturn", "'/business/return/request'", "post"],
["getReturn", "'/business/return/' + returnId", "get"],
["confirmReturn", "'/business/return/' + returnId + '/confirm'", "put"],
],
};
function sourceForFunction(source, functionName) {
const match = source.match(
new RegExp(`export function ${escapeRegExp(functionName)}\\s*\\(`),
);
const start = match?.index ?? -1;
assert.notEqual(start, -1, `${functionName} 导出不存在`);
const end = source.indexOf("\n}", start);
return source.slice(start, end === -1 ? source.length : end + 2);
}
test("五个 PDA API 模块使用现有业务路径和 HTTP 方法", async (t) => {
for (const [relativePath, contracts] of Object.entries(apiContracts)) {
await t.test(relativePath, async () => {
const source = await readFile(path.join(appRoot, relativePath), "utf8");
for (const [functionName, url, method] of contracts) {
const functionSource = sourceForFunction(source, functionName);
const normalizedFunctionSource = functionSource.replaceAll("'", '"');
const normalizedUrl = url.replaceAll("'", '"');
assert.match(
normalizedFunctionSource,
new RegExp(`url:\\s*${escapeRegExp(normalizedUrl)}`),
);
assert.match(functionSource, new RegExp(`method:\\s*["']${method}["']`));
}
});
}
});
test("扫码值只去除首尾空白并拒绝空值", async () => {
const { normalizeScanValue } = await importSource("src/utils/palletScan.js");
assert.equal(normalizeScanValue(" QR-001\n"), "QR-001");
assert.throws(() => normalizeScanValue(" \n\t "), /二维码不能为空/);
});
test("同一扫码值只在短时窗口内被识别为重复", async () => {
const { isDuplicateScan } = await importSource("src/utils/palletScan.js");
assert.equal(isDuplicateScan("QR-001", "QR-001", 1200, 1000, 500), true);
assert.equal(isDuplicateScan("QR-001", "QR-002", 1200, 1000, 500), false);
assert.equal(isDuplicateScan("QR-001", "QR-001", 1801, 1000, 500), false);
});
test("幂等键优先使用 randomUUID,回退时使用 UUID v4 安全随机字节", async () => {
const { createIdempotencyKey } = await importSource("src/utils/palletScan.js");
const expected = "12345678-1234-4123-8123-123456789abc";
assert.equal(createIdempotencyKey({ randomUUID: () => expected }), expected);
assert.equal(
createIdempotencyKey({
getRandomValues(bytes) {
bytes.fill(0);
return bytes;
},
}),
"00000000-0000-4000-8000-000000000000",
);
});
test("PalletScanInput 使用 HID 回车提交并由 loading 锁定输入", async () => {
const source = await readFile(
path.join(appRoot, "src/components/business/PalletScanInput.vue"),
"utf8",
);
assert.match(source, /@confirm=["']handleSubmit["']/);
assert.match(source, /normalizeScanValue/);
assert.match(source, /isDuplicateScan/);
assert.match(source, /emit\(["']scan["']/);
assert.match(source, /emit\(["']invalid["']/);
assert.match(source, /emit\(["']duplicate["']/);
assert.match(source, /loading/);
assert.doesNotMatch(source, /uni\.scanCode|camera|摄像头/);
});
test("PDA 路由和工作台入口覆盖五类现场业务", async () => {
const pages = JSON.parse(
await readFile(path.join(appRoot, "src/pages.json"), "utf8"),
);
const pagePaths = new Set(pages.pages.map((page) => page.path));
for (const pagePath of [
"pages/business/inbound/index",
"pages/business/filling/index",
"pages/business/shipment/index",
"pages/business/usage/index",
"pages/business/return/index",
]) {
assert.equal(pagePaths.has(pagePath), true, `${pagePath} 路由缺失`);
}
const workSource = await readFile(
path.join(appRoot, "src/pages/work/index.vue"),
"utf8",
);
assert.match(workSource, /hasPermiOr/);
assert.match(workSource, /business:inbound/);
assert.match(workSource, /business:filling/);
assert.match(workSource, /business:shipment/);
assert.match(workSource, /business:usage/);
assert.match(workSource, /business:return/);
assert.match(workSource, /pages\/business\/inbound\/index/);
assert.match(workSource, /pages\/business\/filling\/index/);
assert.match(workSource, /pages\/business\/shipment\/index/);
assert.match(workSource, /pages\/business\/usage\/index/);
assert.match(workSource, /pages\/business\/return\/index/);
});
test("PDA 测试模式附加批次请求头并在五个业务页持续提示", async () => {
const requestSource = await readFile(
path.join(appRoot, "src/utils/request.js"),
"utf8",
);
assert.match(requestSource, /X-Test-Batch-Id/);
assert.match(requestSource, /TEST_BATCH_UNAVAILABLE/);
assert.match(requestSource, /uni\.\$emit\(["']test-batch-unavailable["']/);
assert.match(requestSource, /reLaunch\(\{\s*url:\s*["']\/pages\/work\/index["']/);
for (const page of ["inbound", "filling", "shipment", "usage", "return"]) {
const source = await readFile(
path.join(appRoot, `src/pages/business/${page}/index.vue`),
"utf8",
);
assert.match(source, /TestBatchBanner/);
}
});
test("PDA 不再暴露入库和发货草稿物理删除", async () => {
for (const file of ["src/api/business/inbound.js", "src/api/business/shipment.js"]) {
const source = await readFile(path.join(appRoot, file), "utf8");
assert.doesNotMatch(source, /delInbound|delShipment|method:\s*["']delete["']/);
}
for (const page of ["inbound", "shipment"]) {
const source = await readFile(
path.join(appRoot, `src/pages/business/${page}/index.vue`),
"utf8",
);
assert.doesNotMatch(source, /deleteDraft|deleteLoading|business:(?:inbound|shipment):remove/);
}
});
test("登录页只预填账号,不把管理员密码写入源码", async () => {
const source = await readFile(path.join(appRoot, "src/pages/login.vue"), "utf8");
assert.match(source, /username:\s*["']admin["']/);
assert.match(source, /password:\s*["']["']/);
assert.doesNotMatch(source, /password:\s*["'][^"']+["']/);
});
test("PDA 后端地址支持 VITE_APP_BASE_API 并保留本地默认值", async () => {
const source = await readFile(path.join(appRoot, "src/config.js"), "utf8");
assert.match(source, /import\.meta\.env\.VITE_APP_BASE_API/);
assert.match(source, /VITE_APP_BASE_API\s*\|\|\s*["']http:\/\/localhost:9099["']/);
});
test("入库页面遵循 UNSTOCKED 扫码、草稿和幂等确认契约", async () => {
const source = await readFile(
path.join(appRoot, "src/pages/business/inbound/index.vue"),
"utf8",
);
assert.match(source, /PalletScanInput/);
assert.match(source, /scanInboundPallet/);
assert.match(source, /UNSTOCKED/);
assert.match(source, /warehouseId/);
assert.match(source, /palletIds/);
assert.match(source, /getInbound\(/);
assert.match(source, /updateInbound/);
assert.match(source, /confirmInbound/);
assert.match(source, /idempotencyKey/);
assert.match(source, /business:inbound:(?:query|add|edit|confirm)/);
});
test("发货页面遵循来源仓库、目标现场和整单确认契约", async () => {
const source = await readFile(
path.join(appRoot, "src/pages/business/shipment/index.vue"),
"utf8",
);
assert.match(source, /PalletScanInput/);
assert.match(source, /scanShipmentPallet/);
assert.match(source, /FILLED_IN_WAREHOUSE/);
assert.match(source, /remainingPackages/);
assert.match(source, /sourceWarehouseId/);
assert.match(source, /targetSiteId/);
assert.match(source, /palletIds/);
assert.match(source, /getShipment\(/);
assert.match(source, /updateShipment/);
assert.match(source, /confirmShipment/);
assert.match(source, /idempotencyKey/);
assert.match(source, /business:shipment:(?:query|add|edit|confirm)/);
});
test("装填页面遵循空托盘状态和 FillingCreateModel 字段契约", async () => {
const source = await readFile(
path.join(appRoot, "src/pages/business/filling/index.vue"),
"utf8",
);
assert.match(source, /PalletScanInput/);
assert.match(source, /scanFillingPallet/);
assert.match(source, /EMPTY_IN_WAREHOUSE/);
for (const field of [
"qrToken",
"warehouseId",
"strainId",
"batchNo",
"packageSpec",
"initialPackages",
"idempotencyKey",
]) {
assert.match(source, new RegExp(field));
}
assert.match(source, /addFilling/);
assert.match(source, /business:filling:(?:query|add)/);
});
test("现场使用页面遵循产线绑定、余量和使用结果契约", async () => {
const source = await readFile(
path.join(appRoot, "src/pages/business/usage/index.vue"),
"utf8",
);
assert.match(source, /PalletScanInput/);
assert.match(source, /scanUsagePallet/);
assert.match(source, /AT_SITE_UNUSED/);
assert.match(source, /AT_SITE_PARTIAL/);
assert.match(source, /currentLineId/);
assert.match(source, /getUsageLineOptions/);
assert.match(source, /usedPackages/);
assert.match(source, /remainingPackages/);
assert.match(source, /flowState/);
assert.match(source, /addUsage/);
assert.match(source, /idempotencyKey/);
assert.match(source, /business:usage:(?:query|add)/);
});
test("退回页面实现申请与确认两阶段的集合和幂等契约", async () => {
const source = await readFile(
path.join(appRoot, "src/pages/business/return/index.vue"),
"utf8",
);
assert.match(source, /PalletScanInput/);
assert.match(source, /scanReturnPallet/);
assert.match(source, /mode:\s*["']request["']/);
assert.match(source, /mode:\s*["']confirm["']/);
assert.match(source, /sourceSiteId/);
assert.match(source, /targetWarehouseId/);
assert.match(source, /palletIds/);
assert.match(source, /scannedPalletIds/);
assert.match(source, /requestReturn/);
assert.match(source, /getReturn\(/);
assert.match(source, /confirmReturn/);
assert.match(source, /sameIdSet/);
assert.match(source, /REQUESTED/);
assert.match(source, /requestIdempotencyKey/);
assert.match(source, /confirmIdempotencyKey/);
assert.match(source, /business:return:(?:query|request|confirm)/);
});
function escapeRegExp(value) {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
async function importSource(relativePath) {
const source = await readFile(path.join(appRoot, relativePath), "utf8");
return import(`data:text/javascript;charset=utf-8,${encodeURIComponent(source)}`);
}
+3 -1
View File
@@ -42,7 +42,7 @@ JWT_REDIS_EXPIRE_MINUTES = 30
# -------- 数据库配置 --------
# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql'
# 数据库类型,固定使用'mysql'
DB_TYPE = 'mysql'
# 数据库主机
DB_HOST = '127.0.0.1'
@@ -171,3 +171,5 @@ TRANSPORT_CRYPTO_ENABLED_PATHS = ''
TRANSPORT_CRYPTO_REQUIRED_PATHS = ''
# 排除传输层加密的路径列表,多个值使用逗号分隔
TRANSPORT_CRYPTO_EXCLUDE_PATHS = '/openapi.json,/docs,/docs/oauth2-redirect,/redoc,/transport/crypto/frontend-config,/transport/crypto/public-key,/common/download,/common/download/resource'
# 测试批次在线清理最大数据行数;0 表示禁止在线清理
TEST_BATCH_ONLINE_PURGE_MAX_ROWS = 1000
+1 -1
View File
@@ -42,7 +42,7 @@ JWT_REDIS_EXPIRE_MINUTES = 30
# -------- 数据库配置 --------
# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql'
# 数据库类型,固定使用'mysql'
DB_TYPE = 'mysql'
# 数据库主机
DB_HOST = 'shierfeng-mysql'
-173
View File
@@ -1,173 +0,0 @@
# -------- 应用配置 --------
# 应用运行环境
APP_ENV = 'prod'
# 应用名称
APP_NAME = 'ShiErFeng-FastAPI'
# 应用代理路径
APP_ROOT_PATH = '/docker-api'
# 应用主机
APP_HOST = '0.0.0.0'
# 应用端口
APP_PORT = 9099
# 应用版本
APP_VERSION= '1.9.0'
# 应用是否开启热重载
APP_RELOAD = false
# 应用工作进程数
APP_WORKERS = 1
# 应用是否开启IP归属区域查询
APP_IP_LOCATION_QUERY = true
# 应用是否为演示模式
APP_DEMO_MODE = false
# 应用是否允许账号同时登录
APP_SAME_TIME_LOGIN = true
# 应用是否禁用Swagger文档
APP_DISABLE_SWAGGER = true
# 应用是否禁用ReDoc文档
APP_DISABLE_REDOC = true
# 可信代理IP列表,多个值使用逗号分隔
APP_TRUSTED_PROXY_IPS = '127.0.0.1,::1'
# 可信代理跳数,单层Nginx代理通常为1
APP_TRUSTED_PROXY_HOPS = 1
# -------- Jwt配置 --------
# Jwt秘钥
JWT_SECRET_KEY = 'b01c66dc2c58dc6a0aabfe2144256be36226de378bf87f72c0c795dda67f4d55'
# Jwt算法
JWT_ALGORITHM = 'HS256'
# 令牌过期时间
JWT_EXPIRE_MINUTES = 1440
# redis中令牌过期时间
JWT_REDIS_EXPIRE_MINUTES = 30
# -------- 数据库配置 --------
# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql'
DB_TYPE = 'postgresql'
# 数据库主机
DB_HOST = 'shierfeng-pg'
# 数据库端口
DB_PORT = 5432
# 数据库用户名
DB_USERNAME = 'postgres'
# 数据库密码
DB_PASSWORD = 'root'
# 数据库名称
DB_DATABASE = 'shierfeng-fastapi'
# 是否开启sqlalchemy日志
DB_ECHO = true
# 允许溢出连接池大小的最大连接数
DB_MAX_OVERFLOW = 10
# 连接池大小,0表示连接数无限制
DB_POOL_SIZE = 50
# 连接回收时间(单位:秒)
DB_POOL_RECYCLE = 3600
# 连接池中没有线程可用时,最多等待的时间(单位:秒)
DB_POOL_TIMEOUT = 30
# -------- Redis配置 --------
# Redis主机
REDIS_HOST = 'shierfeng-redis'
# Redis端口
REDIS_PORT = 6379
# Redis用户名
REDIS_USERNAME = ''
# Redis密码
REDIS_PASSWORD = ''
# Redis数据库
REDIS_DATABASE = 2
# -------- 日志配置 --------
# 是否启用日志脱敏
LOG_MASK_ENABLED = true
# 日志脱敏占位符
LOG_MASK_PLACEHOLDER = '******'
# 以下三项为互补关系(非互斥):
# 1) LOG_MASK_FIELDS:命中后执行全量脱敏
# 2) LOG_PARTIAL_MASK_FIELDS:命中后执行部分脱敏
# 3) LOG_CONFIG_SECRET_PATTERNS:按 configKey 关键词决定是否脱敏 configValue
# 全量脱敏字段,多个值使用逗号分隔
LOG_MASK_FIELDS = 'password,old_password,new_password,confirm_password,api_key,token,access_token,refresh_token,authorization,client_secret,secret,secret_key,private_key,private_key_pem,credential,credentials,sms_code,captcha_code,system_prompt'
# 部分脱敏字段,多个值使用逗号分隔
# 当前默认不对IP脱敏;如后期需要开启,可直接追加 ip,ipaddr,oper_ip,login_ip 并重启服务
LOG_PARTIAL_MASK_FIELDS = 'phonenumber,phone,mobile,email'
# 按配置键名识别敏感配置的关键词,多个值使用逗号分隔
LOG_CONFIG_SECRET_PATTERNS = 'password,token,secret,key,private,credential,access,jwt,captcha,sms'
# Redis Stream Key
LOG_STREAM_KEY = 'log:stream'
# Redis Stream 消费组名称
LOG_STREAM_GROUP = 'log_aggregator'
# Redis Stream 消费者名称前缀
LOG_STREAM_CONSUMER_PREFIX = 'worker'
# 每次读取的最大消息数量
LOG_STREAM_BATCH_SIZE = 100
# 阻塞读取等待时间(毫秒)
LOG_STREAM_BLOCK_MS = 2000
# Stream 最大长度(近似裁剪)
LOG_STREAM_MAXLEN = 100000
# Pending 回收最小空闲时间(毫秒)
LOG_STREAM_CLAIM_IDLE_MS = 60000
# Pending 回收检查间隔(毫秒)
LOG_STREAM_CLAIM_INTERVAL_MS = 5000
# 每次回收的最大消息数量
LOG_STREAM_CLAIM_BATCH_SIZE = 100
# 去重 Key 过期时间(秒)
LOG_STREAM_DEDUP_TTL = 3600
# 去重 Key 前缀
LOG_STREAM_DEDUP_PREFIX = 'log:dedup'
# stdout 输出是否为 JSON
LOGURU_JSON = false
# Loguru 最低输出级别
LOGURU_LEVEL = 'INFO'
# 是否输出到 stdout
LOGURU_STDOUT = true
# 是否启用文件日志
LOG_FILE_ENABLED = true
# 文件日志根目录
LOG_FILE_BASE_DIR = 'logs'
# 文件滚动策略
LOGURU_ROTATION = '50MB'
# 文件保留策略
LOGURU_RETENTION = '30 days'
# 文件压缩格式
LOGURU_COMPRESSION = 'zip'
# 实例标识(用于区分实例)
LOG_INSTANCE_ID = 'dockerpg'
# 服务名称(用于统一标识服务)
LOG_SERVICE_NAME = 'shierfeng-fastapi-backend'
# Worker 标识(auto 自动生成)
LOG_WORKER_ID = 'auto'
# -------- 传输层加解密配置 --------
# 是否启用传输层加解密
TRANSPORT_CRYPTO_ENABLED = true
# 传输层加解密模式:off=关闭,optional=明文/密文兼容,required=命中接口强制加密
TRANSPORT_CRYPTO_MODE = 'optional'
# 传输层加解密算法标识
TRANSPORT_CRYPTO_ALGORITHM = 'RSA_OAEP_AES_256_GCM'
# 当前启用的密钥版本标识
TRANSPORT_CRYPTO_KID = 'default'
# 传输层RSA位数,需与下方密钥对匹配
TRANSPORT_CRYPTO_RSA_KEY_SIZE = 4096
# 传输层公钥,默认提供一套可用示例值;Docker 部署前请替换为正式密钥
TRANSPORT_CRYPTO_PUBLIC_KEY = '-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwA2ooWpsxLzIVMJp7Wcv\nvR0Bu8paFn8NVPpzz+wGpUlwP5DGK6pBGItsglNMZx56MSYMp3zVyqB95XUVZ6Ub\nQVyHJ6BXXIMs/BpzcHCbyXR/wWG+pKxQ8UEwaHVhK8X21xW1R0kzzwhgMw51unEs\nA81kskVlDdGeNyaOJg5QuofEErCfR1y0e+iqd1PBpIwdEY5L+BzvbVtyhsPz6dBu\n9YbEbKs7JvNle5vjc72ebbMIeGejHFQRYxihuamPCAEylj1qqpHk8U+r+3icxQsj\n8F/TySLuOy37iVWfD+5ikLyou4ZDI3hOYnIYHl194ZM5xVyOGBD/xdqZadXTLqL6\nSrldwZfZDBl3EGgRby8yJqO6SqGgyvyGWXZAaHoPMmF+quu/nUooqnp0fpl+LCqX\nhK67kbYaA9xJeHRaP04cg16imB7sBIXBqzkyZtkhC2BtlL0h5X7dRlAddrQ23z6d\nWdJA3qe3iBSSM8pmedv+Jgfau/PFam2051HqFxvJEh/jnc6rq1aIjL/d4Kk5imIa\nQ6acv+v5N6QVFptlcx6I7j8yZJ7WUHZlB1IxVqfPb69+985eknZyLul60gyu0kPG\nYUecypUu2wiNDBAErZlUxEujMWgJDFYCSonHxtwr88gDInjP0lvwd/OgqjDQ7hSo\nRYxPhTbwo68RJDpImBjn+YsCAwEAAQ==\n-----END PUBLIC KEY-----'
# 传输层私钥,必须与上方公钥成对使用;Docker 部署前请替换为正式密钥
TRANSPORT_CRYPTO_PRIVATE_KEY = '-----BEGIN RSA PRIVATE KEY-----\nMIIJKAIBAAKCAgEAwA2ooWpsxLzIVMJp7WcvvR0Bu8paFn8NVPpzz+wGpUlwP5DG\nK6pBGItsglNMZx56MSYMp3zVyqB95XUVZ6UbQVyHJ6BXXIMs/BpzcHCbyXR/wWG+\npKxQ8UEwaHVhK8X21xW1R0kzzwhgMw51unEsA81kskVlDdGeNyaOJg5QuofEErCf\nR1y0e+iqd1PBpIwdEY5L+BzvbVtyhsPz6dBu9YbEbKs7JvNle5vjc72ebbMIeGej\nHFQRYxihuamPCAEylj1qqpHk8U+r+3icxQsj8F/TySLuOy37iVWfD+5ikLyou4ZD\nI3hOYnIYHl194ZM5xVyOGBD/xdqZadXTLqL6SrldwZfZDBl3EGgRby8yJqO6SqGg\nyvyGWXZAaHoPMmF+quu/nUooqnp0fpl+LCqXhK67kbYaA9xJeHRaP04cg16imB7s\nBIXBqzkyZtkhC2BtlL0h5X7dRlAddrQ23z6dWdJA3qe3iBSSM8pmedv+Jgfau/PF\nam2051HqFxvJEh/jnc6rq1aIjL/d4Kk5imIaQ6acv+v5N6QVFptlcx6I7j8yZJ7W\nUHZlB1IxVqfPb69+985eknZyLul60gyu0kPGYUecypUu2wiNDBAErZlUxEujMWgJ\nDFYCSonHxtwr88gDInjP0lvwd/OgqjDQ7hSoRYxPhTbwo68RJDpImBjn+YsCAwEA\nAQKCAgEAtH7hwjp8WPY3rPk+hqEYy7psO6q0ujnUNM5hc8MWh9caSJNuu/D51vCK\nHX3d63hITNK+x9ZaM2Jcj/9XC56vm+EzILngARFDgPf3EHC06UO1IfEUND3CoMqs\njS/sEDCwiXpccc/JgkUT7EgluwDL5hLuFWGE1NTxxlFU/U0s7/HTA+G9AFuPQHjt\nZNJxxozscOh0W44OM4/jdebJ4TBEaDqtdpgDMttDwEVFIizOrbi6ODbmpCQaZzDq\nJczGoTZG7c5w5jfRnD1NnDzB0apjr3DQYVOT5EiWA39Vy6o2NmMojX1ksfxKZtll\n83vYZ91vSR5waQvo5nFJB5+vJ0CCy4BZaV9/gQBP/OSElELfD0bGYidO7NURAJMW\njGc2B6uIog8BZ3ix02FO/30i5rWeDWM7McLol8+IP0Qcg473YvrCgmRZpprdc9HT\nHnB6BgIwu0ZBoP7CxW7pBm0ApwmOf7OvUdAu68kFQ4KxABuv+Qegu0vSsktBtmIs\ngUDzu/ekoayyOvFHVwVTd4QKOSa2gXb3TS7PP22j6QLL1OPy2fK2NBW0xrRDIgtw\nSx3Yo0dxCYkxJWz1nQYsdIjZbz2/xQPZZQ5yNeePwxaOKyDuA50elN86I9RR2gjL\nh9QMrvPG7DOlgmBG9+JsydQZf00G+x45Su/1fydA09X3AFtZLkkCggEBAOj8NY/x\n3G3/1qAkrcQYLwB0mjLNkgKchRIP8NMildk0nSub5SRUxleW2wp0kM0WqkFTXLMa\nFR0qCRjiyPOtBBZxLobIfGc6568LTKfg4N7VsCeAcTjFjSOE57iX5XzwhTy6ZCKe\nZFGFWfhj/a9lNQHneTcklDHq/oHjLJQ1FacbWNycIOX2Hk7SZKyJvyMutAem3BI+\nm5SLyj5648N2ylmz6f3eaTn8CyNCrUKWnPriQZfV0XF/Aalh4sq/I3fI6pqnYkHK\nuSoG9YHujGXKN2iOV/0krCiGj94l7JqvKGs4ZRoZdD+s1EugGD7qBK1wGATuEseg\nR6mS74ylgD88JPcCggEBANMGWrqhHOAtGeIewLbNob54+nqdwU/O+zk0RcTZErcD\naRZMTLPRlpdbgWbNgdfjFnbUx0WmIeTIboD2MaW5KOnDfV/x+eRhGtEmtNRvHA/o\nHK6uYzok7Ekm7oc298CYrfRbEWVx3m4+mHmU+rsvBeof664zpEEIsSwm+NaAnjz8\nru0U8xw8KWLB8F/Q4J4p4D0yVKCmAXmrrTgEYm1H355JlAlmiu6t6YPS2Xd+gNFD\ntWBsQXYnxEZyPhoD1Q4SQjQmQMEN7+lIHm8f/nMwwUkAd3y6D1w/Uu81Gqa/9eAh\nz3woK++tj/U1CMMTWXJumIyJdH28CWQJa9VdJBoFbw0CggEAdIBhPDhh1DNhHDUb\nGvpIzn5/+LVotJuVwwFrl/gsXC9+BCdxPmiRwYyyvRiqq5MQ0ZegvAJn2myBngsR\nFyBF8f7omAc6hdgjsBkDXNMLPwI1kpscgpnuSHuV720tGPugdExz9Ael/EmlQpql\naQY/qlMX/uXwoMF0QHjbesTMrgHzvmTn4nXek+WK5+f9Rtd8uHLMiub5nx8Do5iJ\nudz1tENN119W2OLaougdgTWVC7MFv6nwkENFDnDfGijX0HcMMQdQD7wSORy/uRgS\n5ndmm4bKItAqsh0PZbMrC/JYUL0jeRiPU6PViHdmiFc2vY9Ww2hUxbO1Aetyk67S\nYUxu4wKCAQAvSOQ5n3JV9SUwms156LfOc1NE+GZhmLKITeM4SZ+87IG2omAphtQk\nlDd5rqDinBrjg6gnPiOoHRVNxly3krbNMqW8Qv9Iok2dAfxRAZibI9qRdbf8Rlu/\nxH58Q9/eAxgvgdxzC8HYmCQYUj6ghNfhb0ejICU1AVqZ1x25CtbqOYCE1UXoVL69\nR1GyVp6OMjnx3H5EBQ6dkc9dlvXrIMjFshz+wkBtXQDPLgbWlL0OpwpUUc2VSTHc\nyyqJL8Skw4icINovqAzTC/rt0ZB1hT46OmWLyDE67WGLAi43oRnaIBla67F0okJ4\nomqVM5e+YXPDQeWdau37wXStOZKmVgNdAoIBADojGo0h9mBgnr+u1oYB+mKx6LVD\n3TTy45IB1ikqprBnSjgXNbQycsTbl+qDo5ge+KqlPNk6Scvn0L7k43/VB9Y5qK2s\nBgxa1KgdeC5WUNU0rs/1UKIODA5SlWIk6JqekiAE+glljVZ5E53l93gPL3uRcvr5\nSD5CPe+qqoBh9nYIRJDogP0e2xV11EuE10j1WxuLkHL5//hePGPpgnb0/rZkP+vb\nkzwz1fTv88kQDnRk6uIe0L78iFTpEwAnlDmuMJ4KafKnujaR5VVCoI7bwryCp4+f\n8zyU7ZpKo/2EE8bYmxHMDPiYByJxCwAbm2Xn7Kw4H/17MLJOxg8685A8jyA=\n-----END RSA PRIVATE KEY-----'
# 历史密钥对配置,JSON数组格式,密钥轮换说明见 docs/transport_crypto_deployment.md
TRANSPORT_CRYPTO_LEGACY_KEY_PAIRS = '[]'
# 公钥缓存有效期(秒)
TRANSPORT_CRYPTO_PUBLIC_KEY_TTL_SECONDS = 3600
# 前端传输加密策略缓存有效期(秒)
TRANSPORT_CRYPTO_FRONTEND_CONFIG_TTL_SECONDS = 300
# GET/DELETE 请求参数加密后的最大 URL 长度
TRANSPORT_CRYPTO_MAX_GET_URL_LENGTH = 4096
# 请求时间窗允许偏差(秒)
TRANSPORT_CRYPTO_CLOCK_SKEW_SECONDS = 120
# 防重放随机数有效期(秒)
TRANSPORT_CRYPTO_REPLAY_TTL_SECONDS = 300
# 启用传输层加密的路径列表,多个值使用逗号分隔,留空表示默认全部启用
TRANSPORT_CRYPTO_ENABLED_PATHS = ''
# 强制要求传输层加密的路径列表,多个值使用逗号分隔
TRANSPORT_CRYPTO_REQUIRED_PATHS = ''
# 排除传输层加密的路径列表,多个值使用逗号分隔
TRANSPORT_CRYPTO_EXCLUDE_PATHS = '/openapi.json,/docs,/docs/oauth2-redirect,/redoc,/transport/crypto/frontend-config,/transport/crypto/public-key,/common/download,/common/download/resource'
+3 -1
View File
@@ -42,7 +42,7 @@ JWT_REDIS_EXPIRE_MINUTES = 30
# -------- 数据库配置 --------
# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql'
# 数据库类型,固定使用'mysql'
DB_TYPE = 'mysql'
# 数据库主机
DB_HOST = '127.0.0.1'
@@ -171,3 +171,5 @@ TRANSPORT_CRYPTO_ENABLED_PATHS = ''
TRANSPORT_CRYPTO_REQUIRED_PATHS = ''
# 排除传输层加密的路径列表,多个值使用逗号分隔
TRANSPORT_CRYPTO_EXCLUDE_PATHS = '/openapi.json,/docs,/docs/oauth2-redirect,/redoc,/transport/crypto/frontend-config,/transport/crypto/public-key,/common/download,/common/download/resource'
# 测试批次在线清理最大数据行数;0 表示禁止在线清理
TEST_BATCH_ONLINE_PURGE_MAX_ROWS = 1000
-14
View File
@@ -1,14 +0,0 @@
FROM python:3.10
WORKDIR /app
# 复制源代码
COPY . .
# 安装依赖
RUN pip install --no-cache-dir -r requirements-pg.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
# 暴露端口
EXPOSE 9099
# 启动命令
CMD ["shierfeng", "app", "run", "--env=dockerpg"]
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from pathlib import Path
DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy', 'dockerpg')
DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy')
@dataclass(frozen=True)
@@ -28,7 +28,7 @@ GENERAL_COPY = {
'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回',
'more_detail_hint': '> 进入对应页面查看更多',
'tui_command_help': '进入只读巡检工作台',
'tui_missing_dependency_hint': '请重新执行 `pip install -r requirements.txt` 或 `pip install -r requirements-pg.txt`',
'tui_missing_dependency_hint': '请重新执行 `pip install -r requirements.txt`',
'tui_missing_dependency_message': '当前环境未安装 TUI 可选依赖,无法启动 `shierfeng tui`',
}
@@ -1,7 +1,7 @@
from dataclasses import dataclass
from pathlib import Path
DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy', 'dockerpg')
DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy')
@dataclass(frozen=True)
@@ -28,7 +28,7 @@ GENERAL_COPY = {
'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回',
'more_detail_hint': '> 进入对应页面查看更多',
'tui_command_help': '进入只读巡检工作台',
'tui_missing_dependency_hint': '请重新执行 `pip install -r requirements.txt` 或 `pip install -r requirements-pg.txt`',
'tui_missing_dependency_hint': '请重新执行 `pip install -r requirements.txt`',
'tui_missing_dependency_message': '当前环境未安装 TUI 可选依赖,无法启动 `shierfeng tui`',
}
+6 -146
View File
@@ -1,4 +1,3 @@
from config.env import DataBaseConfig
class CommonConstant:
@@ -549,32 +548,10 @@ class GenConstant:
TREE_NAME = 'treeName'
PARENT_MENU_ID = 'parentMenuId'
PARENT_MENU_NAME = 'parentMenuName'
COLUMNTYPE_STR = (
['character varying', 'varchar', 'character', 'char']
if DataBaseConfig.db_type == 'postgresql'
else ['char', 'varchar', 'nvarchar', 'varchar2']
)
COLUMNTYPE_TEXT = (
['text', 'citext'] if DataBaseConfig.db_type == 'postgresql' else ['tinytext', 'text', 'mediumtext', 'longtext']
)
COLUMNTYPE_TIME = (
[
'date',
'time',
'time with time zone',
'time without time zone',
'timestamp',
'timestamp with time zone',
'timestamp without time zone',
'interval',
]
if DataBaseConfig.db_type == 'postgresql'
else ['datetime', 'time', 'date', 'timestamp']
)
COLUMNTYPE_GEOMETRY = (
['point', 'line', 'lseg', 'box', 'path', 'polygon', 'circle']
if DataBaseConfig.db_type == 'postgresql'
else [
COLUMNTYPE_STR = ['char', 'varchar', 'nvarchar', 'varchar2']
COLUMNTYPE_TEXT = ['tinytext', 'text', 'mediumtext', 'longtext']
COLUMNTYPE_TIME = ['datetime', 'time', 'date', 'timestamp']
COLUMNTYPE_GEOMETRY = [
'geometry',
'point',
'linestring',
@@ -584,7 +561,6 @@ class GenConstant:
'multipolygon',
'geometrycollection',
]
)
COLUMNTYPE_NUMBER = [
'tinyint',
'smallint',
@@ -619,64 +595,7 @@ class GenConstant:
QUERY_LIKE = 'LIKE'
QUERY_EQ = 'EQ'
REQUIRE = '1'
DB_TO_SQLALCHEMY_TYPE_MAPPING = (
{
'boolean': 'Boolean',
'smallint': 'SmallInteger',
'integer': 'Integer',
'bigint': 'BigInteger',
'real': 'Float',
'double precision': 'Float',
'numeric': 'Numeric',
'character varying': 'String',
'character': 'String',
'text': 'Text',
'bytea': 'LargeBinary',
'date': 'Date',
'time': 'Time',
'time with time zone': 'Time',
'time without time zone': 'Time',
'timestamp': 'DateTime',
'timestamp with time zone': 'DateTime',
'timestamp without time zone': 'DateTime',
'interval': 'Interval',
'json': 'JSON',
'jsonb': 'JSONB',
'uuid': 'Uuid',
'inet': 'INET',
'cidr': 'CIDR',
'macaddr': 'MACADDR',
'point': 'Geometry',
'line': 'Geometry',
'lseg': 'Geometry',
'box': 'Geometry',
'path': 'Geometry',
'polygon': 'Geometry',
'circle': 'Geometry',
'bit': 'Bit',
'bit varying': 'Bit',
'tsvector': 'TSVECTOR',
'tsquery': 'TSQUERY',
'xml': 'String',
'array': 'ARRAY',
'composite': 'JSON',
'enum': 'Enum',
'range': 'Range',
'money': 'Numeric',
'pg_lsn': 'BigInteger',
'txid_snapshot': 'String',
'oid': 'BigInteger',
'regproc': 'String',
'regclass': 'String',
'regtype': 'String',
'regrole': 'String',
'regnamespace': 'String',
'int2vector': 'ARRAY',
'oidvector': 'ARRAY',
'pg_node_tree': 'Text',
}
if DataBaseConfig.db_type == 'postgresql'
else {
DB_TO_SQLALCHEMY_TYPE_MAPPING = {
# 数值类型
'TINYINT': 'SmallInteger',
'SMALLINT': 'SmallInteger',
@@ -722,65 +641,7 @@ class GenConstant:
'MULTIPOLYGON': 'Geometry',
'GEOMETRYCOLLECTION': 'Geometry',
}
)
DB_TO_PYTHON_TYPE_MAPPING = (
{
'boolean': 'bool',
'smallint': 'int',
'integer': 'int',
'bigint': 'int',
'real': 'float',
'double precision': 'float',
'numeric': 'Decimal',
'character varying': 'str',
'character': 'str',
'text': 'str',
'bytea': 'bytes',
'date': 'date',
'time': 'time',
'time with time zone': 'time',
'time without time zone': 'time',
'timestamp': 'datetime',
'timestamp with time zone': 'datetime',
'timestamp without time zone': 'datetime',
'interval': 'timedelta',
'json': 'dict',
'jsonb': 'dict',
'uuid': 'str',
'inet': 'str',
'cidr': 'str',
'macaddr': 'str',
'point': 'list',
'line': 'list',
'lseg': 'list',
'box': 'list',
'path': 'list',
'polygon': 'list',
'circle': 'list',
'bit': 'int',
'bit varying': 'int',
'tsvector': 'str',
'tsquery': 'str',
'xml': 'str',
'array': 'list',
'composite': 'dict',
'enum': 'str',
'range': 'list',
'money': 'Decimal',
'pg_lsn': 'int',
'txid_snapshot': 'str',
'oid': 'int',
'regproc': 'str',
'regclass': 'str',
'regtype': 'str',
'regrole': 'str',
'regnamespace': 'str',
'int2vector': 'list',
'oidvector': 'list',
'pg_node_tree': 'str',
}
if DataBaseConfig.db_type == 'postgresql'
else {
DB_TO_PYTHON_TYPE_MAPPING = {
# 数值类型
'TINYINT': 'int',
'SMALLINT': 'int',
@@ -826,4 +687,3 @@ class GenConstant:
'MULTIPOLYGON': 'bytes',
'GEOMETRYCOLLECTION': 'bytes',
}
)
@@ -13,11 +13,6 @@ def build_async_sqlalchemy_database_url() -> str:
:return: 异步 SQLAlchemy 数据库连接 URL
"""
if DataBaseConfig.db_type == 'postgresql':
return (
f'postgresql+asyncpg://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
return (
f'mysql+asyncmy://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
@@ -33,11 +28,6 @@ def build_sync_sqlalchemy_database_url() -> str:
:return: 同步 SQLAlchemy 数据库连接 URL
"""
if DataBaseConfig.db_type == 'postgresql':
return (
f'postgresql+psycopg2://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
)
return (
f'mysql+pymysql://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
+1 -3
View File
@@ -47,7 +47,7 @@ class DataBaseSettings(BaseSettings):
数据库配置
"""
db_type: Literal['mysql', 'postgresql'] = 'mysql'
db_type: Literal['mysql'] = 'mysql'
db_host: str = '127.0.0.1'
db_port: int = 3306
db_username: str = 'root'
@@ -62,8 +62,6 @@ class DataBaseSettings(BaseSettings):
@computed_field
@property
def sqlglot_parse_dialect(self) -> str:
if self.db_type == 'postgresql':
return 'postgres'
return self.db_type
+5 -13
View File
@@ -38,23 +38,16 @@ shierfeng --help
### 2.2 安装依赖
MySQL 版本:
安装依赖(统一使用 MySQL):
```bash
cd shierfeng-fastapi-backend
pip3 install -r requirements.txt
```
PostgreSQL 版本:
```bash
cd shierfeng-fastapi-backend
pip3 install -r requirements-pg.txt
```
说明:
- `requirements*.txt` 已包含当前项目自身安装项 `.`,因此不需要额外执行 `pip install -e .`
- `requirements.txt` 已包含当前项目自身安装项 `.`,因此不需要额外执行 `pip install -e .`
- 安装完成后,`shierfeng` 会随当前 Python 环境一起可用
如果本地使用 Conda,推荐先进入项目环境再执行命令:
@@ -65,7 +58,7 @@ cd shierfeng-fastapi-backend
shierfeng --help
```
`textual` 已包含在现有依赖文件中,因此安装 `requirements.txt` 或 `requirements-pg.txt` 后即可直接使用 TUI。
`textual` 已包含在现有依赖文件中,安装 `requirements.txt` 后即可直接使用 TUI。
### 2.3 第一个命令
@@ -104,7 +97,6 @@ CLI 不单独维护配置系统,仍然复用项目原有的 `config/env.py`
- `--env=dev` -> `.env.dev`
- `--env=prod` -> `.env.prod`
- `--env=dockermy` -> `.env.dockermy`
- `--env=dockerpg` -> `.env.dockerpg`
### 3.3 帮助命令
@@ -494,7 +486,7 @@ shierfeng tui --env=prod
- 当前 TUI 是只读巡检工作台,页面内的写操作入口会通过确认弹窗或向导二次确认
- 页面切换快捷键为 `D/A/O/B/C/T/G/P/E`,分别对应总览、应用、运维、数据库、缓存、任务、代码生成、参数配置、加密
- 通用快捷键包括 `R` 刷新、`Q` 退出、`S` 聚焦侧栏、`←/→` 切换焦点或区域、`J/K` 滚动、`PgUp/PgDn` 翻页、`Home/End` 首尾跳转
- 若当前 Python 环境缺少 TUI 依赖,`shierfeng tui` 会返回失败结果并提示重新执行 `pip install -r requirements.txt` 或 `pip install -r requirements-pg.txt`
- 若当前 Python 环境缺少 TUI 依赖,`shierfeng tui` 会返回失败结果并提示重新执行 `pip install -r requirements.txt`
## 6. 危险命令清单
@@ -814,7 +806,7 @@ shierfeng ops health --env=dev --output=json
请依次确认:
- 当前目录是否为 `shierfeng-fastapi-backend`
- 当前 Python 环境是否执行过 `pip install -r requirements.txt` 或 `pip install -r requirements-pg.txt`
- 当前 Python 环境是否执行过 `pip install -r requirements.txt`
- 当前终端是否真的使用了安装依赖的那个 Python/Conda 环境
### 8.2 命令报数据库或 Redis 连接失败
@@ -64,23 +64,20 @@ TRANSPORT_CRYPTO_MAX_GET_URL_LENGTH=4096
当前项目的 Docker 部署使用:
- `shierfeng-fastapi-test/docker-compose.test.my.yml` + `shierfeng-fastapi-backend/Dockerfile.my`
- `shierfeng-fastapi-test/docker-compose.test.pg.yml` + `shierfeng-fastapi-backend/Dockerfile.pg`
后端容器启动命令分别是:
- `shierfeng app run --env=dockermy`
- `shierfeng app run --env=dockerpg`
所以 Docker 环境需要直接在以下文件中配置传输层密钥:
- `shierfeng-fastapi-backend/.env.dockermy`
- `shierfeng-fastapi-backend/.env.dockerpg`
配置方式与生产环境相同;`.env.dockermy` / `.env.dockerpg` 里也已经默认提供一套可用示例值,正式部署前请替换为正式密钥。
配置方式与生产环境相同;`.env.dockermy` 里已经默认提供一套可用示例值,正式部署前请替换为正式密钥。
使用时只需要:
1. 修改对应的 `.env.dockermy` 或 `.env.dockerpg`
1. 修改 `.env.dockermy`
2. 重新构建并启动 Docker 服务
## 密钥生成
@@ -8,3 +8,40 @@
2026-09-20 10:04:32.035 | 1d12b62bcc9b41c191fe086905a49beb | b1fdb9fba55447d8976b3ed8c2bc0280 | 2f4a44c679a34d8781a45191abfa7987 | 16993-cd71f0 | ERROR | common.annotation.log_annotation:wrapper:199 - 新增用户admin1失败,邮箱账号已存在
2026-09-20 10:04:43.176 | e3982edb2a9a474aba72beef8bf68e9f | ab43381480ee4fda9808645d08c25635 | 537175b887df487eb1b7e6739de1c9da | 16993-cd71f0 | ERROR | common.annotation.log_annotation:wrapper:199 - 新增用户shierfeng失败,邮箱账号已存在
2026-09-20 10:05:45.737 | a2482c9df9f649259d08e3642bdf0488 | e66b674fdac647e4b0ef9c54851001d9 | 5de9f2b06af74d5396289bb3ea8ec2b8 | 16993-cd71f0 | ERROR | common.annotation.log_annotation:wrapper:199 - 新密码不能与旧密码相同
2026-09-20 11:42:14.773 | | | | 31890-bb233f | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-784' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.136 seconds
2026-09-20 11:42:16.249 | | | | 31890-bb233f | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-964' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.105 seconds
2026-09-20 12:17:22.659 | | | | 57933-537a04 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-13' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.113 seconds
2026-09-20 12:17:29.067 | | | | 58127-ed7958 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-964' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.105 seconds
2026-09-20 12:46:48.547 | 5d5c50d3b58b455aa80a68c91a1a5b62 | ae9e09d7e564480ebeb91e41fdcd4b6d | 77fe7828932949f894e7c4cd8887646b | 16993-cd71f0 | WARNING | module_admin.service.login_service:__check_login_captcha:169 - 验证码已失效
2026-09-20 12:46:48.549 | 5d5c50d3b58b455aa80a68c91a1a5b62 | ae9e09d7e564480ebeb91e41fdcd4b6d | 77fe7828932949f894e7c4cd8887646b | 16993-cd71f0 | WARNING | common.annotation.log_annotation:wrapper:194 - 验证码已失效
2026-09-20 13:18:52.359 | dd3c9b48716a4a58b31b4625f20634aa | 13c18f6b346d4cdf99632eb435cf2d87 | 21419c5c356d438a8e159b3010860caa | 16993-cd71f0 | WARNING | module_admin.service.login_service:get_current_user:279 - 用户token已失效,请重新登录
2026-09-20 17:47:23.214 | | | | 58041-740809 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-181' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.177 seconds
2026-09-20 17:47:23.620 | | | | 58041-740809 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-247' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.109 seconds
2026-09-20 17:47:23.869 | | | | 58041-740809 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-283' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.121 seconds
2026-09-20 17:49:35.457 | | | | 60128-363e41 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-784' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.110 seconds
2026-09-20 17:50:37.968 | | | | 61359-b363d2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-784' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.113 seconds
2026-09-20 17:53:57.014 | | | | 64317-1bf7cd | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-76' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.129 seconds
2026-09-20 17:53:57.604 | | | | 64317-1bf7cd | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-181' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.175 seconds
2026-09-20 17:54:02.489 | | | | 64317-1bf7cd | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-964' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.124 seconds
2026-09-20 18:02:59.450 | | | | 72520-28953b | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-181' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.164 seconds
2026-09-20 18:03:00.429 | | | | 72520-28953b | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-289' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.137 seconds
2026-09-20 18:03:05.635 | | | | 72520-28953b | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-784' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.283 seconds
2026-09-20 18:03:07.372 | | | | 72520-28953b | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-964' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.139 seconds
2026-09-20 18:09:24.200 | | | | 80215-4e32b1 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-253' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.158 seconds
2026-09-20 18:09:28.242 | | | | 80215-4e32b1 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-772' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.105 seconds
2026-09-20 18:09:29.458 | | | | 80215-4e32b1 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-994' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.106 seconds
2026-09-20 18:14:10.968 | | | | 84308-7ecd65 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-676' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.120 seconds
2026-09-20 18:14:13.598 | | | | 84308-7ecd65 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-979' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.114 seconds
2026-09-20 18:20:04.515 | | | | 87818-33a210 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-979' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.109 seconds
2026-09-20 18:29:21.351 | | | | 92649-eff25d | WARNING | module_admin.service.login_service:authenticate_user:110 - 打印User:$2b$12$sJ2mSJgH2GsXKAfijj1/yu.6Pks28OyfkpLSii0DKf5nsXfi6O2t6
2026-09-20 18:29:21.590 | | | | 92649-eff25d | WARNING | module_admin.service.login_service:authenticate_user:111 - 打印User:False
2026-09-20 18:29:21.591 | | | | 92649-eff25d | WARNING | module_admin.service.login_service:authenticate_user:135 - 密码错误
2026-09-20 18:29:48.210 | | | | 93061-767fb0 | WARNING | module_admin.service.login_service:authenticate_user:110 - 打印User:$2b$12$gXCowPRYJUknyms/qz3KEOjHNaFdlszai/ptNLG8kca3C1daZ9xey
2026-09-20 18:29:48.429 | | | | 93061-767fb0 | WARNING | module_admin.service.login_service:authenticate_user:111 - 打印User:False
2026-09-20 18:29:48.430 | | | | 93061-767fb0 | WARNING | module_admin.service.login_service:authenticate_user:135 - 密码错误
2026-09-20 18:30:16.941 | | | | 93497-f06833 | WARNING | module_admin.service.login_service:authenticate_user:133 - 密码错误
2026-09-20 18:30:31.597 | | | | 93971-584c3b | WARNING | module_admin.service.login_service:authenticate_user:133 - 密码错误
2026-09-20 18:30:56.162 | | | | 94357-625365 | WARNING | module_admin.service.login_service:authenticate_user:133 - 密码错误
2026-09-20 18:59:56.301 | | | | 16082-90d8eb | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-652' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.134 seconds
2026-09-20 20:59:08.538 | | | | 94089-caeb0d | WARNING | config.get_scheduler:on_lock_lost:273 - ⚠️ Worker 94089-caeb0d 失去 Application 锁
2026-09-20 21:25:50.212 | cb2c7654e5b94cde929029eaf4b267ee | 6fe2f1d9479d4b3c8a77a4f50f788af9 | 69c6ef438e3f45e298848ceef5c322c5 | 94089-caeb0d | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,32 @@
2026-09-21 18:40:56.930 | | | | 61855-bf03aa | ERROR | sqlalchemy.pool.base:_close_connection:376 - Exception closing connection <AdaptedConnection <asyncmy.connection.Connection object at 0x116e83310>>
Traceback (most recent call last):
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 374, in _close_connection
self._dialect.do_close(connection)
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 721, in do_close
dbapi_connection.close()
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/dialects/mysql/asyncmy.py", line 114, in close
self.await_(self._connection.ensure_closed())
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only
return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn
value = await result
File "asyncmy/connection.pyx", line 367, in ensure_closed
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/streams.py", line 343, in wait_closed
await self._protocol._get_close_waiter(self)
BrokenPipeError: [Errno 32] Broken pipe
2026-09-21 18:40:57.080 | | | | 61855-bf03aa | ERROR | sqlalchemy.pool.base:_close_connection:376 - Exception closing connection <AdaptedConnection <asyncmy.connection.Connection object at 0x116c77e80>>
Traceback (most recent call last):
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/pool/base.py", line 374, in _close_connection
self._dialect.do_close(connection)
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/engine/default.py", line 721, in do_close
dbapi_connection.close()
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/dialects/mysql/asyncmy.py", line 114, in close
self.await_(self._connection.ensure_closed())
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 132, in await_only
return current.parent.switch(awaitable) # type: ignore[no-any-return,attr-defined] # noqa: E501
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/site-packages/sqlalchemy/util/_concurrency_py3k.py", line 196, in greenlet_spawn
value = await result
File "asyncmy/connection.pyx", line 367, in ensure_closed
File "/Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/streams.py", line 343, in wait_closed
await self._protocol._get_close_waiter(self)
BrokenPipeError: [Errno 32] Broken pipe
@@ -0,0 +1,193 @@
2026-09-21 10:13:52.818 | | | | 61855-bf03aa | INFO | server:lifespan:90 - ⏰️ ShiErFeng-FastAPI开始启动
2026-09-21 10:13:52.819 | | | | 61855-bf03aa | INFO | utils.common_util:worship:22 -
////////////////////////////////////////////////////////////////////
// _ooOoo_ //
// o8888888o //
// 88" . "88 //
// (| ^_^ |) //
// O\ = /O //
// ____/`---'\____ //
// .' \\| |// `. //
// / \\||| : |||// \ //
// / _||||| -:- |||||- \ //
// | | \\\ - /// | | //
// | \_| ''\---/'' | | //
// \ .-\__ `-` ___/-. / //
// ___`. .' /--.--\ `. . ___ //
// ."" '< `.___\_<|>_/___.' >'"". //
// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
// \ \ `-. \_ __\ /__ _/ .-` / / //
// ========`-.____`-.___\_____/___.-`____.-'======== //
// `=---=' //
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
// 佛祖保佑 永不宕机 永无BUG //
////////////////////////////////////////////////////////////////////
2026-09-21 10:13:52.821 | | | | 61855-bf03aa | INFO | config.get_db:init_create_table:25 - 🔎 初始化数据库连接...
2026-09-21 10:13:52.895 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DATABASE()
2026-09-21 10:13:52.895 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.897 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT @@sql_mode
2026-09-21 10:13:52.898 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.899 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT @@lower_case_table_names
2026-09-21 10:13:52.899 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.901 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - BEGIN (implicit)
2026-09-21 10:13:52.901 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_config`
2026-09-21 10:13:52.901 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.965 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_dict_type`
2026-09-21 10:13:52.965 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.969 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_dict_data`
2026-09-21 10:13:52.969 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.971 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_job`
2026-09-21 10:13:52.972 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.973 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_job_log`
2026-09-21 10:13:52.973 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.976 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_logininfor`
2026-09-21 10:13:52.976 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.976 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_oper_log`
2026-09-21 10:13:52.977 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.978 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_dept`
2026-09-21 10:13:52.978 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.984 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_user`
2026-09-21 10:13:52.984 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.986 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_user_role`
2026-09-21 10:13:52.986 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.987 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_user_post`
2026-09-21 10:13:52.987 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.988 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_menu`
2026-09-21 10:13:52.989 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.991 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_post`
2026-09-21 10:13:52.991 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.992 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_role`
2026-09-21 10:13:52.992 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.994 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_role_dept`
2026-09-21 10:13:52.994 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.995 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_role_menu`
2026-09-21 10:13:52.995 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.997 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`sys_notice`
2026-09-21 10:13:52.997 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.997 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_strain`
2026-09-21 10:13:52.998 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:52.999 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_warehouse`
2026-09-21 10:13:52.999 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.001 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_customer`
2026-09-21 10:13:53.001 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.002 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_customer_site`
2026-09-21 10:13:53.002 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.003 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_production_line`
2026-09-21 10:13:53.003 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.004 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_pallet`
2026-09-21 10:13:53.004 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.005 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_user_warehouse`
2026-09-21 10:13:53.005 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.006 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_user_site`
2026-09-21 10:13:53.006 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.007 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_inbound_order`
2026-09-21 10:13:53.007 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.008 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_inbound_item`
2026-09-21 10:13:53.008 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.009 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_filling_record`
2026-09-21 10:13:53.009 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.011 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_shipment_order`
2026-09-21 10:13:53.011 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.013 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_shipment_item`
2026-09-21 10:13:53.013 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.014 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_usage_record`
2026-09-21 10:13:53.015 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.016 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_return_order`
2026-09-21 10:13:53.016 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.017 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_return_item`
2026-09-21 10:13:53.017 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.019 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_pallet_inventory`
2026-09-21 10:13:53.019 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.020 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`biz_pallet_event`
2026-09-21 10:13:53.020 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.022 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`gen_table`
2026-09-21 10:13:53.022 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.023 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - DESCRIBE `shierfeng-fastapi`.`gen_table_column`
2026-09-21 10:13:53.023 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [raw sql] ()
2026-09-21 10:13:53.024 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - COMMIT
2026-09-21 10:13:53.025 | | | | 61855-bf03aa | INFO | config.get_db:init_create_table:28 - ✅️ 数据库连接成功
2026-09-21 10:13:53.025 | | | | 61855-bf03aa | INFO | config.get_redis:check_redis_connection:57 - 🔎 开始连接redis...
2026-09-21 10:13:53.027 | | | | 61855-bf03aa | INFO | config.get_redis:check_redis_connection:63 - ✅️ redis连接成功
2026-09-21 10:13:53.031 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - BEGIN (implicit)
2026-09-21 10:13:53.050 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT sys_dict_type.dict_id, sys_dict_type.dict_name, sys_dict_type.dict_type, sys_dict_type.status, sys_dict_type.create_by, sys_dict_type.create_time, sys_dict_type.update_by, sys_dict_type.update_time, sys_dict_type.remark
FROM sys_dict_type
2026-09-21 10:13:53.050 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [generated in 0.00032s] ()
2026-09-21 10:13:53.058 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.058 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [generated in 0.00030s] ('0', 'sys_user_sex', '0')
2026-09-21 10:13:53.062 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.063 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.004945s ago] ('0', 'sys_show_hide', '0')
2026-09-21 10:13:53.065 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.066 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.007828s ago] ('0', 'sys_normal_disable', '0')
2026-09-21 10:13:53.071 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.071 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.01375s ago] ('0', 'sys_job_status', '0')
2026-09-21 10:13:53.074 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.074 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.01605s ago] ('0', 'sys_job_group', '0')
2026-09-21 10:13:53.079 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.079 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.02133s ago] ('0', 'sys_job_executor', '0')
2026-09-21 10:13:53.082 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.082 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.02433s ago] ('0', 'sys_yes_no', '0')
2026-09-21 10:13:53.084 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.084 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.02646s ago] ('0', 'sys_notice_type', '0')
2026-09-21 10:13:53.087 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.087 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.02908s ago] ('0', 'sys_notice_status', '0')
2026-09-21 10:13:53.090 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.090 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.03221s ago] ('0', 'sys_oper_type', '0')
2026-09-21 10:13:53.093 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_dict_data.dict_code, sys_dict_data.dict_sort, sys_dict_data.dict_label, sys_dict_data.dict_value, sys_dict_data.dict_type, sys_dict_data.css_class, sys_dict_data.list_class, sys_dict_data.is_default, sys_dict_data.status, sys_dict_data.create_by, sys_dict_data.create_time, sys_dict_data.update_by, sys_dict_data.update_time, sys_dict_data.remark
FROM sys_dict_type LEFT OUTER JOIN sys_dict_data ON sys_dict_type.dict_type = sys_dict_data.dict_type AND sys_dict_data.status = %s
WHERE sys_dict_type.dict_type = %s AND sys_dict_type.status = %s ORDER BY sys_dict_data.dict_sort
2026-09-21 10:13:53.094 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [cached since 0.03604s ago] ('0', 'sys_common_status', '0')
2026-09-21 10:13:53.096 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - ROLLBACK
2026-09-21 10:13:53.101 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - BEGIN (implicit)
2026-09-21 10:13:53.102 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - SELECT DISTINCT sys_config.config_id, sys_config.config_name, sys_config.config_key, sys_config.config_value, sys_config.config_type, sys_config.create_by, sys_config.create_time, sys_config.update_by, sys_config.update_time, sys_config.remark
FROM sys_config
WHERE true = 1 ORDER BY sys_config.config_id
2026-09-21 10:13:53.102 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - [generated in 0.00022s] ()
2026-09-21 10:13:53.111 | | | | 61855-bf03aa | INFO | sqlalchemy.log:log:210 - ROLLBACK
2026-09-21 10:13:53.112 | | | | 61855-bf03aa | INFO | config.get_scheduler:init_system_scheduler:210 - 🔎 Worker 61855-bf03aa 尝试获取 Application 锁...
2026-09-21 10:13:53.114 | | | | 61855-bf03aa | INFO | config.get_scheduler:_start_scheduler_as_leader:235 - 🎯 Worker 61855-bf03aa 持有 Application 锁,开始启动定时任务...
2026-09-21 10:13:53.142 | | | | 61855-bf03aa | INFO | apscheduler.schedulers.base:start:214 - Scheduler started
2026-09-21 10:13:53.253 | | | | 61855-bf03aa | INFO | config.get_scheduler:_start_scheduler_as_leader:261 - ✅️ 系统初始定时任务加载成功
2026-09-21 10:13:53.755 | | | | 61855-bf03aa | INFO | server:lifespan:103 - 🚀 ShiErFeng-FastAPI启动成功
2026-09-21 10:13:53.759 | | | | 61855-bf03aa | INFO | server:lifespan:115 - 💻 应用地址:
🏠 Local: http://127.0.0.1:9099
📡 Network: http://172.16.146.99:9099
📡 Network: http://172.16.142.109:9099
📡 Network: http://172.16.224.1:9099
📡 Network: http://192.168.216.1:9099
2026-09-21 10:13:53.759 | | | | 61855-bf03aa | INFO | server:lifespan:122 - 📄 Swagger文档:
🏠 Local: http://127.0.0.1:9099/docs
📡 Network: http://172.16.146.99:9099/docs
📡 Network: http://172.16.142.109:9099/docs
📡 Network: http://172.16.224.1:9099/docs
📡 Network: http://192.168.216.1:9099/docs
2026-09-21 10:13:53.759 | | | | 61855-bf03aa | INFO | server:lifespan:129 - 📚 ReDoc文档:
🏠 Local: http://127.0.0.1:9099/redoc
📡 Network: http://172.16.146.99:9099/redoc
📡 Network: http://172.16.142.109:9099/redoc
📡 Network: http://172.16.224.1:9099/redoc
📡 Network: http://192.168.216.1:9099/redoc
2026-09-21 18:40:56.795 | | | | 61855-bf03aa | INFO | config.get_redis:close_redis_pool:85 - ✅️ 关闭redis连接成功
2026-09-21 18:40:57.041 | | | | 61855-bf03aa | INFO | config.get_scheduler:close_system_scheduler:768 - ✅️ 关闭定时任务成功
2026-09-21 18:40:57.051 | | | | 61855-bf03aa | INFO | apscheduler.schedulers.base:shutdown:245 - Scheduler has been shut down
2026-09-21 18:40:57.077 | | | | 61855-bf03aa | INFO | config.get_scheduler:close_system_scheduler:774 - 🔓 Worker 61855-bf03aa 释放 Application 锁
@@ -0,0 +1,865 @@
2026-09-22 10:18:42.014 | c67f56d9e06b4ff9b0df0307b310acf1 | e7bf03f3985b4cd1a17c53316ccc1c57 | 16a71940dde04f61b06084ef747adb35 | 76540-54b2cc | WARNING | common.annotation.log_annotation:wrapper:194 - 存在下级部门,不允许删除
2026-09-22 10:19:35.435 | ebc19a67e42a40ec9174d89fe47588f9 | 3d7efb2b710d4595b0de10b34865f905 | 4250cfd7ec8e42a2ad031f9b8a643a79 | 76540-54b2cc | WARNING | common.annotation.log_annotation:wrapper:194 - 部门存在用户,不允许删除
2026-09-22 10:19:41.831 | f8c6319564384ee9a8959686a5b1bc19 | 6a2dc693410d4cb788b16f9d4f95056c | 984b4a1ddd574fdbaf75b54ea37fb207 | 76540-54b2cc | WARNING | common.annotation.log_annotation:wrapper:194 - 部门存在用户,不允许删除
2026-09-22 11:08:34.493 | 75f92b597fe6486d9f9c68073eedff31 | 1984201c0f604cf38bc4167d3d8de2bf | c14edb9c8ce84ad4a4bb9000b0ff96e3 | 76540-54b2cc | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-22 13:09:15.676 | 90cdba067fdc471393e87d456603cf92 | 1cf6c85fa12f4f52af203f8e4eff32bf | 566753bee664495580fa822c1f551794 | 76540-54b2cc | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-22 13:42:34.457 | | | | 86619-9b6b60 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-964' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.110 seconds
2026-09-22 18:11:19.770 | | | | 12973-c0e2e4 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.143 seconds
2026-09-22 18:32:32.062 | | | | 35168-f5f084 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.105 seconds
2026-09-22 19:27:26.746 | | | | 57152-6a64c1 | WARNING | config.get_scheduler:on_lock_lost:273 - ⚠️ Worker 57152-6a64c1 失去 Application 锁
2026-09-22 22:24:38.614 | | | | 24817-caa44a | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.118 seconds
2026-09-22 22:24:38.636 | | | | 24819-8b91d3 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.109 seconds
2026-09-22 22:24:38.728 | | | | 24821-323481 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.177 seconds
2026-09-22 22:24:38.827 | | | | 24820-cd85d4 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-19' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.172 seconds
2026-09-22 22:24:38.888 | | | | 24818-25445c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-19' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.250 seconds
2026-09-22 22:52:36.300 | | | | 61048-169acd | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.102 seconds
2026-09-22 23:10:59.657 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 2.626 seconds
2026-09-22 23:11:09.832 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 9.292 seconds
2026-09-22 23:11:10.264 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-7' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.235 seconds
2026-09-22 23:11:10.486 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.129 seconds
2026-09-22 23:11:11.481 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-16' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.580 seconds
2026-09-22 23:11:12.091 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-19' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.259 seconds
2026-09-22 23:11:13.035 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-22' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.856 seconds
2026-09-22 23:11:13.520 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-28' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.141 seconds
2026-09-22 23:11:14.010 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-31' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.185 seconds
2026-09-22 23:11:16.736 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-43' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.183 seconds
2026-09-22 23:11:17.795 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-61' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.250 seconds
2026-09-22 23:11:18.541 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-64' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.124 seconds
2026-09-22 23:11:19.391 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-67' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.514 seconds
2026-09-22 23:11:19.736 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-70' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.231 seconds
2026-09-22 23:11:20.331 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-73' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.501 seconds
2026-09-22 23:11:20.756 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-76' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.374 seconds
2026-09-22 23:11:21.218 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task finished name='Task-83' coro=<Queue.join() done, defined at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/queues.py:207> result=None created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/tasks.py:636> took 0.124 seconds
2026-09-22 23:11:21.631 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-88' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.214 seconds
2026-09-22 23:11:21.804 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task finished name='Task-90' coro=<BaseEventLoop.shutdown_default_executor() done, defined at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:560> result=None created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/tasks.py:636> took 0.136 seconds
2026-09-22 23:11:22.566 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-97' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.228 seconds
2026-09-22 23:11:23.001 | | | | 78383-c16ef2 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-100' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.185 seconds
2026-09-22 23:16:20.261 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.530 seconds
2026-09-22 23:16:23.668 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 3.320 seconds
2026-09-22 23:16:23.843 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-7' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.133 seconds
2026-09-22 23:16:24.175 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.143 seconds
2026-09-22 23:16:24.731 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-16' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.293 seconds
2026-09-22 23:16:25.522 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-22' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.408 seconds
2026-09-22 23:16:26.308 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-31' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.385 seconds
2026-09-22 23:16:26.748 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-34' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.308 seconds
2026-09-22 23:16:26.940 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-37' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.121 seconds
2026-09-22 23:16:29.047 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-46' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.126 seconds
2026-09-22 23:16:29.532 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-49' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.331 seconds
2026-09-22 23:16:29.798 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-52' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.227 seconds
2026-09-22 23:16:30.739 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-67' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.550 seconds
2026-09-22 23:16:31.033 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-70' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.274 seconds
2026-09-22 23:16:31.477 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-73' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.384 seconds
2026-09-22 23:16:32.285 | | | | 82428-c58b46 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-76' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.432 seconds
2026-09-22 23:25:04.359 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.418 seconds
2026-09-22 23:25:06.115 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 1.584 seconds
2026-09-22 23:25:06.804 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-7' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.361 seconds
2026-09-22 23:25:08.052 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.753 seconds
2026-09-22 23:25:08.726 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-13' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.494 seconds
2026-09-22 23:25:09.823 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-16' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.894 seconds
2026-09-22 23:25:10.286 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-28' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.128 seconds
2026-09-22 23:25:11.132 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-34' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.243 seconds
2026-09-22 23:25:11.455 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-37' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.173 seconds
2026-09-22 23:25:11.868 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-40' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.294 seconds
2026-09-22 23:25:12.118 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-40' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.132 seconds
2026-09-22 23:25:14.498 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-43' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.285 seconds
2026-09-22 23:25:14.974 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-52' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.149 seconds
2026-09-22 23:25:15.334 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-55' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.110 seconds
2026-09-22 23:25:16.807 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-67' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.847 seconds
2026-09-22 23:25:17.285 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-70' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.196 seconds
2026-09-22 23:25:18.869 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-73' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 1.346 seconds
2026-09-22 23:25:19.708 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-76' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.444 seconds
2026-09-22 23:25:19.920 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-79' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.110 seconds
2026-09-22 23:25:20.493 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-82' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.347 seconds
2026-09-22 23:25:21.245 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-94' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.195 seconds
2026-09-22 23:25:21.859 | | | | 89690-6ac0a0 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-100' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.277 seconds
2026-09-22 23:29:25.904 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.632 seconds
2026-09-22 23:29:27.988 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 1.939 seconds
2026-09-22 23:29:28.432 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.114 seconds
2026-09-22 23:29:28.753 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-13' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.238 seconds
2026-09-22 23:29:29.126 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-16' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.270 seconds
2026-09-22 23:29:29.634 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-22' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.332 seconds
2026-09-22 23:29:30.338 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-25' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.607 seconds
2026-09-22 23:29:30.898 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-28' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.103 seconds
2026-09-22 23:29:31.035 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task finished name='Task-29' coro=<Queue.join() done, defined at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/queues.py:207> result=None created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/tasks.py:636> took 0.109 seconds
2026-09-22 23:29:31.424 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-31' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.206 seconds
2026-09-22 23:29:31.628 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-34' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.176 seconds
2026-09-22 23:29:32.035 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-34' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.108 seconds
2026-09-22 23:29:32.521 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-34' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.359 seconds
2026-09-22 23:29:32.865 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-37' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.137 seconds
2026-09-22 23:29:33.269 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-37' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.172 seconds
2026-09-22 23:29:33.756 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-40' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.319 seconds
2026-09-22 23:29:36.375 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-43' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.355 seconds
2026-09-22 23:29:36.876 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task finished name='Task-45' coro=<BaseEventLoop.shutdown_default_executor() done, defined at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:560> result=None created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/tasks.py:636> took 0.119 seconds
2026-09-22 23:29:37.417 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-49' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.197 seconds
2026-09-22 23:29:37.693 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-52' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.243 seconds
2026-09-22 23:29:38.113 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-55' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.146 seconds
2026-09-22 23:29:38.457 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-58' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.111 seconds
2026-09-22 23:29:38.835 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-64' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.180 seconds
2026-09-22 23:29:39.085 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-67' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.190 seconds
2026-09-22 23:29:39.817 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-70' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.421 seconds
2026-09-22 23:29:40.668 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-73' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.836 seconds
2026-09-22 23:29:40.874 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Handle _run_until_complete_cb(<Future finis...events.py:429>) at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:184 created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:103> took 0.105 seconds
2026-09-22 23:29:41.871 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-76' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.329 seconds
2026-09-22 23:29:42.082 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Handle _run_until_complete_cb(<Task finishe.../tasks.py:636>) at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:184 created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/events.py:80> took 0.172 seconds
2026-09-22 23:29:42.258 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-79' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.152 seconds
2026-09-22 23:29:43.444 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-85' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.621 seconds
2026-09-22 23:29:44.050 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-91' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.344 seconds
2026-09-22 23:29:44.843 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-97' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.610 seconds
2026-09-22 23:29:45.132 | | | | 92873-630804 | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-100' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.175 seconds
2026-09-22 23:33:02.354 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.154 seconds
2026-09-22 23:33:02.683 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-4' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.167 seconds
2026-09-22 23:33:03.250 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-7' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.350 seconds
2026-09-22 23:33:06.726 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 3.057 seconds
2026-09-22 23:33:06.969 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-13' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.198 seconds
2026-09-22 23:33:07.345 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-16' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.319 seconds
2026-09-22 23:33:08.435 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-19' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 1.044 seconds
2026-09-22 23:33:09.165 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-22' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.627 seconds
2026-09-22 23:33:09.402 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-25' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.193 seconds
2026-09-22 23:33:09.847 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-28' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.392 seconds
2026-09-22 23:33:10.270 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-31' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.277 seconds
2026-09-22 23:33:14.225 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-40' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.313 seconds
2026-09-22 23:33:14.518 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-43' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.231 seconds
2026-09-22 23:33:14.899 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-46' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.145 seconds
2026-09-22 23:33:15.434 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-49' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.337 seconds
2026-09-22 23:33:15.651 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-52' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.135 seconds
2026-09-22 23:33:16.085 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-52' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.347 seconds
2026-09-22 23:33:16.906 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-55' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.604 seconds
2026-09-22 23:33:17.133 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-55' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.116 seconds
2026-09-22 23:33:17.304 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-58' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.108 seconds
2026-09-22 23:33:17.742 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-58' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.407 seconds
2026-09-22 23:33:18.396 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-61' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.501 seconds
2026-09-22 23:33:18.668 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-64' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.175 seconds
2026-09-22 23:33:21.458 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-67' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 2.651 seconds
2026-09-22 23:33:21.857 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-70' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.249 seconds
2026-09-22 23:33:22.116 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-76' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.123 seconds
2026-09-22 23:33:23.120 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-97' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.134 seconds
2026-09-22 23:33:23.589 | | | | 95504-09fcce | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-109' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.124 seconds
2026-09-22 23:36:23.014 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.116 seconds
2026-09-22 23:36:24.009 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-10' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.716 seconds
2026-09-22 23:36:24.730 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-13' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.417 seconds
2026-09-22 23:36:25.937 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-16' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.938 seconds
2026-09-22 23:36:28.981 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-19' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 2.588 seconds
2026-09-22 23:36:29.927 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-22' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.554 seconds
2026-09-22 23:36:30.572 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-25' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.514 seconds
2026-09-22 23:36:31.068 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-28' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.207 seconds
2026-09-22 23:36:31.776 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-31' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.128 seconds
2026-09-22 23:36:35.399 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-37' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.587 seconds
2026-09-22 23:36:36.087 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-40' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.317 seconds
2026-09-22 23:36:37.078 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-43' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.785 seconds
2026-09-22 23:36:37.558 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-46' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.296 seconds
2026-09-22 23:36:38.141 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-52' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.220 seconds
2026-09-22 23:36:38.527 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-55' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.271 seconds
2026-09-22 23:36:39.076 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-58' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.468 seconds
2026-09-22 23:36:40.540 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-61' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.841 seconds
2026-09-22 23:36:40.842 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-64' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.249 seconds
2026-09-22 23:36:46.647 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-67' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 4.703 seconds
2026-09-22 23:36:47.157 | | | | 98313-a0269c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-79' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.108 seconds
2026-09-22 23:46:00.259 | | | | 12467-333dad | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-46' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.100 seconds
2026-09-22 23:47:35.249 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Connection closed by server.
2026-09-22 23:47:36.377 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:37.380 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:38.384 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:39.386 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:40.391 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:41.395 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:42.401 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:43.405 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:44.409 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:45.410 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:46.412 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:47.413 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:48.416 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:49.418 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:50.421 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:51.425 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:52.430 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:53.433 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:54.435 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:55.438 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:56.440 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:57.451 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:58.456 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:47:59.458 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:00.461 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:01.464 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:02.467 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:03.470 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:04.474 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:05.481 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:06.489 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:07.493 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:08.500 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:09.504 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:10.506 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:11.512 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:12.518 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:13.521 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:14.526 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:15.531 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:16.534 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:17.539 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:18.545 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:19.566 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:20.573 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:21.593 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:22.599 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:23.603 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:24.606 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:25.610 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:26.613 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:27.620 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:28.625 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:29.628 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:30.632 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:31.636 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:32.640 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:33.645 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:34.648 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:35.651 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:36.655 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:37.658 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:38.663 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:39.666 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:40.686 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:41.697 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:42.699 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:43.702 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:44.705 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:45.707 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:46.710 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:47.713 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:48.718 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:49.723 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:50.728 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:51.737 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:52.750 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:53.757 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:54.763 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:55.766 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:56.770 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:57.774 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:58.778 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:48:59.780 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:00.785 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:01.788 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:02.790 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:03.794 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:04.797 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:05.800 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:06.804 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:07.809 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:08.811 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:09.815 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:10.818 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:11.822 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:12.824 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:13.827 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:14.829 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:15.831 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:16.834 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:17.838 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:18.841 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:19.845 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:20.848 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:21.851 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:22.855 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:23.859 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:24.863 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:25.867 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:26.871 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:27.875 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:28.879 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:29.882 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:30.887 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:31.889 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:32.892 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:33.896 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:34.901 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:35.907 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:36.912 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:37.915 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:38.922 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:40.026 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:41.030 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:42.064 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:43.094 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:44.123 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:45.201 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:46.251 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:47.265 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:48.411 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:49.416 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:50.421 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:51.441 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:52.485 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:53.488 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:54.491 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:55.536 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:56.543 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:57.548 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:58.552 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:49:59.556 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:00.563 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:01.569 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:02.576 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:03.757 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:04.780 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:05.786 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:06.792 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:07.798 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:08.805 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:09.811 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:10.816 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:11.823 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:12.832 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:13.835 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:14.841 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:15.847 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:16.851 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:17.856 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:18.861 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:19.866 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:20.873 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:21.880 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:22.889 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:23.897 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:24.904 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:25.911 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:26.916 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:27.920 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:28.925 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:29.929 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:30.934 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:31.937 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:32.941 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:33.945 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:34.953 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:35.959 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:36.965 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:37.972 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:38.978 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:39.981 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:40.986 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:41.989 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:42.992 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:43.995 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:44.999 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:46.002 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:47.005 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:48.008 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:49.012 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:50.015 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:51.019 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:52.021 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:53.024 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:54.028 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:55.029 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:56.032 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:57.036 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:58.038 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:50:59.041 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:51:00.045 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:51:01.047 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:51:02.049 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-22 23:51:03.051 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:03.571 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:04.574 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:05.579 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:06.583 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:07.587 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:08.591 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:09.595 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:10.602 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:11.608 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:12.613 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:13.614 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:14.617 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:15.621 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:16.623 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:00:17.625 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:11.971 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:13.078 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:14.081 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:15.085 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:16.088 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:17.092 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:18.092 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:19.095 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:20.098 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:21.100 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:22.113 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:23.116 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:11:24.117 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:27:40.574 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:27:41.686 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:27:42.690 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:27:43.694 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:27:44.698 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:44:00.591 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:44:01.596 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:44:02.600 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:44:03.604 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:44:04.607 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:44:05.609 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:03.587 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:04.590 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:05.594 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:06.597 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:07.598 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:08.600 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:09.603 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:10.606 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:11.609 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:12.611 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:13.615 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:14.635 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:15.647 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:16.650 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:17.651 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:18.654 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:19.657 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:20.658 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:21.661 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:22.662 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:23.665 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:24.668 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:25.670 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:26.672 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:27.674 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:28.677 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:29.681 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 00:50:30.684 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:05:50.591 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:05:51.593 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:05:52.595 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:05:53.599 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:05:54.601 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:05:55.603 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:23:03.608 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:23:04.611 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:23:05.614 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:23:06.618 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:23:07.620 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:23:08.623 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:40:49.623 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:40:50.710 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:40:51.712 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:40:52.716 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:40:53.718 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:40:54.721 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:03.636 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:04.641 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:05.645 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:06.649 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:07.653 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:08.658 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 01:51:09.661 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:06:48.621 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:06:49.722 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:06:50.726 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:06:51.730 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:06:52.736 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:23:48.707 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:23:49.725 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:23:50.730 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:23:51.734 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:23:52.739 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:23:53.743 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:39:38.635 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:39:39.642 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:39:40.647 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:39:41.652 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:39:42.655 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:39:43.658 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:56:25.666 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:56:26.755 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:56:27.759 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:56:28.763 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:56:29.767 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 02:56:30.770 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:12:53.660 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:12:54.759 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:12:55.762 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:12:56.766 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:12:57.769 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:12:58.777 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:20.670 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:21.673 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:22.677 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:23.681 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:24.685 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:25.688 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:26.691 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:14:27.692 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:31:33.664 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:31:34.670 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:31:35.675 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:31:36.679 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:31:37.682 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:31:38.687 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:48:22.670 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:48:23.764 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:48:24.767 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:48:25.771 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:48:26.773 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 03:48:27.777 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:05:24.673 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:05:25.677 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:05:26.680 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:05:27.683 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:05:28.685 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:05:29.689 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:23:12.688 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:23:13.693 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:23:14.696 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:23:15.698 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:23:16.700 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:23:17.702 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:40:37.692 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:40:38.697 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:40:39.703 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:40:40.707 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:40:41.710 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:40:42.715 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:55:41.727 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:55:42.800 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:55:43.806 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:55:44.812 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:55:45.816 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 04:55:46.821 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:13:12.718 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:13:13.807 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:13:14.811 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:13:15.817 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:13:16.823 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:13:17.826 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:29:29.715 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:29:30.719 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:29:31.723 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:29:32.726 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:29:33.730 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:29:34.732 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:05.738 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:06.819 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:07.822 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:08.826 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:09.829 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:10.833 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:11.835 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 05:45:12.839 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:01:29.723 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:01:30.824 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:01:31.826 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:01:32.829 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:01:33.832 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:18:33.830 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:18:34.835 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:18:35.837 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:18:36.839 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:18:37.843 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:18:38.846 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:36:06.836 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:36:07.839 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:36:08.842 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:36:09.845 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:36:10.848 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:51:09.750 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:51:10.754 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:51:11.758 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:51:12.761 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:51:13.764 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 06:51:14.768 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:07:09.760 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:07:10.764 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:07:11.765 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:07:12.769 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:07:13.771 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:07:14.774 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:24:44.764 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:24:45.767 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:24:46.769 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:24:47.771 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:24:48.776 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:24:49.781 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:39:47.786 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:39:48.807 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:39:49.809 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:39:50.812 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:39:51.815 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:39:52.819 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:05.774 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:06.780 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:07.785 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:08.790 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:09.793 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:10.796 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:11.799 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:12.802 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:46:13.805 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:00.778 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:01.872 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:02.875 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:03.877 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:04.880 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:05.882 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:06.884 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:07.886 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:08.887 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:09.889 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:10.895 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:11.900 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:12.910 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:55:13.921 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:10.286 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:11.430 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:12.438 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:13.450 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:14.457 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:15.603 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:16.659 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:17.666 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:18.673 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:19.681 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:20.683 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:21.689 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:22.696 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:23.698 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:24.700 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:25.702 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:26.704 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:27.708 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:28.711 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:29.713 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:30.716 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:31.718 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:32.720 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:33.722 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:34.726 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:35.758 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:36.794 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:37.811 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:38.818 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:39.823 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:40.829 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:41.836 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:42.883 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:43.890 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:44.909 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:45.918 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:46.924 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:47.936 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:48.941 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:49.949 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:50.955 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:51.977 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:52.991 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:53.998 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:55.014 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:56.022 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:57.029 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:58.037 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:58:59.053 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:00.058 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:01.071 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:02.082 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:03.085 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:04.091 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:05.109 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:06.112 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:07.120 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:08.123 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:09.129 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:10.135 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:11.139 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:12.143 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:13.150 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:14.157 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:15.168 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:16.176 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:17.202 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:18.232 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:19.245 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:20.254 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:21.262 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:22.269 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:23.274 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:24.280 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:25.285 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:26.293 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:27.298 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:28.303 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:29.310 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:30.317 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:31.324 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:32.332 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:33.337 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:34.342 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:35.349 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:36.353 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:37.359 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:38.364 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:39.373 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:40.377 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:41.382 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:42.389 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:43.394 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:44.402 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:45.410 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:46.419 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:47.425 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:48.431 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:49.435 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:50.454 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:51.459 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:52.463 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:53.472 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:54.480 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:55.486 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:56.491 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:57.497 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:58.509 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 07:59:59.520 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:00.526 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:01.531 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:02.537 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:03.548 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:04.555 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:05.563 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:06.578 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:07.584 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:08.591 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:09.597 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:10.601 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:11.606 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:12.609 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:13.613 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:14.618 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:15.622 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:16.628 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:17.632 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:18.640 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:19.645 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:20.648 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:21.651 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:22.654 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:23.655 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:24.660 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:25.667 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:26.672 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:27.676 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:28.679 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:29.681 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:30.683 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:31.687 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:32.690 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:33.693 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:34.697 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:35.699 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:36.701 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:37.704 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:38.708 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:39.710 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:40.713 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:41.722 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:42.729 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:43.732 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:44.737 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:45.740 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:46.744 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:47.747 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:48.751 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:49.754 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:50.757 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:51.761 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:52.764 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:53.768 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:54.772 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:55.776 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:56.785 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:57.791 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:58.797 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:00:59.805 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:00.813 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:01.839 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:02.853 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:03.861 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:04.865 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:05.868 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:06.870 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:07.871 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:08.874 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:09.880 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:10.882 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:11.883 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:12.885 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:13.888 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:14.890 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:15.893 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:16.896 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:17.898 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:18.900 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:19.905 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:20.911 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:21.919 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:22.928 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:23.931 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:24.935 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:25.940 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:26.949 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:27.955 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:28.963 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:29.969 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:30.975 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:31.980 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:32.987 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:34.000 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:35.010 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:36.013 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:37.017 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:38.019 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:39.022 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:40.027 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:41.031 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:42.036 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:43.038 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:44.040 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:45.044 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:46.046 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:47.048 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:48.052 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:49.055 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:50.057 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:51.059 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:52.061 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:53.064 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:54.068 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:55.071 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:56.074 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:57.077 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:58.081 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:01:59.083 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:00.087 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:01.090 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:02.093 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:03.095 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:04.098 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:05.101 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:06.106 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:07.108 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:08.110 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:09.113 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:10.119 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:11.122 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:12.127 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:13.133 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:14.140 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:15.147 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:16.151 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:17.157 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:18.171 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:19.176 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:20.181 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:21.189 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:22.198 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:23.202 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
2026-09-23 08:02:24.205 | | | | 12367-8e907e | ERROR | module_admin.service.log_service:consume_stream:464 - 日志聚合消费异常: Error 61 connecting to 127.0.0.1:6379. Connection refused.
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,15 @@
2026-09-26 12:55:38.977 | | | | 43890-69016c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-631' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.114 seconds
2026-09-26 12:55:41.558 | | | | 43890-69016c | WARNING | asyncio.base_events:_run_once:1904 - Executing <Task pending name='Task-1137' coro=<IsolatedAsyncioTestCase._asyncioLoopRunner() running at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:95> wait_for=<Future pending cb=[Task.task_wakeup()] created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/asyncio/base_events.py:429> created at /Users/jiaolongyan/miniconda3/envs/ShiErFeng/lib/python3.10/unittest/async_case.py:117> took 0.131 seconds
2026-09-26 13:40:25.189 | 4adcaf0fe9734e06a3e3540456d2dcda | bfc317a4ef2d47f9b1ff9b0dacbb4caf | f325961f7b574bb0946772b05e178ded | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:219 - 用户token已失效,请重新登录
2026-09-26 16:46:13.947 | 31755c4a7f4747f3963c5b94c040836f | 054f0424f5df44c196e82d4403fe8b1e | 6a70d146cceb42a08e58f1df9d00e30a | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.354 | b5e7bd983c794a9f8bdccfee51db8d73 | 005c76cace20459a8111156d5dfb9a69 | fdf16bf6fb774975978a7ee55994ccef | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.355 | cbf427c3908042d29c47fe1fdf002787 | 76eea226e3914e978fc1945589863eb0 | a036db90caa74c59ad836fcb6dfb4698 | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.358 | badf85531e264537881425cefd532a4e | 9777e8101ca64266a7fc028277cba6b6 | 7ac0e140695745698e8f6182e49f44a0 | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.360 | 0a5c054a6aeb4d5da44cf7edeba90bda | 546e0c5fca214ac59e6b1ca60bb51a5d | b6d578ac982343e780115f406dbd2f80 | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.360 | f9d8cb8d6f13403693533d4831d34fe2 | 85788d53e2c544128a120b7468ce841f | 92f14081de0344f18ba48a801b6a3277 | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.360 | 03ab2322a8a942c0890e0746010f06c6 | a118b2fa8b324ab6ad8ad7b7b8e27279 | b295f1db72c24d8d815aba6908e3239e | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.404 | d541c8c66d304766be61766e9cce2648 | f7a2b5ba8d04420d9fc819298ece8a82 | 7067c57860c24bc6af0047f6f0523112 | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.408 | 0b279fc9e3f245c2a269f42cd15790df | d00aa8f0f30a4eb38350d2d559f2b783 | fbfb19dcf5ab4ab18f9179912242ebba | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.409 | 8f088061d64445eb83100393320bba81 | de6a6a19267e474195c7b3d33334dcc5 | 58249b4d816b4a3b8833981f5aadebca | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 19:22:28.411 | 20c430d179d44806a414717830bf1c44 | 07c1721f324e447a9d121d6e78518182 | 286523eb9ad7456697859a49d3c85381 | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
2026-09-26 21:43:11.533 | f639f0f70cf841baa341fff7fda02dbf | c08cd9bcfe1447f9809115a22a51c909 | 4b0d65ad896c4f79b36636218ef526de | 35286-85260c | WARNING | module_admin.service.login_service:get_current_user:277 - 用户token已失效,请重新登录
File diff suppressed because it is too large Load Diff
@@ -1,6 +1,6 @@
from datetime import datetime
from sqlalchemy import CHAR, Column, DateTime, Integer, LargeBinary, String
from sqlalchemy import CHAR, Column, DateTime, Integer, String
from sqlalchemy.dialects import mysql
from config.database import Base
@@ -20,7 +20,7 @@ class SysNotice(Base):
notice_title = Column(String(50), nullable=False, comment='公告标题')
notice_type = Column(CHAR(1), nullable=False, comment='公告类型(1通知 2公告)')
notice_content = Column(
mysql.LONGBLOB if DataBaseConfig.db_type == 'mysql' else LargeBinary,
mysql.LONGBLOB,
nullable=True,
server_default=SqlalchemyUtil.get_server_default_null(DataBaseConfig.db_type, False),
comment='公告内容',
@@ -1,6 +1,6 @@
from datetime import datetime
from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, SmallInteger, String
from sqlalchemy import CHAR, BigInteger, Column, DateTime, Integer, String
from sqlalchemy.dialects import mysql
from config.database import Base
@@ -27,13 +27,13 @@ class SysRole(Base):
comment='数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
)
menu_check_strictly = Column(
mysql.TINYINT(display_width=1) if DataBaseConfig.db_type == 'mysql' else SmallInteger,
mysql.TINYINT(display_width=1),
nullable=True,
server_default='1',
comment='菜单树选择项是否关联显示',
)
dept_check_strictly = Column(
mysql.TINYINT(display_width=1) if DataBaseConfig.db_type == 'mysql' else SmallInteger,
mysql.TINYINT(display_width=1),
nullable=True,
server_default='1',
comment='部门树选择项是否关联显示',
@@ -107,8 +107,6 @@ class LoginService:
logger.warning('用户不存在')
raise LoginException(data='', message='用户不存在')
if not PwdUtil.verify_password(login_user.password, user[0].password):
logger.warning(f"打印User:{user[0].password}")
logger.warning(f"打印User:{PwdUtil.verify_password(login_user.password, user[0].password)}")
cache_password_error_count = await request.app.state.redis.get(
f'{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.key}:{login_user.user_name}'
)
@@ -111,7 +111,7 @@ async def edit_master_customer(
summary='兼容旧接口,固定拒绝,请使用测试数据批次清理',
description='兼容旧接口,固定拒绝单条物理删除,请使用测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('master:customer:remove')],
dependencies=[UserInterfaceAuthDependency('master:customer:list')],
)
@Log(title='客户管理', business_type=BusinessType.DELETE)
async def delete_master_customer(
@@ -163,7 +163,7 @@ async def edit_business_inbound(
summary='不支持单条物理删除,请通过测试数据批次清理',
description='不支持单条物理删除,请通过测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('business:inbound:remove')],
dependencies=[UserInterfaceAuthDependency('business:inbound:list')],
)
@Log(title='仓库入库', business_type=BusinessType.DELETE)
async def delete_business_inbound(
@@ -109,7 +109,7 @@ async def edit_master_line(
summary='兼容旧接口,固定拒绝,请使用测试数据批次清理',
description='兼容旧接口,固定拒绝单条物理删除,请使用测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('master:line:remove')],
dependencies=[UserInterfaceAuthDependency('master:line:list')],
)
@Log(title='生产线管理', business_type=BusinessType.DELETE)
async def delete_master_line(
@@ -123,7 +123,7 @@ async def edit_master_pallet(
summary='兼容旧接口,固定拒绝,请使用测试数据批次清理',
description='兼容旧接口,固定拒绝单条物理删除,请使用测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('master:pallet:remove')],
dependencies=[UserInterfaceAuthDependency('master:pallet:list')],
)
@Log(title='托盘管理', business_type=BusinessType.DELETE)
async def delete_master_pallet(
@@ -180,7 +180,7 @@ async def edit_business_shipment(
summary='不支持单条物理删除,请通过测试数据批次清理',
description='不支持单条物理删除,请通过测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('business:shipment:remove')],
dependencies=[UserInterfaceAuthDependency('business:shipment:list')],
)
@Log(title='整托发货', business_type=BusinessType.DELETE)
async def delete_business_shipment(
@@ -161,7 +161,7 @@ async def edit_master_site(
summary='兼容旧接口,固定拒绝,请使用测试数据批次清理',
description='兼容旧接口,固定拒绝单条物理删除,请使用测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('master:site:remove')],
dependencies=[UserInterfaceAuthDependency('master:site:list')],
)
@Log(title='客户现场管理', business_type=BusinessType.DELETE)
async def delete_master_site(
@@ -111,7 +111,7 @@ async def edit_master_strain(
summary='兼容旧接口,固定拒绝,请使用测试数据批次清理',
description='兼容旧接口,固定拒绝单条物理删除,请使用测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('master:strain:remove')],
dependencies=[UserInterfaceAuthDependency('master:strain:list')],
)
@Log(title='菌种管理', business_type=BusinessType.DELETE)
async def delete_master_strain(
@@ -0,0 +1,262 @@
from typing import Annotated
from fastapi import Path, Request, Response
from sqlalchemy.ext.asyncio import AsyncSession
from common.annotation.log_annotation import Log, RequestLogFieldRoot
from common.aspect.db_seesion import DBSessionDependency
from common.aspect.interface_auth import UserInterfaceAuthDependency
from common.aspect.pre_auth import CurrentUserDependency, PreAuthDependency
from common.enums import BusinessType
from common.router import APIRouterPro
from module_admin.entity.vo.user_vo import CurrentUserModel
from module_business.entity.vo.test_batch_vo import (
AdoptionExecuteRequestModel,
AdoptionPreviewRequestModel,
PurgeExecuteRequestModel,
TestBatchCreateModel,
TestBatchEditModel,
TestBatchUserAssignModel,
)
from module_business.service.test_batch_adoption_service import TestBatchAdoptionService
from module_business.service.test_batch_purge_service import TestBatchPurgeService
from module_business.service.test_batch_service import TestBatchService
from utils.response_util import ResponseUtil
test_batch_controller = APIRouterPro(
prefix='/system/test-batch',
tags=['系统管理-测试数据批次'],
dependencies=[PreAuthDependency()],
)
@test_batch_controller.get('/options')
async def list_test_batch_options(
request: Request,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.list_available_batches(query_db, current_user)
return ResponseUtil.success(data=result)
@test_batch_controller.get(
'/list',
dependencies=[UserInterfaceAuthDependency('system:testbatch:list')],
)
@Log(
title='测试数据批次',
business_type=BusinessType.OTHER,
request_log_mode='summary',
response_log_mode='summary',
)
async def list_test_batches(
request: Request,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.list_batches(query_db, current_user)
return ResponseUtil.success(rows=result, dict_content={'total': len(result)})
@test_batch_controller.post(
'',
dependencies=[UserInterfaceAuthDependency('system:testbatch:add')],
)
@Log(
title='测试数据批次',
business_type=BusinessType.INSERT,
request_log_mode='summary',
response_log_mode='summary',
)
async def create_test_batch(
request: Request,
command: TestBatchCreateModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.create_batch(query_db, command, current_user)
return ResponseUtil.success(msg=result.message)
@test_batch_controller.put(
'/{batch_id}',
dependencies=[UserInterfaceAuthDependency('system:testbatch:edit')],
)
@Log(
title='测试数据批次',
business_type=BusinessType.UPDATE,
request_log_mode='summary',
response_log_mode='summary',
)
async def edit_test_batch(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
command: TestBatchEditModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.edit_batch(query_db, batch_id, command, current_user)
return ResponseUtil.success(msg=result.message)
@test_batch_controller.put(
'/{batch_id}/users',
dependencies=[UserInterfaceAuthDependency('system:testbatch:assign')],
)
@Log(
title='测试数据批次',
business_type=BusinessType.GRANT,
request_log_mode='summary',
response_log_mode='summary',
)
async def assign_test_batch_users(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
command: TestBatchUserAssignModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.replace_users(query_db, batch_id, command, current_user)
return ResponseUtil.success(msg=result.message)
@test_batch_controller.put(
'/{batch_id}/close',
dependencies=[UserInterfaceAuthDependency('system:testbatch:close')],
)
@Log(
title='测试数据批次',
business_type=BusinessType.UPDATE,
request_log_mode='summary',
response_log_mode='summary',
)
async def close_test_batch(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.close_batch(query_db, batch_id, current_user)
return ResponseUtil.success(msg=result.message)
@test_batch_controller.put(
'/{batch_id}/reopen',
dependencies=[UserInterfaceAuthDependency('system:testbatch:close')],
)
@Log(
title='测试数据批次',
business_type=BusinessType.UPDATE,
request_log_mode='summary',
response_log_mode='summary',
)
async def reopen_test_batch(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.reopen_batch(query_db, batch_id, current_user)
return ResponseUtil.success(msg=result.message)
@Log(
title='测试数据批次',
business_type=BusinessType.CLEAN,
request_log_mode='include',
request_include_fields=(RequestLogFieldRoot.PATH_PARAMS.field('batch_id'),),
response_log_mode='summary',
)
@test_batch_controller.post(
'/{batch_id}/adoption/preview',
dependencies=[UserInterfaceAuthDependency('system:testbatch:adopt')],
)
async def preview_test_batch_adoption(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
command: AdoptionPreviewRequestModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchAdoptionService.preview(query_db, batch_id, command, current_user)
return ResponseUtil.success(data=result)
@Log(
title='测试数据批次',
business_type=BusinessType.CLEAN,
request_log_mode='include',
request_include_fields=(RequestLogFieldRoot.PATH_PARAMS.field('batch_id'),),
response_log_mode='summary',
)
@test_batch_controller.post(
'/{batch_id}/adoption/execute',
dependencies=[UserInterfaceAuthDependency('system:testbatch:adopt')],
)
async def execute_test_batch_adoption(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
command: AdoptionExecuteRequestModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchAdoptionService.execute(query_db, batch_id, command, current_user)
return ResponseUtil.success(msg=result.message)
@Log(
title='测试数据批次',
business_type=BusinessType.CLEAN,
request_log_mode='include',
request_include_fields=(RequestLogFieldRoot.PATH_PARAMS.field('batch_id'),),
response_log_mode='summary',
)
@test_batch_controller.post(
'/{batch_id}/purge/preview',
dependencies=[UserInterfaceAuthDependency('system:testbatch:purge')],
)
async def preview_test_batch_purge(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchPurgeService.preview(query_db, batch_id, current_user)
return ResponseUtil.success(data=result)
@Log(
title='测试数据批次',
business_type=BusinessType.CLEAN,
request_log_mode='include',
request_include_fields=(RequestLogFieldRoot.PATH_PARAMS.field('batch_id'),),
response_log_mode='summary',
)
@test_batch_controller.post(
'/{batch_id}/purge',
dependencies=[UserInterfaceAuthDependency('system:testbatch:purge')],
)
async def purge_test_batch(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
command: PurgeExecuteRequestModel,
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchPurgeService.purge(query_db, batch_id, command, current_user)
return ResponseUtil.success(msg=result.message)
@test_batch_controller.get(
'/{batch_id}',
dependencies=[UserInterfaceAuthDependency('system:testbatch:query')],
)
async def get_test_batch(
request: Request,
batch_id: Annotated[int, Path(gt=0, description='测试批次ID')],
query_db: Annotated[AsyncSession, DBSessionDependency()],
current_user: Annotated[CurrentUserModel, CurrentUserDependency()],
) -> Response:
result = await TestBatchService.get_batch_detail(query_db, batch_id, current_user)
return ResponseUtil.success(data=result)
@@ -166,7 +166,7 @@ async def edit_master_warehouse(
summary='兼容旧接口,固定拒绝,请使用测试数据批次清理',
description='兼容旧接口,固定拒绝单条物理删除,请使用测试数据批次清理',
response_model=ResponseBaseModel,
dependencies=[UserInterfaceAuthDependency('master:warehouse:remove')],
dependencies=[UserInterfaceAuthDependency('master:warehouse:list')],
)
@Log(title='仓库管理', business_type=BusinessType.DELETE)
async def delete_master_warehouse(
@@ -53,6 +53,7 @@ class MasterDao:
query_object.page_num,
query_object.page_size,
is_page,
exclude_fields={'test_batch_id'},
)
@staticmethod
@@ -145,6 +145,7 @@ class OperationDao:
query_object.page_num,
query_object.page_size,
is_page,
exclude_fields={'test_batch_id'},
)
@staticmethod
@@ -143,6 +143,7 @@ class ReportDao:
query_object.page_num,
query_object.page_size,
True,
exclude_fields={'test_batch_id'},
)
@classmethod
@@ -14,6 +14,8 @@ from module_business.domain.enums import TestBatchStatus
from module_business.domain.test_batch_graph import (
BATCH_LABELS,
BATCH_MODELS,
ROOT_TABLES,
BatchSelection,
TestBatchGraph,
issue_preview_token,
selection_hash,
@@ -21,6 +23,7 @@ from module_business.domain.test_batch_graph import (
from module_business.entity.vo.test_batch_vo import (
AdoptionExecuteRequestModel,
AdoptionPreviewRequestModel,
AdoptionRootModel,
BatchImpactModel,
TestBatchPreviewModel,
)
@@ -53,6 +56,16 @@ class TestBatchAdoptionService:
if status != TestBatchStatus.ACTIVE.value:
raise ServiceWarning('', '测试批次状态异常')
@staticmethod
def _assert_roots_exist(
roots: list[AdoptionRootModel],
selection: BatchSelection,
) -> None:
for root in roots:
table_name = ROOT_TABLES[root.resource_type]
if not set(root.resource_ids).issubset(selection[table_name]):
raise ServiceWarning('', '指定的旧数据不存在')
@staticmethod
def _assert_token(batch: object, raw_token: str, now: datetime) -> None:
supplied_hash = hashlib.sha256(raw_token.encode()).hexdigest()
@@ -80,6 +93,7 @@ class TestBatchAdoptionService:
batch = await TestBatchDao.get_batch_for_update(db, batch_id)
cls._assert_active(batch)
selection = await TestBatchGraph.compute_closure(db, command.roots)
cls._assert_roots_exist(command.roots, selection)
if await TestBatchAdoptionDao.find_tagged_record(db, selection) is not None:
raise ServiceWarning('', '存在记录已属于其他测试批次')
display_keys = await TestBatchAdoptionDao.list_display_keys(db, selection)
@@ -141,20 +141,6 @@ class GenTableDao:
:param is_page: 是否开启分页
:return: 数据库列表信息对象
"""
if DataBaseConfig.db_type == 'postgresql':
query_sql = """
table_name as table_name,
table_comment as table_comment,
create_time as create_time,
update_time as update_time
from
list_table
where
table_name not like 'apscheduler_%'
and table_name not like 'gen_%'
and table_name not in (select table_name from gen_table)
"""
else:
query_sql = r"""
table_name as table_name,
table_comment as table_comment,
@@ -173,14 +159,8 @@ class GenTableDao:
if query_object.table_comment:
query_sql += """and lower(table_comment) like lower(concat('%', :table_comment, '%'))"""
if query_object.begin_time:
if DataBaseConfig.db_type == 'postgresql':
query_sql += """and create_time::date >= to_date(:begin_time, 'yyyy-MM-dd')"""
else:
query_sql += """and date_format(create_time, '%Y%m%d') >= date_format(:begin_time, '%Y%m%d')"""
if query_object.end_time:
if DataBaseConfig.db_type == 'postgresql':
query_sql += """and create_time::date <= to_date(:end_time, 'yyyy-MM-dd')"""
else:
query_sql += """and date_format(create_time, '%Y%m%d') >= date_format(:end_time, '%Y%m%d')"""
query_sql += """order by create_time desc"""
query = select(
@@ -201,21 +181,6 @@ class GenTableDao:
:param table_names: 业务表名称组
:return: 数据库列表信息对象
"""
if DataBaseConfig.db_type == 'postgresql':
query_sql = """
select
table_name as table_name,
table_comment as table_comment,
create_time as create_time,
update_time as update_time
from
list_table
where
table_name not like 'qrtz_%'
and table_name not like 'gen_%'
and table_name = any(:table_names)
"""
else:
query_sql = r"""
select
table_name as table_name,
@@ -308,16 +273,6 @@ class GenTableColumnDao:
:param table_name: 业务表名称
:return: 业务表字段列表信息对象
"""
if DataBaseConfig.db_type == 'postgresql':
query_sql = """
select
column_name, is_required, is_pk, sort, column_comment, is_increment, column_type
from
list_column
where
table_name = :table_name
"""
else:
query_sql = """
select
column_name as column_name,
@@ -1,30 +1,3 @@
{% if dbType == 'postgresql' %}
DO $$
DECLARE
parentId bigint;
BEGIN
-- 菜单 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}', '{{ parentMenuId }}', '1', '{{ businessName }}', '{{ moduleName }}/{{ businessName }}/index', 1, 0, 'C', '0', '0', '{{ permissionPrefix }}:list', '#', 'admin', current_timestamp, '', null, '{{ functionName }}菜单')
returning menu_id into parentId;
-- 按钮 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}查询', parentId, '1', '#', '', 1, 0, 'F', '0', '0', '{{ permissionPrefix }}:query', '#', 'admin', current_timestamp, '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}新增', parentId, '2', '#', '', 1, 0, 'F', '0', '0', '{{ permissionPrefix }}:add', '#', 'admin', current_timestamp, '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}修改', parentId, '3', '#', '', 1, 0, 'F', '0', '0', '{{ permissionPrefix }}:edit', '#', 'admin', current_timestamp, '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}删除', parentId, '4', '#', '', 1, 0, 'F', '0', '0', '{{ permissionPrefix }}:remove', '#', 'admin', current_timestamp, '', null, '');
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}导出', parentId, '5', '#', '', 1, 0, 'F', '0', '0', '{{ permissionPrefix }}:export', '#', 'admin', current_timestamp, '', null, '');
END $$;
{% else %}
-- 菜单 SQL
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}', '{{ parentMenuId }}', '1', '{{ businessName }}', '{{ moduleName }}/{{ businessName }}/index', 1, 0, 'C', '0', '0', '{{ permissionPrefix }}:list', '#', 'admin', sysdate(), '', null, '{{ functionName }}菜单');
@@ -47,4 +20,3 @@ values('{{ functionName }}删除', @parentId, '4', '#', '', 1, 0, 'F', '0', '0'
insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
values('{{ functionName }}导出', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '{{ permissionPrefix }}:export', '#', 'admin', sysdate(), '', null, '');
{% endif %}
@@ -1,24 +0,0 @@
aiofiles==25.1.0
alembic==1.18.3
APScheduler==3.11.2
async-lru==2.1.0
asyncpg==0.31.0
bcrypt==5.0.0
fastapi[all]==0.128.2
loguru==0.7.3
openpyxl==3.1.5
pandas==2.3.3
Pillow==12.1.1
psutil==7.2.2
psycopg2==2.9.11
pydantic>=2.11.4
pydantic-validation-decorator==0.1.5
PyJWT[crypto]==2.11.0
qrcode==8.2
redis==7.1.0
ruff==0.15.0
SQLAlchemy[asyncio]==2.0.46
sqlglot[rs]==28.10.0
textual==8.2.5
user-agents==2.2.0
.
@@ -1,5 +0,0 @@
Metadata-Version: 2.4
Name: shierfeng-fastapi-backend-cli
Version: 1.9.0
Summary: ShiErFeng FastAPI backend internal CLI entrypoint
Requires-Python: >=3.10
@@ -1,170 +0,0 @@
pyproject.toml
cli/__init__.py
cli/bootstrap.py
cli/context.py
cli/exit_codes.py
cli/guards.py
cli/main.py
cli/output.py
cli/utils.py
cli/completion/__init__.py
cli/completion/commands.py
cli/completion/controller.py
cli/completion/doctor.py
cli/completion/installers.py
cli/completion/presenter.py
cli/completion/providers.py
cli/completion/shells.py
cli/core/__init__.py
cli/core/app_builder.py
cli/core/completion_dispatcher.py
cli/core/context_factory.py
cli/core/execution.py
cli/groups/__init__.py
cli/groups/app/__init__.py
cli/groups/app/command.py
cli/groups/app/controller.py
cli/groups/app/presenter.py
cli/groups/cache/__init__.py
cli/groups/cache/command.py
cli/groups/cache/controller.py
cli/groups/cache/presenter.py
cli/groups/config/__init__.py
cli/groups/config/command.py
cli/groups/config/controller.py
cli/groups/config/presenter.py
cli/groups/crypto/__init__.py
cli/groups/crypto/command.py
cli/groups/crypto/controller.py
cli/groups/crypto/presenter.py
cli/groups/db/__init__.py
cli/groups/db/command.py
cli/groups/db/controller.py
cli/groups/db/presenter.py
cli/groups/dev/__init__.py
cli/groups/dev/command.py
cli/groups/dev/controller.py
cli/groups/dev/presenter.py
cli/groups/gen/__init__.py
cli/groups/gen/command.py
cli/groups/gen/controller.py
cli/groups/gen/presenter.py
cli/groups/job/__init__.py
cli/groups/job/command.py
cli/groups/job/controller.py
cli/groups/job/presenter.py
cli/groups/ops/__init__.py
cli/groups/ops/command.py
cli/groups/ops/controller.py
cli/groups/ops/presenter.py
cli/metadata/__init__.py
cli/metadata/command_specs.py
cli/metadata/option_specs.py
cli/metadata/risk_specs.py
cli/runtime/__init__.py
cli/runtime/base.py
cli/runtime/app/__init__.py
cli/runtime/app/gateway.py
cli/runtime/app/service.py
cli/runtime/app/support.py
cli/runtime/cache/__init__.py
cli/runtime/cache/gateway.py
cli/runtime/cache/service.py
cli/runtime/cache/support.py
cli/runtime/config/__init__.py
cli/runtime/config/gateway.py
cli/runtime/config/service.py
cli/runtime/config/support.py
cli/runtime/crypto/__init__.py
cli/runtime/crypto/gateway.py
cli/runtime/crypto/service.py
cli/runtime/crypto/support.py
cli/runtime/db/__init__.py
cli/runtime/db/gateway.py
cli/runtime/db/service.py
cli/runtime/db/support.py
cli/runtime/dev/__init__.py
cli/runtime/dev/gateway.py
cli/runtime/dev/service.py
cli/runtime/dev/support.py
cli/runtime/gen/__init__.py
cli/runtime/gen/gateway.py
cli/runtime/gen/service.py
cli/runtime/gen/support.py
cli/runtime/job/__init__.py
cli/runtime/job/gateway.py
cli/runtime/job/service.py
cli/runtime/job/support.py
cli/runtime/ops/__init__.py
cli/runtime/ops/gateway.py
cli/runtime/ops/service.py
cli/runtime/ops/support.py
cli/tui/__init__.py
cli/tui/app.py
cli/tui/capabilities.py
cli/tui/commands.py
cli/tui/diagnostics.py
cli/tui/keymaps.py
cli/tui/search.py
cli/tui/actions/__init__.py
cli/tui/actions/assembly.py
cli/tui/actions/bootstrap.py
cli/tui/actions/builders.py
cli/tui/actions/execution.py
cli/tui/actions/models.py
cli/tui/actions/presentation.py
cli/tui/actions/registry.py
cli/tui/actions/factories/__init__.py
cli/tui/actions/factories/cache.py
cli/tui/actions/factories/gen.py
cli/tui/actions/factories/jobs.py
cli/tui/actions/factories/static.py
cli/tui/adapters/__init__.py
cli/tui/adapters/app.py
cli/tui/adapters/base.py
cli/tui/adapters/cache.py
cli/tui/adapters/configs.py
cli/tui/adapters/crypto.py
cli/tui/adapters/database.py
cli/tui/adapters/gen.py
cli/tui/adapters/health.py
cli/tui/adapters/jobs.py
cli/tui/adapters/models.py
cli/tui/adapters/ops.py
cli/tui/copy/__init__.py
cli/tui/copy/actions.py
cli/tui/copy/fragments.py
cli/tui/copy/navigation.py
cli/tui/copy/workspace.py
cli/tui/screens/__init__.py
cli/tui/screens/browser.py
cli/tui/screens/confirm.py
cli/tui/screens/dashboard.py
cli/tui/screens/detail.py
cli/tui/screens/focus.py
cli/tui/screens/interactions.py
cli/tui/screens/search.py
cli/tui/screens/summary.py
cli/tui/widgets/__init__.py
cli/tui/widgets/status_panel.py
cli/tui/widgets/workspace.py
cli/wizard/__init__.py
cli/wizard/aggregators.py
cli/wizard/base.py
cli/wizard/commands.py
cli/wizard/presenters.py
cli/wizard/preview.py
cli/wizard/prompts.py
cli/wizard/flows/__init__.py
cli/wizard/flows/app_run.py
cli/wizard/flows/cache_clear.py
cli/wizard/flows/db_upgrade.py
cli/wizard/flows/gen_export.py
cli/wizard/flows/gen_import.py
cli/wizard/flows/prod_check.py
shierfeng_fastapi_backend_cli.egg-info/PKG-INFO
shierfeng_fastapi_backend_cli.egg-info/SOURCES.txt
shierfeng_fastapi_backend_cli.egg-info/dependency_links.txt
shierfeng_fastapi_backend_cli.egg-info/entry_points.txt
shierfeng_fastapi_backend_cli.egg-info/top_level.txt
tests/test_log_sanitize_util.py
@@ -1,2 +0,0 @@
[console_scripts]
shierfeng = cli.main:main
@@ -135,3 +135,25 @@ ALTER TABLE biz_pallet_event
ADD INDEX idx_biz_pallet_event_test_batch_id (test_batch_id),
ADD CONSTRAINT fk_biz_pallet_event_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
-- 菜单迁移:移除旧物理删除权限,加入测试数据批次管理菜单。
-- 新菜单不自动授予普通角色;超级管理员由现有 admin 权限访问。
START TRANSACTION;
DELETE FROM sys_role_menu
WHERE menu_id IN (1068, 1072, 1076, 1081, 1085, 1090, 1095, 1102);
DELETE FROM sys_menu
WHERE menu_id IN (1068, 1072, 1076, 1081, 1085, 1090, 1095, 1102);
INSERT INTO sys_menu VALUES
(519, '测试数据批次', 1, '7', 'testBatch', 'system/testBatch/index', '', '', 1, 0, 'C', '0', '0', 'system:testbatch:list', '#', 'admin', SYSDATE(), '', NULL, '测试数据批次菜单'),
(1109, '批次查询', 519, '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:query', '#', 'admin', SYSDATE(), '', NULL, ''),
(1110, '批次新增', 519, '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:add', '#', 'admin', SYSDATE(), '', NULL, ''),
(1111, '批次修改', 519, '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:edit', '#', 'admin', SYSDATE(), '', NULL, ''),
(1112, '批次授权', 519, '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:assign', '#', 'admin', SYSDATE(), '', NULL, ''),
(1113, '批次关闭', 519, '5', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:close', '#', 'admin', SYSDATE(), '', NULL, ''),
(1114, '数据纳入', 519, '6', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:adopt', '#', 'admin', SYSDATE(), '', NULL, ''),
(1115, '批次清理', 519, '7', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:purge', '#', 'admin', SYSDATE(), '', NULL, '');
COMMIT;
@@ -1,139 +0,0 @@
-- 测试数据批次隔离:PostgreSQL 增量补丁
-- 本补丁仅增加可空归属字段,不回填既有数据。
CREATE TABLE biz_test_batch (
batch_id BIGSERIAL NOT NULL,
batch_code VARCHAR(64) NOT NULL,
batch_name VARCHAR(100) NOT NULL,
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
create_by VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
update_by VARCHAR(64) NOT NULL DEFAULT '',
update_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
closed_by BIGINT NULL,
closed_at TIMESTAMP WITHOUT TIME ZONE NULL,
purged_by BIGINT NULL,
purged_at TIMESTAMP WITHOUT TIME ZONE NULL,
purge_summary TEXT NULL,
preview_action VARCHAR(16) NULL,
preview_token_hash CHAR(64) NULL,
preview_scope_hash CHAR(64) NULL,
preview_expires_at TIMESTAMP WITHOUT TIME ZONE NULL,
remark VARCHAR(500) NULL,
PRIMARY KEY (batch_id),
CONSTRAINT uq_biz_test_batch_code UNIQUE (batch_code),
CONSTRAINT ck_biz_test_batch_status CHECK (status IN ('ACTIVE', 'CLOSED', 'PURGED')),
CONSTRAINT ck_biz_test_batch_preview_action CHECK (
preview_action IS NULL OR preview_action IN ('ADOPT', 'PURGE')
),
CONSTRAINT fk_biz_test_batch_closed_by FOREIGN KEY (closed_by) REFERENCES sys_user (user_id),
CONSTRAINT fk_biz_test_batch_purged_by FOREIGN KEY (purged_by) REFERENCES sys_user (user_id)
);
COMMENT ON TABLE biz_test_batch IS '测试数据批次';
CREATE TABLE biz_test_batch_user (
batch_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
create_by VARCHAR(64) NOT NULL DEFAULT '',
create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
PRIMARY KEY (batch_id, user_id),
CONSTRAINT fk_biz_test_batch_user_batch FOREIGN KEY (batch_id) REFERENCES biz_test_batch (batch_id),
CONSTRAINT fk_biz_test_batch_user_user FOREIGN KEY (user_id) REFERENCES sys_user (user_id)
);
COMMENT ON TABLE biz_test_batch_user IS '测试数据批次与用户关联';
ALTER TABLE biz_strain ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_strain.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_strain_test_batch_id ON biz_strain (test_batch_id);
ALTER TABLE biz_strain ADD CONSTRAINT fk_biz_strain_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_customer ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_customer.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_customer_test_batch_id ON biz_customer (test_batch_id);
ALTER TABLE biz_customer ADD CONSTRAINT fk_biz_customer_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_customer_site ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_customer_site.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_customer_site_test_batch_id ON biz_customer_site (test_batch_id);
ALTER TABLE biz_customer_site ADD CONSTRAINT fk_biz_customer_site_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_production_line ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_production_line.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_production_line_test_batch_id ON biz_production_line (test_batch_id);
ALTER TABLE biz_production_line ADD CONSTRAINT fk_biz_production_line_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_warehouse ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_warehouse.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_warehouse_test_batch_id ON biz_warehouse (test_batch_id);
ALTER TABLE biz_warehouse ADD CONSTRAINT fk_biz_warehouse_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_pallet ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_pallet.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_pallet_test_batch_id ON biz_pallet (test_batch_id);
ALTER TABLE biz_pallet ADD CONSTRAINT fk_biz_pallet_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_inbound_order ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_inbound_order.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_inbound_order_test_batch_id ON biz_inbound_order (test_batch_id);
ALTER TABLE biz_inbound_order ADD CONSTRAINT fk_biz_inbound_order_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_inbound_item ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_inbound_item.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_inbound_item_test_batch_id ON biz_inbound_item (test_batch_id);
ALTER TABLE biz_inbound_item ADD CONSTRAINT fk_biz_inbound_item_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_filling_record ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_filling_record.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_filling_record_test_batch_id ON biz_filling_record (test_batch_id);
ALTER TABLE biz_filling_record ADD CONSTRAINT fk_biz_filling_record_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_shipment_order ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_shipment_order.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_shipment_order_test_batch_id ON biz_shipment_order (test_batch_id);
ALTER TABLE biz_shipment_order ADD CONSTRAINT fk_biz_shipment_order_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_shipment_item ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_shipment_item.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_shipment_item_test_batch_id ON biz_shipment_item (test_batch_id);
ALTER TABLE biz_shipment_item ADD CONSTRAINT fk_biz_shipment_item_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_usage_record ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_usage_record.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_usage_record_test_batch_id ON biz_usage_record (test_batch_id);
ALTER TABLE biz_usage_record ADD CONSTRAINT fk_biz_usage_record_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_return_order ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_return_order.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_return_order_test_batch_id ON biz_return_order (test_batch_id);
ALTER TABLE biz_return_order ADD CONSTRAINT fk_biz_return_order_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_return_item ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_return_item.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_return_item_test_batch_id ON biz_return_item (test_batch_id);
ALTER TABLE biz_return_item ADD CONSTRAINT fk_biz_return_item_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_pallet_inventory ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_pallet_inventory.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_pallet_inventory_test_batch_id ON biz_pallet_inventory (test_batch_id);
ALTER TABLE biz_pallet_inventory ADD CONSTRAINT fk_biz_pallet_inventory_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
ALTER TABLE biz_pallet_event ADD COLUMN test_batch_id BIGINT NULL;
COMMENT ON COLUMN biz_pallet_event.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
CREATE INDEX idx_biz_pallet_event_test_batch_id ON biz_pallet_event (test_batch_id);
ALTER TABLE biz_pallet_event ADD CONSTRAINT fk_biz_pallet_event_test_batch_id
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
File diff suppressed because it is too large Load Diff
@@ -307,52 +307,52 @@ insert into sys_menu values('515', '发货出库', '123', '3', 'reportShipment',
insert into sys_menu values('516', '产线消耗', '123', '4', 'consumption', 'report/consumption/index', '', '', 1, 0, 'C', '0', '0', 'report:consumption:list', '#', 'admin', sysdate(), '', null, '产线消耗菜单');
insert into sys_menu values('517', '退回仓库', '123', '5', 'reportReturn', 'report/return/index', '', '', 1, 0, 'C', '0', '0', 'report:return:list', '#', 'admin', sysdate(), '', null, '退回仓库报表菜单');
insert into sys_menu values('518', '托盘追溯', '123', '6', 'palletTrace', 'report/palletTrace/index', '', '', 1, 0, 'C', '0', '0', 'report:pallettrace:list', '#', 'admin', sysdate(), '', null, '托盘追溯菜单');
insert into sys_menu values('519', '测试数据批次', '1', '7', 'testBatch', 'system/testBatch/index', '', '', 1, 0, 'C', '0', '0', 'system:testbatch:list', '#', 'admin', sysdate(), '', null, '测试数据批次菜单');
-- 托盘业务按钮
insert into sys_menu values('1065', '菌种查询', '502', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'master:strain:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1066', '菌种新增', '502', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'master:strain:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1067', '菌种修改', '502', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'master:strain:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1068', '菌种删除', '502', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'master:strain:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1069', '客户查询', '503', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'master:customer:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1070', '客户新增', '503', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'master:customer:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1071', '客户修改', '503', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'master:customer:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1072', '客户删除', '503', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'master:customer:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1073', '现场查询', '504', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'master:site:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1074', '现场新增', '504', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'master:site:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1075', '现场修改', '504', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'master:site:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1076', '现场删除', '504', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'master:site:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1077', '分配用户', '504', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'master:site:assign', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1078', '产线查询', '505', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'master:line:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1079', '产线新增', '505', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'master:line:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1080', '产线修改', '505', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'master:line:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1081', '产线删除', '505', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'master:line:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1082', '仓库查询', '506', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'master:warehouse:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1083', '仓库新增', '506', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'master:warehouse:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1084', '仓库修改', '506', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'master:warehouse:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1085', '仓库删除', '506', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'master:warehouse:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1086', '分配用户', '506', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'master:warehouse:assign', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1087', '托盘查询', '507', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'master:pallet:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1088', '托盘新增', '507', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'master:pallet:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1089', '托盘修改', '507', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'master:pallet:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1090', '托盘删除', '507', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'master:pallet:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1091', '托盘打印', '507', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'master:pallet:print', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1092', '入库查询', '508', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'business:inbound:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1093', '入库新增', '508', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'business:inbound:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1094', '入库修改', '508', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'business:inbound:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1095', '入库删除', '508', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'business:inbound:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1096', '入库确认', '508', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'business:inbound:confirm', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1097', '装填查询', '509', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'business:filling:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1098', '装填新增', '509', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'business:filling:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1099', '发货查询', '510', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'business:shipment:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1100', '发货新增', '510', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'business:shipment:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1101', '发货修改', '510', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'business:shipment:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1102', '发货删除', '510', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'business:shipment:remove', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1103', '发货确认', '510', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'business:shipment:confirm', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1104', '使用查询', '511', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'business:usage:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1105', '使用新增', '511', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'business:usage:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1106', '退回查询', '512', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'business:return:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1107', '退回申请', '512', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'business:return:request', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1108', '退回确认', '512', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'business:return:confirm', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1109', '批次查询', '519', '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:query', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1110', '批次新增', '519', '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:add', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1111', '批次修改', '519', '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:edit', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1112', '批次授权', '519', '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:assign', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1113', '批次关闭', '519', '5', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:close', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1114', '数据纳入', '519', '6', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:adopt', '#', 'admin', sysdate(), '', null, '');
insert into sys_menu values('1115', '批次清理', '519', '7', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:purge', '#', 'admin', sysdate(), '', null, '');
-- ----------------------------
@@ -436,7 +436,7 @@ def test_run_completion_coroutine_clears_scoped_app_env_when_original_missing(mo
async def _read_env() -> str | None:
return os.environ.get('APP_ENV')
result = completion_registry.dynamic_service.run_completion_coroutine(_read_env(), env='dockerpg')
result = completion_registry.dynamic_service.run_completion_coroutine(_read_env(), env='dockermy')
assert result == 'dockerpg'
assert result == 'dockermy'
assert 'APP_ENV' not in os.environ
@@ -3,7 +3,7 @@ import unittest
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock, patch
from sqlalchemy.dialects import mysql, postgresql
from sqlalchemy.dialects import mysql
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.orm import InstrumentedAttribute
from sqlalchemy.sql import Select, operators
@@ -205,7 +205,7 @@ class AccessDaoTest(unittest.IsolatedAsyncioTestCase):
await AccessDao.user_has_warehouse(db, 8, 99)
statement = db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()):
for dialect in (mysql.dialect(),):
sql = ' '.join(
str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).split()
)
@@ -250,7 +250,7 @@ class AccessDaoTest(unittest.IsolatedAsyncioTestCase):
await AccessDao.user_has_site(db, 8, 7)
statement = db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()):
for dialect in (mysql.dialect(),):
sql = ' '.join(
str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).split()
)

Some files were not shown because too many files have changed in this diff Show More