调整部分前端布局和后端增删改逻辑

This commit is contained in:
焦龙言
2026-09-26 23:11:05 +08:00
parent 977e7f996e
commit 17d991a74a
117 changed files with 311994 additions and 3192 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 的专门用例。 - 本轮新增的 TEST scope 入口成功回归目前集中于退回申请;入库、装填、发货和使用的既有业务成功回归仍以 `TestBatchScope.formal()` 为主。生产路径、DAO SQL scope 条件和六文件回归均已验证,但尚未为这四条链路分别补齐 TEST batch 成功、跨批次拒绝、CLOSED 拒绝、派生字段和 rollback 的专门用例。
- 目录级 Ruff format 和全仓 `git diff --check` 的既有非白名单阻塞仍按上文保留,未修改用户文件。 - 目录级 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 代码已具备提交条件;本报告仍只保留为本地审查材料,不应纳入业务提交。
+5 -13
View File
@@ -8,7 +8,7 @@
* 前端采用Vue3、Element Plus。 * 前端采用Vue3、Element Plus。
* 移动端采用uni-app、Vue3、Vite,内置tailwindcss。 * 移动端采用uni-app、Vue3、Vite,内置tailwindcss。
* 后端采用FastAPI、sqlalchemy、MySQL(PostgreSQL)、Redis、OAuth2 & Jwt。 * 后端采用FastAPI、sqlalchemy、MySQL、Redis、OAuth2 & Jwt。
* 权限认证使用OAuth2 & Jwt,支持多终端认证系统。 * 权限认证使用OAuth2 & Jwt,支持多终端认证系统。
* 支持加载动态权限菜单,多方式轻松权限控制。 * 支持加载动态权限菜单,多方式轻松权限控制。
* 纯Python版本: * 纯Python版本:
@@ -112,17 +112,15 @@ pnpm dev:mp-weixin
# 进入后端目录 # 进入后端目录
cd shierfeng-fastapi-backend cd shierfeng-fastapi-backend
# 如果使用的是MySQL数据库,请执行以下命令安装项目依赖环境 # 安装项目依赖环境(统一使用 MySQL)
pip3 install -r requirements.txt pip3 install -r requirements.txt
# 如果使用的是PostgreSQL数据库,请执行以下命令安装项目依赖环境
pip3 install -r requirements-pg.txt
# 配置环境 # 配置环境
在.env.dev文件中配置开发环境的数据库和redis 在.env.dev文件中配置开发环境的数据库和redis
# 运行sql文件 # 运行 SQL 文件
1.新建数据库shierfeng-fastapi(默认,可修改) 1. 新建数据库 shierfeng-fastapi(默认,可修改)
2.如果使用的是MySQL数据库,使用命令或数据库连接工具运行sql文件夹下的shierfeng-fastapi.sql;如果使用的是PostgreSQL数据库,使用命令或数据库连接工具运行sql文件夹下的shierfeng-fastapi-pg.sql 2. 使用命令或数据库连接工具运行 sql 文件夹下的 shierfeng-fastapi.sql
# 运行后端 # 运行后端
shierfeng app run --env=dev shierfeng app run --env=dev
@@ -172,9 +170,3 @@ shierfeng app run --env=prod
```bash ```bash
docker compose -f shierfeng-fastapi-test/docker-compose.test.my.yml up -d --build 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** - [ ] **Step 1: 写路由、权限和凭据安全测试并确认 RED**
测试必须断言五个页面路径和标题存在,工作台包含五类业务权限字符串,且 `src/pages/login.vue` 不再包含 `admin123` 或其他密码字面量。测试也要断言入口跳转路径与页面路径一致。 测试必须断言五个页面路径和标题存在,工作台包含五类业务权限字符串,且 `src/pages/login.vue` 不再包含旧默认密码或其他密码字面量。测试也要断言入口跳转路径与页面路径一致。
- [ ] **Step 2: 注册五个页面并实现入口过滤** - [ ] **Step 2: 注册五个页面并实现入口过滤**
@@ -702,7 +702,7 @@ ruff check module_business tests/module_business
```bash ```bash
git diff --check HEAD~9..HEAD 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 rg -n 'Bearer[[:space:]]+[A-Za-z0-9._-]+' shierfeng-fastapi-app/src shierfeng-fastapi-app/tests
git status --short git status --short
``` ```
@@ -148,6 +148,32 @@ return.js
## 9. 当前基线与风险 ## 9. 当前基线与风险
- Web/FastAPI 核心业务已存在并有业务测试;本次重点是 uni-app PDA 缺失能力。 - Web/FastAPI 核心业务已存在并有业务测试;本次重点是 uni-app PDA 缺失能力。
- 当前 PDA 工程只有通用登录、首页、工作台和个人中心,尚无业务页面与业务 API 模块。 - 当前 PDA 工程已包含通用登录、首页、工作台、个人中心,以及入库、装填、发货、现场使用、退回五类业务页面和对应 API 模块。
- 后端接口已存在,但 PDA 的实际设备联调、服务器访问地址和真实角色授权仍需运行环境配合。 - 后端接口、Web 管理页面和数据库 SQL 已存在;PDA 的实际设备联调、服务器访问地址、数据库迁移和真实角色授权仍需运行环境配合。
- APK 暂不打包,因此本次交付物是源码、接口封装、页面和可验证开发版本,不包含安装包。 - 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`;密码保持空白并由操作员手工输入,不将真实密码写入源码、测试或日志。
+1 -1
View File
@@ -12,7 +12,7 @@
## 上线前准备 ## 上线前准备
1. 先备份数据库,并确认当前没有正在进行的入库、装填、发货、使用或退回操作。 1. 先备份数据库,并确认当前没有正在进行的入库、装填、发货、使用或退回操作。
2. MySQL 只执行 `shierfeng-fastapi-backend/sql/patches/20260922_test_data_batch_mysql.sql`;PostgreSQL 只执行对应的 `_pg.sql` 文件,不能同时执行两份。 2. MySQL 执行 `shierfeng-fastapi-backend/sql/patches/20260922_test_data_batch_mysql.sql`。
3. 迁移完成后检查 `biz_test_batch`、`biz_test_batch_user` 和各业务表的 `test_batch_id` 字段及外键。 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` 秒。 4. 配置在线清理上限。默认 `TEST_BATCH_ONLINE_PURGE_MAX_ROWS=0`,表示禁止在线清理;只有明确配置为正整数且批次影响总数不超过上限时,管理页才允许执行清理。预览令牌默认有效期为 `TEST_BATCH_PREVIEW_TTL_SECONDS=600` 秒。
+1
View File
@@ -2,6 +2,7 @@
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8" /> <meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/static/favicon.ico" />
<script> <script>
var coverSupport = var coverSupport =
'CSS' in window && 'CSS' in window &&
+1 -1
View File
@@ -9,7 +9,7 @@ export default {
// 应用版本 // 应用版本
version: "1.9.0", version: "1.9.0",
// 应用logo // 应用logo
logo: "/static/logo.png", logo: "/static/sylvan-logo.png",
// 官方网站 // 官方网站
site_url: "https://vfadmin.insistence.tech", site_url: "https://vfadmin.insistence.tech",
// 政策协议 // 政策协议
+3 -3
View File
@@ -5,12 +5,12 @@
<!-- Logo Section --> <!-- Logo Section -->
<view class="mb-6 flex flex-col items-center"> <view class="mb-6 flex flex-col items-center">
<view <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 <image
class="size-10" class="h-16 w-full"
:src="globalConfig.appInfo.logo" :src="globalConfig.appInfo.logo"
mode="widthFix" mode="aspectFit"
/> />
</view> </view>
<text class="text-xl font-bold tracking-wide text-gray-800" <text class="text-xl font-bold tracking-wide text-gray-800"
@@ -2,11 +2,13 @@
<view class="flex h-full flex-col bg-gray-50 pb-10"> <view class="flex h-full flex-col bg-gray-50 pb-10">
<!-- Header --> <!-- Header -->
<view class="flex flex-col items-center py-10"> <view class="flex flex-col items-center py-10">
<image <view class="flex h-24 w-64 items-center justify-center rounded-xl bg-gray-800 px-4 shadow-md">
class="size-20 rounded-xl shadow-md" <image
src="/static/logo200.png" class="h-20 w-full"
mode="widthFix" src="/static/sylvan-logo.png"
/> mode="aspectFit"
/>
</view>
<text class="mt-4 text-xl font-bold text-gray-800" <text class="mt-4 text-xl font-bold text-gray-800"
>智链云枢管理系统</text >智链云枢管理系统</text
> >
+3 -3
View File
@@ -5,12 +5,12 @@
<!-- Logo Section --> <!-- Logo Section -->
<view class="mb-6 flex flex-col items-center"> <view class="mb-6 flex flex-col items-center">
<view <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 <image
class="size-10" class="h-16 w-full"
:src="globalConfig.appInfo.logo" :src="globalConfig.appInfo.logo"
mode="widthFix" mode="aspectFit"
/> />
</view> </view>
<text class="text-xl font-bold tracking-wide text-gray-800" <text class="text-xl font-bold tracking-wide text-gray-800"
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

@@ -6,6 +6,29 @@ import { test } from "node:test";
const appRoot = fileURLToPath(new URL("..", import.meta.url)); 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 = { const apiContracts = {
"src/api/business/inbound.js": [ "src/api/business/inbound.js": [
["listInbound", "'/business/inbound/list'", "get"], ["listInbound", "'/business/inbound/list'", "get"],
+3 -1
View File
@@ -42,7 +42,7 @@ JWT_REDIS_EXPIRE_MINUTES = 30
# -------- 数据库配置 -------- # -------- 数据库配置 --------
# 数据库类型,可选的有'mysql'、'postgresql',默认为'mysql' # 数据库类型,固定使用'mysql'
DB_TYPE = 'mysql' DB_TYPE = 'mysql'
# 数据库主机 # 数据库主机
DB_HOST = '127.0.0.1' DB_HOST = '127.0.0.1'
@@ -171,3 +171,5 @@ TRANSPORT_CRYPTO_ENABLED_PATHS = ''
TRANSPORT_CRYPTO_REQUIRED_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' 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_TYPE = 'mysql'
# 数据库主机 # 数据库主机
DB_HOST = 'shierfeng-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_TYPE = 'mysql'
# 数据库主机 # 数据库主机
DB_HOST = '127.0.0.1' DB_HOST = '127.0.0.1'
@@ -171,3 +171,5 @@ TRANSPORT_CRYPTO_ENABLED_PATHS = ''
TRANSPORT_CRYPTO_REQUIRED_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' 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 dataclasses import dataclass
from pathlib import Path from pathlib import Path
DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy', 'dockerpg') DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy')
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -28,7 +28,7 @@ GENERAL_COPY = {
'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回', 'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回',
'more_detail_hint': '> 进入对应页面查看更多', 'more_detail_hint': '> 进入对应页面查看更多',
'tui_command_help': '进入只读巡检工作台', '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`', 'tui_missing_dependency_message': '当前环境未安装 TUI 可选依赖,无法启动 `shierfeng tui`',
} }
@@ -1,7 +1,7 @@
from dataclasses import dataclass from dataclasses import dataclass
from pathlib import Path from pathlib import Path
DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy', 'dockerpg') DEFAULT_ENVIRONMENTS = ('dev', 'prod', 'dockermy')
@dataclass(frozen=True) @dataclass(frozen=True)
@@ -28,7 +28,7 @@ GENERAL_COPY = {
'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回', 'action_confirm_hint': '按键提示 · [Enter] 确认执行 [Esc] 取消返回',
'more_detail_hint': '> 进入对应页面查看更多', 'more_detail_hint': '> 进入对应页面查看更多',
'tui_command_help': '进入只读巡检工作台', '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`', 'tui_missing_dependency_message': '当前环境未安装 TUI 可选依赖,无法启动 `shierfeng tui`',
} }
+105 -245
View File
@@ -1,4 +1,3 @@
from config.env import DataBaseConfig
class CommonConstant: class CommonConstant:
@@ -549,42 +548,19 @@ class GenConstant:
TREE_NAME = 'treeName' TREE_NAME = 'treeName'
PARENT_MENU_ID = 'parentMenuId' PARENT_MENU_ID = 'parentMenuId'
PARENT_MENU_NAME = 'parentMenuName' PARENT_MENU_NAME = 'parentMenuName'
COLUMNTYPE_STR = ( COLUMNTYPE_STR = ['char', 'varchar', 'nvarchar', 'varchar2']
['character varying', 'varchar', 'character', 'char'] COLUMNTYPE_TEXT = ['tinytext', 'text', 'mediumtext', 'longtext']
if DataBaseConfig.db_type == 'postgresql' COLUMNTYPE_TIME = ['datetime', 'time', 'date', 'timestamp']
else ['char', 'varchar', 'nvarchar', 'varchar2'] COLUMNTYPE_GEOMETRY = [
) 'geometry',
COLUMNTYPE_TEXT = ( 'point',
['text', 'citext'] if DataBaseConfig.db_type == 'postgresql' else ['tinytext', 'text', 'mediumtext', 'longtext'] 'linestring',
) 'polygon',
COLUMNTYPE_TIME = ( 'multipoint',
[ 'multilinestring',
'date', 'multipolygon',
'time', 'geometrycollection',
'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 [
'geometry',
'point',
'linestring',
'polygon',
'multipoint',
'multilinestring',
'multipolygon',
'geometrycollection',
]
)
COLUMNTYPE_NUMBER = [ COLUMNTYPE_NUMBER = [
'tinyint', 'tinyint',
'smallint', 'smallint',
@@ -619,211 +595,95 @@ class GenConstant:
QUERY_LIKE = 'LIKE' QUERY_LIKE = 'LIKE'
QUERY_EQ = 'EQ' QUERY_EQ = 'EQ'
REQUIRE = '1' REQUIRE = '1'
DB_TO_SQLALCHEMY_TYPE_MAPPING = ( DB_TO_SQLALCHEMY_TYPE_MAPPING = {
{ # 数值类型
'boolean': 'Boolean', 'TINYINT': 'SmallInteger',
'smallint': 'SmallInteger', 'SMALLINT': 'SmallInteger',
'integer': 'Integer', 'MEDIUMINT': 'Integer',
'bigint': 'BigInteger', 'INT': 'Integer',
'real': 'Float', 'INTEGER': 'Integer',
'double precision': 'Float', 'BIGINT': 'BigInteger',
'numeric': 'Numeric', 'FLOAT': 'Float',
'character varying': 'String', 'DOUBLE': 'Float',
'character': 'String', 'DECIMAL': 'DECIMAL',
'text': 'Text', 'BIT': 'Integer',
'bytea': 'LargeBinary', # 日期和时间类型
'date': 'Date', 'DATE': 'Date',
'time': 'Time', 'TIME': 'Time',
'time with time zone': 'Time', 'DATETIME': 'DateTime',
'time without time zone': 'Time', 'TIMESTAMP': 'TIMESTAMP',
'timestamp': 'DateTime', 'YEAR': 'Integer',
'timestamp with time zone': 'DateTime', # 字符串类型
'timestamp without time zone': 'DateTime', 'CHAR': 'CHAR',
'interval': 'Interval', 'VARCHAR': 'String',
'json': 'JSON', 'TINYTEXT': 'Text',
'jsonb': 'JSONB', 'TEXT': 'Text',
'uuid': 'Uuid', 'MEDIUMTEXT': 'Text',
'inet': 'INET', 'LONGTEXT': 'Text',
'cidr': 'CIDR', 'BINARY': 'BINARY',
'macaddr': 'MACADDR', 'VARBINARY': 'VARBINARY',
'point': 'Geometry', 'TINYBLOB': 'LargeBinary',
'line': 'Geometry', 'BLOB': 'LargeBinary',
'lseg': 'Geometry', 'MEDIUMBLOB': 'LargeBinary',
'box': 'Geometry', 'LONGBLOB': 'LargeBinary',
'path': 'Geometry', # 枚举和集合类型
'polygon': 'Geometry', 'ENUM': 'Enum',
'circle': 'Geometry', 'SET': 'String',
'bit': 'Bit', # JSON 类型
'bit varying': 'Bit', 'JSON': 'JSON',
'tsvector': 'TSVECTOR', # 空间数据类型(需要扩展支持,如 GeoAlchemy2)
'tsquery': 'TSQUERY', 'GEOMETRY': 'Geometry', # 需要安装 geoalchemy2
'xml': 'String', 'POINT': 'Geometry',
'array': 'ARRAY', 'LINESTRING': 'Geometry',
'composite': 'JSON', 'POLYGON': 'Geometry',
'enum': 'Enum', 'MULTIPOINT': 'Geometry',
'range': 'Range', 'MULTILINESTRING': 'Geometry',
'money': 'Numeric', 'MULTIPOLYGON': 'Geometry',
'pg_lsn': 'BigInteger', 'GEOMETRYCOLLECTION': 'Geometry',
'txid_snapshot': 'String', }
'oid': 'BigInteger', DB_TO_PYTHON_TYPE_MAPPING = {
'regproc': 'String', # 数值类型
'regclass': 'String', 'TINYINT': 'int',
'regtype': 'String', 'SMALLINT': 'int',
'regrole': 'String', 'MEDIUMINT': 'int',
'regnamespace': 'String', 'INT': 'int',
'int2vector': 'ARRAY', 'INTEGER': 'int',
'oidvector': 'ARRAY', 'BIGINT': 'int',
'pg_node_tree': 'Text', 'FLOAT': 'float',
} 'DOUBLE': 'float',
if DataBaseConfig.db_type == 'postgresql' 'DECIMAL': 'Decimal',
else { 'BIT': 'int',
# 数值类型 # 日期和时间类型
'TINYINT': 'SmallInteger', 'DATE': 'date',
'SMALLINT': 'SmallInteger', 'TIME': 'time',
'MEDIUMINT': 'Integer', 'DATETIME': 'datetime',
'INT': 'Integer', 'TIMESTAMP': 'datetime',
'INTEGER': 'Integer', 'YEAR': 'int',
'BIGINT': 'BigInteger', # 字符串类型
'FLOAT': 'Float', 'CHAR': 'str',
'DOUBLE': 'Float', 'VARCHAR': 'str',
'DECIMAL': 'DECIMAL', 'TINYTEXT': 'str',
'BIT': 'Integer', 'TEXT': 'str',
# 日期和时间类型 'MEDIUMTEXT': 'str',
'DATE': 'Date', 'LONGTEXT': 'str',
'TIME': 'Time', 'BINARY': 'bytes',
'DATETIME': 'DateTime', 'VARBINARY': 'bytes',
'TIMESTAMP': 'TIMESTAMP', 'TINYBLOB': 'bytes',
'YEAR': 'Integer', 'BLOB': 'bytes',
# 字符串类型 'MEDIUMBLOB': 'bytes',
'CHAR': 'CHAR', 'LONGBLOB': 'bytes',
'VARCHAR': 'String', # 枚举和集合类型
'TINYTEXT': 'Text', 'ENUM': 'str',
'TEXT': 'Text', 'SET': 'str',
'MEDIUMTEXT': 'Text', # JSON 类型
'LONGTEXT': 'Text', 'JSON': 'dict',
'BINARY': 'BINARY', # 空间数据类型(通常需要特殊处理)
'VARBINARY': 'VARBINARY', 'GEOMETRY': 'bytes',
'TINYBLOB': 'LargeBinary', 'POINT': 'bytes',
'BLOB': 'LargeBinary', 'LINESTRING': 'bytes',
'MEDIUMBLOB': 'LargeBinary', 'POLYGON': 'bytes',
'LONGBLOB': 'LargeBinary', 'MULTIPOINT': 'bytes',
# 枚举和集合类型 'MULTILINESTRING': 'bytes',
'ENUM': 'Enum', 'MULTIPOLYGON': 'bytes',
'SET': 'String', 'GEOMETRYCOLLECTION': 'bytes',
# JSON 类型 }
'JSON': 'JSON',
# 空间数据类型(需要扩展支持,如 GeoAlchemy2)
'GEOMETRY': 'Geometry', # 需要安装 geoalchemy2
'POINT': 'Geometry',
'LINESTRING': 'Geometry',
'POLYGON': 'Geometry',
'MULTIPOINT': 'Geometry',
'MULTILINESTRING': 'Geometry',
'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 {
# 数值类型
'TINYINT': 'int',
'SMALLINT': 'int',
'MEDIUMINT': 'int',
'INT': 'int',
'INTEGER': 'int',
'BIGINT': 'int',
'FLOAT': 'float',
'DOUBLE': 'float',
'DECIMAL': 'Decimal',
'BIT': 'int',
# 日期和时间类型
'DATE': 'date',
'TIME': 'time',
'DATETIME': 'datetime',
'TIMESTAMP': 'datetime',
'YEAR': 'int',
# 字符串类型
'CHAR': 'str',
'VARCHAR': 'str',
'TINYTEXT': 'str',
'TEXT': 'str',
'MEDIUMTEXT': 'str',
'LONGTEXT': 'str',
'BINARY': 'bytes',
'VARBINARY': 'bytes',
'TINYBLOB': 'bytes',
'BLOB': 'bytes',
'MEDIUMBLOB': 'bytes',
'LONGBLOB': 'bytes',
# 枚举和集合类型
'ENUM': 'str',
'SET': 'str',
# JSON 类型
'JSON': 'dict',
# 空间数据类型(通常需要特殊处理)
'GEOMETRY': 'bytes',
'POINT': 'bytes',
'LINESTRING': 'bytes',
'POLYGON': 'bytes',
'MULTIPOINT': 'bytes',
'MULTILINESTRING': 'bytes',
'MULTIPOLYGON': 'bytes',
'GEOMETRYCOLLECTION': 'bytes',
}
)
@@ -13,11 +13,6 @@ def build_async_sqlalchemy_database_url() -> str:
:return: 异步 SQLAlchemy 数据库连接 URL :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 ( return (
f'mysql+asyncmy://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@' f'mysql+asyncmy://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}' f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}'
@@ -33,11 +28,6 @@ def build_sync_sqlalchemy_database_url() -> str:
:return: 同步 SQLAlchemy 数据库连接 URL :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 ( return (
f'mysql+pymysql://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@' f'mysql+pymysql://{DataBaseConfig.db_username}:{quote_plus(DataBaseConfig.db_password)}@'
f'{DataBaseConfig.db_host}:{DataBaseConfig.db_port}/{DataBaseConfig.db_database}' 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_host: str = '127.0.0.1'
db_port: int = 3306 db_port: int = 3306
db_username: str = 'root' db_username: str = 'root'
@@ -62,8 +62,6 @@ class DataBaseSettings(BaseSettings):
@computed_field @computed_field
@property @property
def sqlglot_parse_dialect(self) -> str: def sqlglot_parse_dialect(self) -> str:
if self.db_type == 'postgresql':
return 'postgres'
return self.db_type return self.db_type
+5 -13
View File
@@ -38,23 +38,16 @@ shierfeng --help
### 2.2 安装依赖 ### 2.2 安装依赖
MySQL 版本: 安装依赖(统一使用 MySQL):
```bash ```bash
cd shierfeng-fastapi-backend cd shierfeng-fastapi-backend
pip3 install -r requirements.txt 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 环境一起可用 - 安装完成后,`shierfeng` 会随当前 Python 环境一起可用
如果本地使用 Conda,推荐先进入项目环境再执行命令: 如果本地使用 Conda,推荐先进入项目环境再执行命令:
@@ -65,7 +58,7 @@ cd shierfeng-fastapi-backend
shierfeng --help shierfeng --help
``` ```
`textual` 已包含在现有依赖文件中,因此安装 `requirements.txt` 或 `requirements-pg.txt` 后即可直接使用 TUI。 `textual` 已包含在现有依赖文件中,安装 `requirements.txt` 后即可直接使用 TUI。
### 2.3 第一个命令 ### 2.3 第一个命令
@@ -104,7 +97,6 @@ CLI 不单独维护配置系统,仍然复用项目原有的 `config/env.py`
- `--env=dev` -> `.env.dev` - `--env=dev` -> `.env.dev`
- `--env=prod` -> `.env.prod` - `--env=prod` -> `.env.prod`
- `--env=dockermy` -> `.env.dockermy` - `--env=dockermy` -> `.env.dockermy`
- `--env=dockerpg` -> `.env.dockerpg`
### 3.3 帮助命令 ### 3.3 帮助命令
@@ -494,7 +486,7 @@ shierfeng tui --env=prod
- 当前 TUI 是只读巡检工作台,页面内的写操作入口会通过确认弹窗或向导二次确认 - 当前 TUI 是只读巡检工作台,页面内的写操作入口会通过确认弹窗或向导二次确认
- 页面切换快捷键为 `D/A/O/B/C/T/G/P/E`,分别对应总览、应用、运维、数据库、缓存、任务、代码生成、参数配置、加密 - 页面切换快捷键为 `D/A/O/B/C/T/G/P/E`,分别对应总览、应用、运维、数据库、缓存、任务、代码生成、参数配置、加密
- 通用快捷键包括 `R` 刷新、`Q` 退出、`S` 聚焦侧栏、`←/→` 切换焦点或区域、`J/K` 滚动、`PgUp/PgDn` 翻页、`Home/End` 首尾跳转 - 通用快捷键包括 `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. 危险命令清单 ## 6. 危险命令清单
@@ -814,7 +806,7 @@ shierfeng ops health --env=dev --output=json
请依次确认: 请依次确认:
- 当前目录是否为 `shierfeng-fastapi-backend` - 当前目录是否为 `shierfeng-fastapi-backend`
- 当前 Python 环境是否执行过 `pip install -r requirements.txt` 或 `pip install -r requirements-pg.txt` - 当前 Python 环境是否执行过 `pip install -r requirements.txt`
- 当前终端是否真的使用了安装依赖的那个 Python/Conda 环境 - 当前终端是否真的使用了安装依赖的那个 Python/Conda 环境
### 8.2 命令报数据库或 Redis 连接失败 ### 8.2 命令报数据库或 Redis 连接失败
@@ -64,23 +64,20 @@ TRANSPORT_CRYPTO_MAX_GET_URL_LENGTH=4096
当前项目的 Docker 部署使用: 当前项目的 Docker 部署使用:
- `shierfeng-fastapi-test/docker-compose.test.my.yml` + `shierfeng-fastapi-backend/Dockerfile.my` - `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=dockermy`
- `shierfeng app run --env=dockerpg`
所以 Docker 环境需要直接在以下文件中配置传输层密钥: 所以 Docker 环境需要直接在以下文件中配置传输层密钥:
- `shierfeng-fastapi-backend/.env.dockermy` - `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 服务 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: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: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 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 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 sqlalchemy.dialects import mysql
from config.database import Base from config.database import Base
@@ -20,7 +20,7 @@ class SysNotice(Base):
notice_title = Column(String(50), nullable=False, comment='公告标题') notice_title = Column(String(50), nullable=False, comment='公告标题')
notice_type = Column(CHAR(1), nullable=False, comment='公告类型(1通知 2公告)') notice_type = Column(CHAR(1), nullable=False, comment='公告类型(1通知 2公告)')
notice_content = Column( notice_content = Column(
mysql.LONGBLOB if DataBaseConfig.db_type == 'mysql' else LargeBinary, mysql.LONGBLOB,
nullable=True, nullable=True,
server_default=SqlalchemyUtil.get_server_default_null(DataBaseConfig.db_type, False), server_default=SqlalchemyUtil.get_server_default_null(DataBaseConfig.db_type, False),
comment='公告内容', comment='公告内容',
@@ -1,6 +1,6 @@
from datetime import datetime 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 sqlalchemy.dialects import mysql
from config.database import Base from config.database import Base
@@ -27,13 +27,13 @@ class SysRole(Base):
comment='数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)', comment='数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)',
) )
menu_check_strictly = Column( menu_check_strictly = Column(
mysql.TINYINT(display_width=1) if DataBaseConfig.db_type == 'mysql' else SmallInteger, mysql.TINYINT(display_width=1),
nullable=True, nullable=True,
server_default='1', server_default='1',
comment='菜单树选择项是否关联显示', comment='菜单树选择项是否关联显示',
) )
dept_check_strictly = Column( dept_check_strictly = Column(
mysql.TINYINT(display_width=1) if DataBaseConfig.db_type == 'mysql' else SmallInteger, mysql.TINYINT(display_width=1),
nullable=True, nullable=True,
server_default='1', server_default='1',
comment='部门树选择项是否关联显示', comment='部门树选择项是否关联显示',
@@ -107,8 +107,6 @@ class LoginService:
logger.warning('用户不存在') logger.warning('用户不存在')
raise LoginException(data='', message='用户不存在') raise LoginException(data='', message='用户不存在')
if not PwdUtil.verify_password(login_user.password, user[0].password): 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( cache_password_error_count = await request.app.state.redis.get(
f'{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.key}:{login_user.user_name}' f'{RedisInitKeyConfig.PASSWORD_ERROR_COUNT.key}:{login_user.user_name}'
) )
@@ -53,6 +53,7 @@ class MasterDao:
query_object.page_num, query_object.page_num,
query_object.page_size, query_object.page_size,
is_page, is_page,
exclude_fields={'test_batch_id'},
) )
@staticmethod @staticmethod
@@ -145,6 +145,7 @@ class OperationDao:
query_object.page_num, query_object.page_num,
query_object.page_size, query_object.page_size,
is_page, is_page,
exclude_fields={'test_batch_id'},
) )
@staticmethod @staticmethod
@@ -143,6 +143,7 @@ class ReportDao:
query_object.page_num, query_object.page_num,
query_object.page_size, query_object.page_size,
True, True,
exclude_fields={'test_batch_id'},
) )
@classmethod @classmethod
@@ -141,47 +141,27 @@ class GenTableDao:
:param is_page: 是否开启分页 :param is_page: 是否开启分页
:return: 数据库列表信息对象 :return: 数据库列表信息对象
""" """
if DataBaseConfig.db_type == 'postgresql': query_sql = r"""
query_sql = """ table_name as table_name,
table_name as table_name, table_comment as table_comment,
table_comment as table_comment, create_time as create_time,
create_time as create_time, update_time as update_time
update_time as update_time from
from information_schema.tables
list_table where
where table_schema = (select database())
table_name not like 'apscheduler_%' and table_name not like 'apscheduler\_%'
and table_name not like 'gen_%' and table_name not like 'gen\_%'
and table_name not in (select table_name from gen_table) 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,
create_time as create_time,
update_time as update_time
from
information_schema.tables
where
table_schema = (select database())
and table_name not like 'apscheduler\_%'
and table_name not like 'gen\_%'
and table_name not in (select table_name from gen_table)
"""
if query_object.table_name: if query_object.table_name:
query_sql += """and lower(table_name) like lower(concat('%', :table_name, '%'))""" query_sql += """and lower(table_name) like lower(concat('%', :table_name, '%'))"""
if query_object.table_comment: if query_object.table_comment:
query_sql += """and lower(table_comment) like lower(concat('%', :table_comment, '%'))""" query_sql += """and lower(table_comment) like lower(concat('%', :table_comment, '%'))"""
if query_object.begin_time: if query_object.begin_time:
if DataBaseConfig.db_type == 'postgresql': query_sql += """and date_format(create_time, '%Y%m%d') >= date_format(:begin_time, '%Y%m%d')"""
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 query_object.end_time:
if DataBaseConfig.db_type == 'postgresql': query_sql += """and date_format(create_time, '%Y%m%d') >= date_format(:end_time, '%Y%m%d')"""
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_sql += """order by create_time desc"""
query = select( query = select(
text(query_sql).bindparams(**query_object.model_dump(exclude_none=True, exclude={'page_num', 'page_size'})) text(query_sql).bindparams(**query_object.model_dump(exclude_none=True, exclude={'page_num', 'page_size'}))
@@ -201,35 +181,20 @@ class GenTableDao:
:param table_names: 业务表名称组 :param table_names: 业务表名称组
:return: 数据库列表信息对象 :return: 数据库列表信息对象
""" """
if DataBaseConfig.db_type == 'postgresql': query_sql = r"""
query_sql = """ select
select table_name as table_name,
table_name as table_name, table_comment as table_comment,
table_comment as table_comment, create_time as create_time,
create_time as create_time, update_time as update_time
update_time as update_time from
from information_schema.tables
list_table where
where table_name not like 'qrtz\_%'
table_name not like 'qrtz_%' and table_name not like 'gen\_%'
and table_name not like 'gen_%' and table_schema = (select database())
and table_name = any(:table_names) and table_name in :table_names
""" """
else:
query_sql = r"""
select
table_name as table_name,
table_comment as table_comment,
create_time as create_time,
update_time as update_time
from
information_schema.tables
where
table_name not like 'qrtz\_%'
and table_name not like 'gen\_%'
and table_schema = (select database())
and table_name in :table_names
"""
query = text(query_sql).bindparams(table_names=tuple(table_names)) query = text(query_sql).bindparams(table_names=tuple(table_names))
gen_db_table_list = (await db.execute(query)).fetchall() gen_db_table_list = (await db.execute(query)).fetchall()
@@ -308,42 +273,32 @@ class GenTableColumnDao:
:param table_name: 业务表名称 :param table_name: 业务表名称
:return: 业务表字段列表信息对象 :return: 业务表字段列表信息对象
""" """
if DataBaseConfig.db_type == 'postgresql': query_sql = """
query_sql = """ select
select column_name as column_name,
column_name, is_required, is_pk, sort, column_comment, is_increment, column_type case
from when is_nullable = 'no' and column_key != 'PRI' then '1'
list_column else '0'
where end as is_required,
table_name = :table_name case
""" when column_key = 'PRI' then '1'
else: else '0'
query_sql = """ end as is_pk,
select ordinal_position as sort,
column_name as column_name, column_comment as column_comment,
case case
when is_nullable = 'no' and column_key != 'PRI' then '1' when extra = 'auto_increment' then '1'
else '0' else '0'
end as is_required, end as is_increment,
case column_type as column_type
when column_key = 'PRI' then '1' from
else '0' information_schema.columns
end as is_pk, where
ordinal_position as sort, table_schema = (select database())
column_comment as column_comment, and table_name = :table_name
case order by
when extra = 'auto_increment' then '1' ordinal_position
else '0' """
end as is_increment,
column_type as column_type
from
information_schema.columns
where
table_schema = (select database())
and table_name = :table_name
order by
ordinal_position
"""
query = text(query_sql).bindparams(table_name=table_name) query = text(query_sql).bindparams(table_name=table_name)
gen_db_table_columns = (await db.execute(query)).fetchall() gen_db_table_columns = (await db.execute(query)).fetchall()
@@ -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 -- 菜单 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) 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 }}菜单'); 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) 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, ''); 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
@@ -1,161 +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);
-- 菜单迁移:移除旧物理删除权限,加入测试数据批次管理菜单。
-- 新菜单不自动授予普通角色;超级管理员由现有 admin 权限访问。
BEGIN;
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', CURRENT_TIMESTAMP, '', NULL, '测试数据批次菜单'),
(1109, '批次查询', 519, '1', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:query', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, ''),
(1110, '批次新增', 519, '2', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:add', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, ''),
(1111, '批次修改', 519, '3', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:edit', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, ''),
(1112, '批次授权', 519, '4', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:assign', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, ''),
(1113, '批次关闭', 519, '5', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:close', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, ''),
(1114, '数据纳入', 519, '6', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:adopt', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, ''),
(1115, '批次清理', 519, '7', '', '', '', '', 1, 0, 'F', '0', '0', 'system:testbatch:purge', '#', 'admin', CURRENT_TIMESTAMP, '', NULL, '');
COMMIT;
File diff suppressed because it is too large Load Diff
@@ -436,7 +436,7 @@ def test_run_completion_coroutine_clears_scoped_app_env_when_original_missing(mo
async def _read_env() -> str | None: async def _read_env() -> str | None:
return os.environ.get('APP_ENV') 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 assert 'APP_ENV' not in os.environ
@@ -3,7 +3,7 @@ import unittest
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock, patch 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.ext.asyncio import AsyncSession
from sqlalchemy.orm import InstrumentedAttribute from sqlalchemy.orm import InstrumentedAttribute
from sqlalchemy.sql import Select, operators from sqlalchemy.sql import Select, operators
@@ -205,7 +205,7 @@ class AccessDaoTest(unittest.IsolatedAsyncioTestCase):
await AccessDao.user_has_warehouse(db, 8, 99) await AccessDao.user_has_warehouse(db, 8, 99)
statement = db.execute.await_args.args[0] statement = db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = ' '.join( sql = ' '.join(
str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).split() 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) await AccessDao.user_has_site(db, 8, 7)
statement = db.execute.await_args.args[0] statement = db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = ' '.join( sql = ' '.join(
str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).split() str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).split()
) )
@@ -70,7 +70,7 @@ class AiRemovalContractTest(unittest.TestCase):
def test_ai_dependencies_are_removed(self) -> None: def test_ai_dependencies_are_removed(self) -> None:
backend_dependencies = set() backend_dependencies = set()
for filename in ('requirements.txt', 'requirements-pg.txt'): for filename in ('requirements.txt',):
backend_dependencies.update(_parse_requirement_names(BACKEND_ROOT / filename)) backend_dependencies.update(_parse_requirement_names(BACKEND_ROOT / filename))
self.assertEqual([], sorted(AI_DEPENDENCIES & backend_dependencies)) self.assertEqual([], sorted(AI_DEPENDENCIES & backend_dependencies))
@@ -82,7 +82,7 @@ class AiRemovalContractTest(unittest.TestCase):
def test_initialization_sql_has_no_ai_or_external_menu(self) -> None: def test_initialization_sql_has_no_ai_or_external_menu(self) -> None:
forbidden_terms = ('ai_models', 'ai_chat_config', 'ai_provider_type', '施尔丰仓库') forbidden_terms = ('ai_models', 'ai_chat_config', 'ai_provider_type', '施尔丰仓库')
violations = [] violations = []
for filename in ('shierfeng-fastapi.sql', 'shierfeng-fastapi-pg.sql'): for filename in ('shierfeng-fastapi.sql',):
sql = (BACKEND_ROOT / 'sql' / filename).read_text(encoding='utf-8').lower() sql = (BACKEND_ROOT / 'sql' / filename).read_text(encoding='utf-8').lower()
violations.extend(f'{filename}: {term}' for term in forbidden_terms if term.lower() in sql) violations.extend(f'{filename}: {term}' for term in forbidden_terms if term.lower() in sql)
self.assertEqual([], violations) self.assertEqual([], violations)
@@ -649,12 +649,11 @@ class ApiPermissionContractTest(unittest.TestCase):
): ):
_extract_guarded_vue_permissions(source) _extract_guarded_vue_permissions(source)
def test_independent_expected_permissions_reject_four_layers_missing_same_permission(self) -> None: def test_independent_expected_permissions_reject_layers_missing_same_permission(self) -> None:
missing = 'master:strain:query' missing = 'master:strain:query'
mutated = EXPECTED_PERMISSIONS - {missing} mutated = EXPECTED_PERMISSIONS - {missing}
layers = { layers = {
'mysql': mutated, 'mysql': mutated,
'postgresql': mutated,
'controller': mutated, 'controller': mutated,
'vue': mutated, 'vue': mutated,
} }
@@ -5,7 +5,7 @@ from types import SimpleNamespace
from typing import Any from typing import Any
from unittest.mock import AsyncMock, MagicMock, patch 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.ext.asyncio import AsyncSession
from sqlalchemy.sql import operators from sqlalchemy.sql import operators
@@ -39,7 +39,7 @@ from utils.page_util import PageUtil
def compile_sql(statement: Any, dialect: Any | None = None) -> str: def compile_sql(statement: Any, dialect: Any | None = None) -> str:
compiled = statement.compile( compiled = statement.compile(
dialect=dialect or postgresql.dialect(), dialect=dialect or mysql.dialect(),
compile_kwargs={'literal_binds': True}, compile_kwargs={'literal_binds': True},
) )
return ' '.join(str(compiled).split()).replace('%%', '%') return ' '.join(str(compiled).split()).replace('%%', '%')
@@ -289,7 +289,7 @@ class TestInventoryDao(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertTrue(statement.get_final_froms()[0].compare(BizPalletInventory.__table__)) self.assertTrue(statement.get_final_froms()[0].compare(BizPalletInventory.__table__))
self.assertIs(True, statement.get_execution_options().get('populate_existing')) self.assertIs(True, statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn('biz_pallet_inventory.pallet_id = 7', sql) self.assertIn('biz_pallet_inventory.pallet_id = 7', sql)
self.assertIn('FOR UPDATE', sql) self.assertIn('FOR UPDATE', sql)
@@ -310,7 +310,7 @@ class TestInventoryDao(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertTrue(statement.get_final_froms()[0].compare(BizPalletInventory.__table__)) self.assertTrue(statement.get_final_froms()[0].compare(BizPalletInventory.__table__))
self.assertIs(True, statement.get_execution_options().get('populate_existing')) self.assertIs(True, statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn('biz_pallet_inventory.pallet_id IN (2, 5, 9)', sql) self.assertIn('biz_pallet_inventory.pallet_id IN (2, 5, 9)', sql)
self.assertIn('ORDER BY biz_pallet_inventory.pallet_id', sql) self.assertIn('ORDER BY biz_pallet_inventory.pallet_id', sql)
@@ -353,7 +353,7 @@ class TestInventoryDao(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertTrue(statement.get_final_froms()[0].compare(BizPallet.__table__)) self.assertTrue(statement.get_final_froms()[0].compare(BizPallet.__table__))
self.assertIs(True, statement.get_execution_options().get('populate_existing')) self.assertIs(True, statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn('biz_pallet.pallet_id IN (2, 5, 9)', sql) self.assertIn('biz_pallet.pallet_id IN (2, 5, 9)', sql)
self.assertIn('ORDER BY biz_pallet.pallet_id', sql) self.assertIn('ORDER BY biz_pallet.pallet_id', sql)
@@ -412,7 +412,7 @@ class TestInventoryDao(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertTrue(statement.selected_columns[0].compare(BizPalletEvent.event_seq.property.columns[0])) self.assertTrue(statement.selected_columns[0].compare(BizPalletEvent.event_seq.property.columns[0]))
self.assertTrue(statement.get_final_froms()[0].compare(BizPalletEvent.__table__)) self.assertTrue(statement.get_final_froms()[0].compare(BizPalletEvent.__table__))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertNotIn('max(', sql.lower()) self.assertNotIn('max(', sql.lower())
self.assertIn('biz_pallet_event.event_id = 40', sql) self.assertIn('biz_pallet_event.event_id = 40', sql)
@@ -483,7 +483,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertTrue(statement.get_final_froms()[0].compare(model.__table__)) self.assertTrue(statement.get_final_froms()[0].compare(model.__table__))
self.assertIs(True, statement.get_execution_options().get('populate_existing')) self.assertIs(True, statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn(f'{model.__tablename__}.{id_field} = {record_id}', sql) self.assertIn(f'{model.__tablename__}.{id_field} = {record_id}', sql)
self.assertIn('FOR UPDATE', sql) self.assertIn('FOR UPDATE', sql)
@@ -519,7 +519,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertTrue(item_statement.get_final_froms()[0].compare(BizShipmentItem.__table__)) self.assertTrue(item_statement.get_final_froms()[0].compare(BizShipmentItem.__table__))
self.assertIs(True, parent_statement.get_execution_options().get('populate_existing')) self.assertIs(True, parent_statement.get_execution_options().get('populate_existing'))
self.assertIs(True, item_statement.get_execution_options().get('populate_existing')) self.assertIs(True, item_statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
parent_sql = compile_sql(parent_statement, dialect) parent_sql = compile_sql(parent_statement, dialect)
item_sql = compile_sql(item_statement, dialect) item_sql = compile_sql(item_statement, dialect)
@@ -551,9 +551,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.db.execute.assert_awaited_once() self.db.execute.assert_awaited_once()
parent_statement = self.db.execute.await_args.args[0] parent_statement = self.db.execute.await_args.args[0]
mysql_sql = compile_sql(parent_statement, mysql.dialect()) mysql_sql = compile_sql(parent_statement, mysql.dialect())
postgresql_sql = compile_sql(parent_statement, postgresql.dialect())
self.assertIn('false = 1', mysql_sql) self.assertIn('false = 1', mysql_sql)
self.assertIn('false', postgresql_sql)
async def test_inbound_for_update_locks_parent_then_current_items(self) -> None: async def test_inbound_for_update_locks_parent_then_current_items(self) -> None:
inbound = SimpleNamespace(inbound_id=11) inbound = SimpleNamespace(inbound_id=11)
@@ -578,7 +576,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertTrue(item_statement.get_final_froms()[0].compare(BizInboundItem.__table__)) self.assertTrue(item_statement.get_final_froms()[0].compare(BizInboundItem.__table__))
self.assertIs(True, parent_statement.get_execution_options().get('populate_existing')) self.assertIs(True, parent_statement.get_execution_options().get('populate_existing'))
self.assertIs(True, item_statement.get_execution_options().get('populate_existing')) self.assertIs(True, item_statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
parent_sql = compile_sql(parent_statement, dialect) parent_sql = compile_sql(parent_statement, dialect)
item_sql = compile_sql(item_statement, dialect) item_sql = compile_sql(item_statement, dialect)
@@ -610,7 +608,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertIsNone(actual) self.assertIsNone(actual)
self.db.execute.assert_awaited_once() self.db.execute.assert_awaited_once()
parent_statement = self.db.execute.await_args.args[0] parent_statement = self.db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
sql = compile_sql(parent_statement, dialect) sql = compile_sql(parent_statement, dialect)
self.assertIn('biz_inbound_order.warehouse_id IN (3, 7)', sql) self.assertIn('biz_inbound_order.warehouse_id IN (3, 7)', sql)
@@ -684,7 +682,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertIsNone(actual) self.assertIsNone(actual)
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn("biz_inbound_order.confirm_idempotency_key = 'confirm-key'", sql) self.assertIn("biz_inbound_order.confirm_idempotency_key = 'confirm-key'", sql)
@@ -850,7 +848,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertIs(marker, actual) self.assertIs(marker, actual)
statement = paginate.await_args.args[1] statement = paginate.await_args.args[1]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn('biz_inbound_order.warehouse_id IN (2, 5)', sql) self.assertIn('biz_inbound_order.warehouse_id IN (2, 5)', sql)
@@ -871,9 +869,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertIs(marker, actual) self.assertIs(marker, actual)
statement = paginate.await_args.args[1] statement = paginate.await_args.args[1]
mysql_sql = compile_sql(statement, mysql.dialect()) mysql_sql = compile_sql(statement, mysql.dialect())
postgresql_sql = compile_sql(statement, postgresql.dialect())
self.assertIn('WHERE false = 1', mysql_sql) self.assertIn('WHERE false = 1', mysql_sql)
self.assertIn('WHERE false', postgresql_sql)
self.assertEqual((query.page_num, query.page_size, True), paginate.await_args.args[2:]) self.assertEqual((query.page_num, query.page_size, True), paginate.await_args.args[2:])
async def test_inbound_list_none_scope_has_no_authorization_predicate(self) -> None: async def test_inbound_list_none_scope_has_no_authorization_predicate(self) -> None:
@@ -906,7 +902,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.assertIs(marker, actual) self.assertIs(marker, actual)
statement = paginate.await_args.args[1] statement = paginate.await_args.args[1]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn('biz_shipment_order.source_warehouse_id IN (3, 7)', sql) self.assertIn('biz_shipment_order.source_warehouse_id IN (3, 7)', sql)
@@ -922,7 +918,6 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
) )
empty_statement = empty_paginate.await_args.args[1] empty_statement = empty_paginate.await_args.args[1]
self.assertIn('false = 1', compile_sql(empty_statement, mysql.dialect())) self.assertIn('false = 1', compile_sql(empty_statement, mysql.dialect()))
self.assertIn('false', compile_sql(empty_statement, postgresql.dialect()))
async def test_shipment_detail_and_confirm_key_push_both_scopes_into_parent_sql(self) -> None: async def test_shipment_detail_and_confirm_key_push_both_scopes_into_parent_sql(self) -> None:
parent_result = MagicMock() parent_result = MagicMock()
@@ -953,7 +948,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
) )
) )
key_statement = self.db.execute.await_args.args[0] key_statement = self.db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
detail_sql = compile_sql(detail_statement, dialect) detail_sql = compile_sql(detail_statement, dialect)
key_sql = compile_sql(key_statement, dialect) key_sql = compile_sql(key_statement, dialect)
@@ -994,7 +989,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
) )
key_statement = self.db.execute.await_args.args[0] key_statement = self.db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=dialect.name): with self.subTest(dialect=dialect.name):
for statement in (list_statement, detail_statement, key_statement): for statement in (list_statement, detail_statement, key_statement):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
@@ -1016,7 +1011,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
) )
empty_key = self.db.execute.await_args.args[0] empty_key = self.db.execute.await_args.args[0]
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
with self.subTest(dialect=f'{dialect.name}-empty'): with self.subTest(dialect=f'{dialect.name}-empty'):
for statement in (empty_list, empty_detail, empty_key): for statement in (empty_list, empty_detail, empty_key):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
@@ -1055,7 +1050,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertFalse(statement.get_execution_options().get('populate_existing', False)) self.assertFalse(statement.get_execution_options().get('populate_existing', False))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertNotIn('FOR UPDATE', sql) self.assertNotIn('FOR UPDATE', sql)
if expected_scope is not None: if expected_scope is not None:
@@ -1154,9 +1149,7 @@ class TestOperationDaoReads(unittest.IsolatedAsyncioTestCase):
self.db.execute.assert_awaited_once() self.db.execute.assert_awaited_once()
parent_statement = self.db.execute.await_args.args[0] parent_statement = self.db.execute.await_args.args[0]
mysql_sql = compile_sql(parent_statement, mysql.dialect()) mysql_sql = compile_sql(parent_statement, mysql.dialect())
postgresql_sql = compile_sql(parent_statement, postgresql.dialect())
self.assertIn('false = 1', mysql_sql) self.assertIn('false = 1', mysql_sql)
self.assertIn('false', postgresql_sql)
async def test_simple_details_target_primary_keys(self) -> None: async def test_simple_details_target_primary_keys(self) -> None:
cases = ( cases = (
@@ -1315,7 +1308,7 @@ class TestOperationDaoWrites(unittest.IsolatedAsyncioTestCase):
order_statement = self.db.execute.await_args_list[1].args[0] order_statement = self.db.execute.await_args_list[1].args[0]
self.assertTrue(item_statement.table.compare(item_model.__table__)) self.assertTrue(item_statement.table.compare(item_model.__table__))
self.assertTrue(order_statement.table.compare(order_model.__table__)) self.assertTrue(order_statement.table.compare(order_model.__table__))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
self.assertIn( self.assertIn(
f'{item_model.__tablename__}.{id_field} = {record_id}', f'{item_model.__tablename__}.{id_field} = {record_id}',
compile_sql(item_statement, dialect), compile_sql(item_statement, dialect),
@@ -1,7 +1,7 @@
import unittest import unittest
from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, Text, UniqueConstraint from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, Text, UniqueConstraint
from sqlalchemy.dialects import mysql, postgresql from sqlalchemy.dialects import mysql
from sqlalchemy.schema import CreateColumn, CreateTable from sqlalchemy.schema import CreateColumn, CreateTable
from config.database import Base from config.database import Base
@@ -1061,12 +1061,12 @@ def _normalized_check_sql(table: Table) -> dict[str, str]:
class BusinessModelContractTest(unittest.TestCase): class BusinessModelContractTest(unittest.TestCase):
def test_batch_related_tables_compile_for_mysql_and_postgresql(self) -> None: def test_batch_related_tables_compile_for_mysql(self) -> None:
self.assertIs(Base.metadata.tables['sys_user'], user_do.SysUser.__table__) self.assertIs(Base.metadata.tables['sys_user'], user_do.SysUser.__table__)
batch_tables = EXPECTED_TEST_BATCH_TABLES | TEST_BATCH_OWNED_TABLES batch_tables = EXPECTED_TEST_BATCH_TABLES | TEST_BATCH_OWNED_TABLES
self.assertEqual(18, len(batch_tables)) self.assertEqual(18, len(batch_tables))
for table_name in batch_tables: for table_name in batch_tables:
for dialect_name, dialect in (('mysql', mysql.dialect()), ('postgresql', postgresql.dialect())): for dialect_name, dialect in (('mysql', mysql.dialect()),):
with self.subTest(table_name=table_name, dialect=dialect_name): with self.subTest(table_name=table_name, dialect=dialect_name):
compiled = str(CreateTable(Base.metadata.tables[table_name]).compile(dialect=dialect)) compiled = str(CreateTable(Base.metadata.tables[table_name]).compile(dialect=dialect))
self.assertIn(table_name, compiled) self.assertIn(table_name, compiled)
@@ -1187,7 +1187,7 @@ class BusinessModelContractTest(unittest.TestCase):
self.assertEqual(EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS, actual_audit_columns) self.assertEqual(EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS, actual_audit_columns)
violations = [] violations = []
dialects = {'mysql': mysql.dialect(), 'postgresql': postgresql.dialect()} dialects = {'mysql': mysql.dialect()}
for table_name, column_name in sorted(EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS): for table_name, column_name in sorted(EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS):
column = Base.metadata.tables[table_name].c[column_name] column = Base.metadata.tables[table_name].c[column_name]
for dialect_name, dialect in dialects.items(): for dialect_name, dialect in dialects.items():
@@ -0,0 +1,77 @@
import unittest
from unittest.mock import AsyncMock, MagicMock, patch
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from common.vo import PageModel
from module_business.dao.master_dao import MasterDao
from module_business.dao.operation_dao import OperationDao
from module_business.dao.report_dao import ReportDao
from module_business.entity.do.master_do import BizStrain
from module_business.entity.do.operation_do import BizInboundOrder
from module_business.entity.vo.master_vo import StrainPageQueryModel
from module_business.entity.vo.operation_vo import InboundPageQueryModel
from module_business.entity.vo.report_vo import FillingReportQueryModel
from utils.page_util import PageUtil
class TestPageUtil(unittest.IsolatedAsyncioTestCase):
async def test_paginate_excludes_internal_test_batch_field_from_serialized_rows(self) -> None:
record = BizStrain(
strain_id=1,
strain_code='S-1',
strain_name='菌种',
status='0',
test_batch_id=None,
)
count_result = MagicMock()
count_result.scalar.return_value = 1
query_result = MagicMock()
query_result.__iter__.return_value = iter([(record,)])
db = MagicMock(spec=AsyncSession)
db.execute = AsyncMock(side_effect=[count_result, query_result])
page = await PageUtil.paginate(
db,
select(BizStrain),
page_num=1,
page_size=10,
is_page=True,
exclude_fields={'test_batch_id'},
)
self.assertEqual('S-1', page.rows[0]['strainCode'])
self.assertNotIn('testBatchId', page.rows[0])
async def test_business_paginators_hide_internal_test_batch_field(self) -> None:
db = MagicMock(spec=AsyncSession)
page = PageModel(rows=[], pageNum=1, pageSize=10, total=0, hasNext=False)
cases = (
(
MasterDao._paginate,
(db, select(BizStrain), StrainPageQueryModel(), True),
),
(
OperationDao._paginate,
(db, select(BizInboundOrder), InboundPageQueryModel(), True),
),
(
ReportDao._paginate,
(db, select(BizInboundOrder), FillingReportQueryModel()),
),
)
for paginator, args in cases:
with (
self.subTest(paginator=paginator.__qualname__),
patch.object(
PageUtil,
'paginate',
new=AsyncMock(return_value=page),
) as paginate,
):
result = await paginator(*args)
self.assertIs(page, result)
self.assertEqual({'test_batch_id'}, paginate.await_args.kwargs['exclude_fields'])
@@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
from fastapi.routing import APIRoute from fastapi.routing import APIRoute
from pydantic import BaseModel, ValidationError from pydantic import BaseModel, ValidationError
from sqlalchemy import Select from sqlalchemy import Select
from sqlalchemy.dialects import mysql, postgresql from sqlalchemy.dialects import mysql
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from common.aspect.interface_auth import CheckUserInterfaceAuth from common.aspect.interface_auth import CheckUserInterfaceAuth
@@ -355,7 +355,7 @@ class TestReportDaoQueries(unittest.IsolatedAsyncioTestCase):
def _assert_compiles_for_supported_databases(self, statement: Select) -> tuple[str, str]: def _assert_compiles_for_supported_databases(self, statement: Select) -> tuple[str, str]:
compiled = tuple( compiled = tuple(
' '.join(str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).lower().split()) ' '.join(str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).lower().split())
for dialect in (mysql.dialect(), postgresql.dialect()) for dialect in (mysql.dialect(),)
) )
self.assertTrue(all(sql.startswith('select ') for sql in compiled)) self.assertTrue(all(sql.startswith('select ') for sql in compiled))
return compiled return compiled
@@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.routing import APIRoute from fastapi.routing import APIRoute
from sqlalchemy.dialects import mysql, postgresql from sqlalchemy.dialects import mysql
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -270,7 +270,7 @@ class ReturnDaoScopeRedTest(unittest.IsolatedAsyncioTestCase):
self.assertTrue(item_statement.get_final_froms()[0].compare(BizReturnItem.__table__)) self.assertTrue(item_statement.get_final_froms()[0].compare(BizReturnItem.__table__))
self.assertIs(True, parent_statement.get_execution_options().get('populate_existing')) self.assertIs(True, parent_statement.get_execution_options().get('populate_existing'))
self.assertIs(True, item_statement.get_execution_options().get('populate_existing')) self.assertIs(True, item_statement.get_execution_options().get('populate_existing'))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
parent_sql = compile_sql(parent_statement, dialect) parent_sql = compile_sql(parent_statement, dialect)
item_sql = compile_sql(item_statement, dialect) item_sql = compile_sql(item_statement, dialect)
self.assertIn('biz_return_order.return_id = 13', parent_sql) self.assertIn('biz_return_order.return_id = 13', parent_sql)
@@ -299,7 +299,7 @@ class ReturnDaoScopeRedTest(unittest.IsolatedAsyncioTestCase):
) )
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
sql = compile_sql(statement, postgresql.dialect()) sql = compile_sql(statement, mysql.dialect())
self.assertIn('biz_return_order.source_site_id IN (9)', sql) self.assertIn('biz_return_order.source_site_id IN (9)', sql)
self.assertIn('biz_return_order.target_warehouse_id IN (7)', sql) self.assertIn('biz_return_order.target_warehouse_id IN (7)', sql)
self.assertIn(' OR ', sql) self.assertIn(' OR ', sql)
@@ -332,7 +332,7 @@ class ReturnDaoScopeRedTest(unittest.IsolatedAsyncioTestCase):
statement = self.db.execute.await_args.args[0] statement = self.db.execute.await_args.args[0]
self.assertTrue(statement.get_final_froms()[0].compare(BizReturnOrder.__table__)) self.assertTrue(statement.get_final_froms()[0].compare(BizReturnOrder.__table__))
for dialect in (mysql.dialect(), postgresql.dialect()): for dialect in (mysql.dialect(),):
sql = compile_sql(statement, dialect) sql = compile_sql(statement, dialect)
self.assertIn(f"biz_return_order.{column} = '{key}'", sql) self.assertIn(f"biz_return_order.{column} = '{key}'", sql)
self.assertIn(f'biz_return_order.source_site_id = {source_site_id}', sql) self.assertIn(f'biz_return_order.source_site_id = {source_site_id}', sql)
@@ -10,7 +10,7 @@ from unittest.mock import AsyncMock, MagicMock, patch
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.routing import APIRoute from fastapi.routing import APIRoute
from sqlalchemy.dialects import postgresql from sqlalchemy.dialects import mysql
from sqlalchemy.exc import IntegrityError, MultipleResultsFound from sqlalchemy.exc import IntegrityError, MultipleResultsFound
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -322,7 +322,7 @@ class ShipmentDetailDaoTest(unittest.IsolatedAsyncioTestCase):
item_sql = ' '.join( item_sql = ' '.join(
str( str(
item_statement.compile( item_statement.compile(
dialect=postgresql.dialect(), dialect=mysql.dialect(),
compile_kwargs={'literal_binds': True}, compile_kwargs={'literal_binds': True},
) )
).split() ).split()
@@ -374,7 +374,7 @@ class ShipmentDetailDaoTest(unittest.IsolatedAsyncioTestCase):
item_sql = ' '.join( item_sql = ' '.join(
str( str(
item_statement.compile( item_statement.compile(
dialect=postgresql.dialect(), dialect=mysql.dialect(),
compile_kwargs={'literal_binds': True}, compile_kwargs={'literal_binds': True},
) )
).split() ).split()
@@ -5,12 +5,11 @@ from collections.abc import Callable
from pathlib import Path from pathlib import Path
SQL_ROOT = Path(__file__).resolve().parents[2] / 'sql' SQL_ROOT = Path(__file__).resolve().parents[2] / 'sql'
INITIALIZERS = ('shierfeng-fastapi.sql', 'shierfeng-fastapi-pg.sql') INITIALIZERS = ('shierfeng-fastapi.sql',)
PATCH_PATH = SQL_ROOT / 'patches/20260724_pallet_workflow_mysql.sql' PATCH_PATH = SQL_ROOT / 'patches/20260724_pallet_workflow_mysql.sql'
MENU_PROMOTION_PATCH_PATH = SQL_ROOT / 'patches/20260727_promote_business_menus_mysql.sql' MENU_PROMOTION_PATCH_PATH = SQL_ROOT / 'patches/20260727_promote_business_menus_mysql.sql'
BUSINESS_MENU_ICON_PATCH_PATH = SQL_ROOT / 'patches/20260728_add_business_menu_icons_mysql.sql' BUSINESS_MENU_ICON_PATCH_PATH = SQL_ROOT / 'patches/20260728_add_business_menu_icons_mysql.sql'
TEST_BATCH_MYSQL_PATCH_PATH = SQL_ROOT / 'patches/20260922_test_data_batch_mysql.sql' TEST_BATCH_MYSQL_PATCH_PATH = SQL_ROOT / 'patches/20260922_test_data_batch_mysql.sql'
TEST_BATCH_PG_PATCH_PATH = SQL_ROOT / 'patches/20260922_test_data_batch_pg.sql'
SYS_MENU_VALUE_COUNT = 20 SYS_MENU_VALUE_COUNT = 20
SYS_MENU_PERMS_INDEX = 13 SYS_MENU_PERMS_INDEX = 13
SYS_MENU_ICON_INDEX = 14 SYS_MENU_ICON_INDEX = 14
@@ -1007,18 +1006,6 @@ def _column_definitions(body: str) -> dict[str, str]:
return definitions return definitions
def _is_postgres_naive_timestamp_with_default_precision(definition: str) -> bool:
return (
re.fullmatch(
r'[`"]?[a-z_][a-z0-9_]*[`"]?\s+'
r'timestamp(?:\s+without\s+time\s+zone)?(?:\s+not\s+null)?',
definition.strip(),
flags=re.I,
)
is not None
)
def _assert_test_batch_sql_contract( def _assert_test_batch_sql_contract(
test_case: unittest.TestCase, test_case: unittest.TestCase,
sql: str, sql: str,
@@ -1064,18 +1051,9 @@ def _assert_test_batch_sql_contract(
test_case.assertNotRegex(definitions['test_batch_id'], r'\bnot\s+null\b') test_case.assertNotRegex(definitions['test_batch_id'], r'\bnot\s+null\b')
index_name = f'idx_{table_name}_test_batch_id' index_name = f'idx_{table_name}_test_batch_id'
if dialect == 'mysql': index_pattern = rf'\b(?:add\s+)?(?:index|key)\s+{index_name}\s*\(\s*test_batch_id\s*\)'
index_pattern = rf'\b(?:add\s+)?(?:index|key)\s+{index_name}\s*\(\s*test_batch_id\s*\)' test_case.assertRegex(normalized, index_pattern)
test_case.assertRegex(normalized, index_pattern) test_case.assertIn("comment '测试数据批次id;null表示正式数据'", normalized)
test_case.assertIn("comment '测试数据批次id;null表示正式数据'", normalized)
else:
index_pattern = rf'\bcreate\s+index\s+{index_name}\s+on\s+{table_name}\s*\(\s*test_batch_id\s*\)'
test_case.assertRegex(normalized, index_pattern)
test_case.assertRegex(
normalized,
rf'comment\s+on\s+column\s+{table_name}\.test_batch_id\s+is\s+'
r"'测试数据批次id;null表示正式数据'",
)
constraint_name = f'fk_{table_name}_test_batch_id' constraint_name = f'fk_{table_name}_test_batch_id'
test_case.assertRegex( test_case.assertRegex(
@@ -1345,9 +1323,7 @@ class SqlContractTest(unittest.TestCase):
def test_test_batch_initializers_and_patches_match_contract(self) -> None: def test_test_batch_initializers_and_patches_match_contract(self) -> None:
scripts = ( scripts = (
(SQL_ROOT / 'shierfeng-fastapi.sql', 'mysql', False), (SQL_ROOT / 'shierfeng-fastapi.sql', 'mysql', False),
(SQL_ROOT / 'shierfeng-fastapi-pg.sql', 'postgresql', False),
(TEST_BATCH_MYSQL_PATCH_PATH, 'mysql', True), (TEST_BATCH_MYSQL_PATCH_PATH, 'mysql', True),
(TEST_BATCH_PG_PATCH_PATH, 'postgresql', True),
) )
for path, dialect, is_patch in scripts: for path, dialect, is_patch in scripts:
with self.subTest(path=path.name): with self.subTest(path=path.name):
@@ -1361,7 +1337,7 @@ class SqlContractTest(unittest.TestCase):
def test_test_batch_patches_migrate_legacy_menu_permissions_without_role_grants(self) -> None: def test_test_batch_patches_migrate_legacy_menu_permissions_without_role_grants(self) -> None:
legacy_removed_ids = set(LEGACY_REMOVED_BUTTON_SPECS) legacy_removed_ids = set(LEGACY_REMOVED_BUTTON_SPECS)
for path in (TEST_BATCH_MYSQL_PATCH_PATH, TEST_BATCH_PG_PATCH_PATH): for path in (TEST_BATCH_MYSQL_PATCH_PATH,):
with self.subTest(path=path.name): with self.subTest(path=path.name):
raw = path.read_text(encoding='utf-8') raw = path.read_text(encoding='utf-8')
statements = _sql_statements(raw) statements = _sql_statements(raw)
@@ -1430,32 +1406,24 @@ class SqlContractTest(unittest.TestCase):
self.assertEqual(EXPECTED_FOREIGN_KEYS[table], foreign_keys) self.assertEqual(EXPECTED_FOREIGN_KEYS[table], foreign_keys)
self.assertEqual(EXPECTED_CHECKS[table], checks) self.assertEqual(EXPECTED_CHECKS[table], checks)
def test_postgres_business_datetimes_preserve_default_microsecond_precision(self) -> None: def test_mysql_business_datetimes_use_native_datetime_columns(self) -> None:
self.assertEqual(40, sum(len(columns) for columns in EXPECTED_DATETIME_COLUMNS.values())) self.assertEqual(40, sum(len(columns) for columns in EXPECTED_DATETIME_COLUMNS.values()))
tables = _create_table_bodies((SQL_ROOT / 'shierfeng-fastapi-pg.sql').read_text(encoding='utf-8')) tables = _create_table_bodies((SQL_ROOT / 'shierfeng-fastapi.sql').read_text(encoding='utf-8'))
invalid_columns = [] invalid_columns = []
for table, expected_columns in EXPECTED_DATETIME_COLUMNS.items(): for table, expected_columns in EXPECTED_DATETIME_COLUMNS.items():
definitions = _column_definitions(tables[table]) definitions = _column_definitions(tables[table])
actual_columns = { actual_columns = {
column column
for column, definition in definitions.items() for column, definition in definitions.items()
if re.search(r'\btimestamp\b', definition, flags=re.I) if re.search(r'\bdatetime\b', definition, flags=re.I)
} }
self.assertEqual(expected_columns, actual_columns, table) self.assertEqual(expected_columns, actual_columns, table)
for column in expected_columns: for column in expected_columns:
definition = definitions[column] definition = definitions[column]
if not _is_postgres_naive_timestamp_with_default_precision(definition): if not re.search(r'\bdatetime\b', definition, flags=re.I):
invalid_columns.append(f'{table}.{column}') invalid_columns.append(f'{table}.{column}')
self.assertEqual([], sorted(invalid_columns)) self.assertEqual([], sorted(invalid_columns))
def test_postgres_datetime_type_validator_rejects_precision_and_timezone_mutations(self) -> None:
self.assertTrue(_is_postgres_naive_timestamp_with_default_precision('occurred_at timestamp'))
self.assertTrue(
_is_postgres_naive_timestamp_with_default_precision('occurred_at timestamp without time zone not null')
)
self.assertFalse(_is_postgres_naive_timestamp_with_default_precision('occurred_at timestamp(3)'))
self.assertFalse(_is_postgres_naive_timestamp_with_default_precision('occurred_at timestamp with time zone'))
def test_initializers_define_fixed_business_menus_and_permissions(self) -> None: def test_initializers_define_fixed_business_menus_and_permissions(self) -> None:
self.assertEqual(18, len(EXPECTED_PAGE_PERMISSIONS)) self.assertEqual(18, len(EXPECTED_PAGE_PERMISSIONS))
self.assertEqual(43, len(EXPECTED_BUTTON_PERMISSIONS)) self.assertEqual(43, len(EXPECTED_BUTTON_PERMISSIONS))
@@ -1679,18 +1647,6 @@ class SqlContractTest(unittest.TestCase):
with self.assertRaises(AssertionError): with self.assertRaises(AssertionError):
_assert_business_menu_fields(self, mutated) _assert_business_menu_fields(self, mutated)
def test_mysql_and_postgresql_business_menu_fields_are_identical(self) -> None:
mysql_rows = _business_menu_rows((SQL_ROOT / INITIALIZERS[0]).read_text(encoding='utf-8'))
postgres_rows = _business_menu_rows((SQL_ROOT / INITIALIZERS[1]).read_text(encoding='utf-8'))
compared_indexes = tuple(range(15))
mysql_contract = {
menu_id: tuple(row[index] for index in compared_indexes) for menu_id, row in mysql_rows.items()
}
postgres_contract = {
menu_id: tuple(row[index] for index in compared_indexes) for menu_id, row in postgres_rows.items()
}
self.assertEqual(mysql_contract, postgres_contract)
def test_initializers_do_not_grant_new_business_menus_to_roles(self) -> None: def test_initializers_do_not_grant_new_business_menus_to_roles(self) -> None:
for filename in INITIALIZERS: for filename in INITIALIZERS:
with self.subTest(filename=filename): with self.subTest(filename=filename):
@@ -1717,14 +1673,10 @@ class SqlContractTest(unittest.TestCase):
any(int(row[0]) in REMOVED_AI_DICT_CODES or row[4] == 'ai_provider_type' for row in dict_data) any(int(row[0]) in REMOVED_AI_DICT_CODES or row[4] == 'ai_provider_type' for row in dict_data)
) )
def test_initializers_keep_menu_allocator_and_use_native_dialects(self) -> None: def test_initializer_uses_mysql_native_menu_allocator(self) -> None:
mysql = (SQL_ROOT / 'shierfeng-fastapi.sql').read_text(encoding='utf-8').lower() mysql = (SQL_ROOT / 'shierfeng-fastapi.sql').read_text(encoding='utf-8').lower()
postgres = (SQL_ROOT / 'shierfeng-fastapi-pg.sql').read_text(encoding='utf-8').lower()
self.assertRegex(mysql, r'auto_increment\s*=\s*2000') self.assertRegex(mysql, r'auto_increment\s*=\s*2000')
self.assertNotRegex(mysql, r'\bbigserial\b|\balter\s+sequence\b|\bcomment\s+on\b') self.assertNotRegex(mysql, r'\bbigserial\b|\balter\s+sequence\b|\bcomment\s+on\b')
self.assertRegex(postgres, r'alter\s+sequence\s+sys_menu_menu_id_seq\s+restart\s+2000')
self.assertNotIn('`', postgres)
self.assertNotRegex(postgres, r'\bauto_increment\b|\bengine\s*=')
def test_initializers_create_event_before_inventory_foreign_key(self) -> None: def test_initializers_create_event_before_inventory_foreign_key(self) -> None:
for filename in INITIALIZERS: for filename in INITIALIZERS:
@@ -3,7 +3,7 @@ from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, MagicMock, patch
from fastapi import params from fastapi import params
from sqlalchemy.dialects import postgresql from sqlalchemy.dialects import mysql
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.sql import select from sqlalchemy.sql import select
from starlette.requests import Request from starlette.requests import Request
@@ -32,7 +32,7 @@ def make_request(batch_id: str | None = None) -> Request:
def compile_sql(statement: object) -> str: def compile_sql(statement: object) -> str:
return ' '.join( return ' '.join(
str(statement.compile(dialect=postgresql.dialect(), compile_kwargs={'literal_binds': True})).split() str(statement.compile(dialect=mysql.dialect(), compile_kwargs={'literal_binds': True})).split()
) )
@@ -4,7 +4,7 @@ from pathlib import Path
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock, patch 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.ext.asyncio import AsyncSession
from common.vo import PageModel from common.vo import PageModel
@@ -75,7 +75,7 @@ def make_test_scope(batch_id: int) -> TestBatchScope:
def _compile(statement: object) -> str: def _compile(statement: object) -> str:
return ' '.join( return ' '.join(
' '.join(str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).lower().split()) ' '.join(str(statement.compile(dialect=dialect, compile_kwargs={'literal_binds': True})).lower().split())
for dialect in (mysql.dialect(), postgresql.dialect()) for dialect in (mysql.dialect(),)
) )
@@ -6,7 +6,7 @@ from types import SimpleNamespace
from typing import get_type_hints from typing import get_type_hints
from unittest.mock import AsyncMock, MagicMock, patch from unittest.mock import AsyncMock, MagicMock, patch
from sqlalchemy.dialects import postgresql from sqlalchemy.dialects import mysql
from sqlalchemy.exc import IntegrityError from sqlalchemy.exc import IntegrityError
from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.ext.asyncio import AsyncSession
@@ -77,7 +77,7 @@ def make_batch(
def compile_sql(statement: object) -> str: def compile_sql(statement: object) -> str:
return ' '.join( return ' '.join(
str(statement.compile(dialect=postgresql.dialect(), compile_kwargs={'literal_binds': True})).split() str(statement.compile(dialect=mysql.dialect(), compile_kwargs={'literal_binds': True})).split()
) )
@@ -7,6 +7,7 @@ from datetime import datetime
from types import SimpleNamespace from types import SimpleNamespace
from unittest.mock import patch from unittest.mock import patch
import bcrypt
import pytest import pytest
from fastapi import Request from fastapi import Request
from loguru import logger as _logger from loguru import logger as _logger
@@ -16,6 +17,8 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
from common.annotation.log_annotation import Log, RequestLogFieldRoot, ResponseLogFieldRoot from common.annotation.log_annotation import Log, RequestLogFieldRoot, ResponseLogFieldRoot
from common.enums import BusinessType from common.enums import BusinessType
from config.env import LogConfig from config.env import LogConfig
from exceptions.exception import LoginException
from module_admin.service import login_service
from utils.log_util import LoggerInitializer, LogSanitizer, _build_text_assignment_patterns, _build_text_key_pattern from utils.log_util import LoggerInitializer, LogSanitizer, _build_text_assignment_patterns, _build_text_key_pattern
@@ -47,6 +50,50 @@ def test_sanitize_nested_log_payload() -> None:
assert sanitized['jsonBody']['ipaddr'] == '192.168.1.10' assert sanitized['jsonBody']['ipaddr'] == '192.168.1.10'
def test_failed_login_does_not_log_password_hash() -> None:
password_hash = bcrypt.hashpw(b'expected-password', bcrypt.gensalt()).decode('utf-8')
class FakeRedis:
async def get(self, key: str) -> None:
return None
async def set(self, key: str, value: object, ex: object) -> None:
return None
async def delete(self, key: str) -> None:
return None
async def fake_login_by_account(query_db: object, user_name: str) -> list[SimpleNamespace]:
return [SimpleNamespace(password=password_hash, status='0')]
request = SimpleNamespace(
app=SimpleNamespace(state=SimpleNamespace(redis=FakeRedis())),
client=SimpleNamespace(host='127.0.0.1'),
headers={},
)
login_user = SimpleNamespace(user_name='admin', password='wrong-password', captcha_enabled=False)
log_messages: list[str] = []
sink_id = login_service.logger.add(
lambda message: log_messages.append(str(message)),
format='{message}',
level='WARNING',
)
try:
with (
patch.object(login_service, 'login_by_account', fake_login_by_account),
pytest.raises(LoginException) as exception_info,
):
asyncio.run(login_service.LoginService.authenticate_user(request, None, login_user))
finally:
login_service.logger.remove(sink_id)
output = ''.join(log_messages)
assert exception_info.value.message == '密码错误'
assert '密码错误' in output
assert password_hash not in output
def test_ip_masking_can_be_enabled_by_partial_mask_field_configuration() -> None: def test_ip_masking_can_be_enabled_by_partial_mask_field_configuration() -> None:
payload = { payload = {
'jsonBody': { 'jsonBody': {
@@ -11,7 +11,6 @@ from openpyxl.utils import get_column_letter
from openpyxl.worksheet.datavalidation import DataValidation from openpyxl.worksheet.datavalidation import DataValidation
from sqlalchemy.engine.row import Row from sqlalchemy.engine.row import Row
from sqlalchemy.orm.collections import InstrumentedList from sqlalchemy.orm.collections import InstrumentedList
from sqlalchemy.sql.expression import TextClause, null
from config.database import Base from config.database import Base
from config.env import CachePathConfig from config.env import CachePathConfig
@@ -153,17 +152,14 @@ class SqlalchemyUtil:
return result return result
@classmethod @classmethod
def get_server_default_null(cls, dialect_name: str, need_explicit_null: bool = True) -> TextClause | None: def get_server_default_null(cls, dialect_name: str, need_explicit_null: bool = True) -> None:
""" """
根据数据库方言动态返回值为null的server_default 根据数据库方言动态返回值为null的server_default
:param dialect_name: 数据库方言名称 :param dialect_name: 数据库方言名称
:param need_explicit_null: 是否需要显式DEFAULT NULL :param need_explicit_null: 是否需要显式DEFAULT NULL
:return: 不同数据库方言对应的null_server_default :return: MySQL 使用隐式 NULL,不设置显式默认值
""" """
if need_explicit_null and dialect_name == 'postgresql':
return null()
return None
class CamelCaseUtil: class CamelCaseUtil:
+31 -3
View File
@@ -13,6 +13,27 @@ class PageUtil:
分页工具类 分页工具类
""" """
@classmethod
def _remove_excluded_fields(cls, value: Any, excluded_fields: set[str]) -> Any:
if isinstance(value, dict):
return {
key: cls._remove_excluded_fields(item, excluded_fields)
for key, item in value.items()
if key not in excluded_fields
}
if isinstance(value, list):
return [cls._remove_excluded_fields(item, excluded_fields) for item in value]
return value
@classmethod
def _transform_rows(cls, rows: list[Any], exclude_fields: set[str] | None) -> Any:
transformed = CamelCaseUtil.transform_result(rows)
if not exclude_fields:
return transformed
excluded_fields = set(exclude_fields)
excluded_fields.update(CamelCaseUtil.snake_to_camel(field) for field in exclude_fields)
return cls._remove_excluded_fields(transformed, excluded_fields)
@classmethod @classmethod
def get_page_obj(cls, data_list: list, page_num: int, page_size: int) -> PageModel: def get_page_obj(cls, data_list: list, page_num: int, page_size: int) -> PageModel:
""" """
@@ -39,7 +60,14 @@ class PageUtil:
@classmethod @classmethod
async def paginate( async def paginate(
cls, db: AsyncSession, query: Select, page_num: int, page_size: int, is_page: bool = False cls,
db: AsyncSession,
query: Select,
page_num: int,
page_size: int,
is_page: bool = False,
*,
exclude_fields: set[str] | None = None,
) -> PageModel | list[dict[str, Any] | list[dict[Any, Any]]]: ) -> PageModel | list[dict[str, Any] | list[dict[Any, Any]]]:
""" """
输入查询语句和分页信息,返回分页数据列表结果 输入查询语句和分页信息,返回分页数据列表结果
@@ -62,7 +90,7 @@ class PageUtil:
paginated_data.append(row) paginated_data.append(row)
has_next = math.ceil(total / page_size) > page_num has_next = math.ceil(total / page_size) > page_num
result = PageModel[Any]( result = PageModel[Any](
rows=CamelCaseUtil.transform_result(paginated_data), rows=cls._transform_rows(paginated_data, exclude_fields),
pageNum=page_num, pageNum=page_num,
pageSize=page_size, pageSize=page_size,
total=total, total=total,
@@ -76,7 +104,7 @@ class PageUtil:
no_paginated_data.append(row[0]) no_paginated_data.append(row[0])
else: else:
no_paginated_data.append(row) no_paginated_data.append(row)
result = CamelCaseUtil.transform_result(no_paginated_data) result = cls._transform_rows(no_paginated_data, exclude_fields)
return result return result
@@ -1,24 +0,0 @@
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
# API代理配置(PostgreSQL版本)
location /docker-api/ {
proxy_pass http://shierfeng-backend-pg:9099/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
+3 -2
View File
@@ -6,7 +6,8 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="renderer" content="webkit"> <meta name="renderer" content="webkit">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="icon" href="/favicon.ico"> <link rel="icon" type="image/svg+xml" href="/sylvan-mark.svg">
<link rel="alternate icon" href="/favicon.ico">
<title>%VITE_APP_TITLE%</title> <title>%VITE_APP_TITLE%</title>
<!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]--> <!--[if lt IE 11]><script>window.location.href='/html/ie.html';</script><![endif]-->
<style> <style>
@@ -212,4 +213,4 @@
<script type="module" src="/src/main.js"></script> <script type="module" src="/src/main.js"></script>
</body> </body>
</html> </html>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 1.6 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 140 140">
<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

@@ -11,6 +11,25 @@ import * as testBatchContext from '../src/utils/testBatchContext.js'
const frontendRoot = fileURLToPath(new URL('..', import.meta.url)) const frontendRoot = fileURLToPath(new URL('..', import.meta.url))
const execFileAsync = promisify(execFile) const execFileAsync = promisify(execFile)
test('Web 端统一使用 Sylvan 横版标识、折叠图标和浏览器图标', async () => {
const [logoComponent, toolBuilder, indexHtml, fullLogo, markLogo] = await Promise.all([
readFile(path.join(frontendRoot, 'src/layout/components/Sidebar/Logo.vue'), 'utf8'),
readFile(path.join(frontendRoot, 'src/views/tool/build/index.vue'), 'utf8'),
readFile(path.join(frontendRoot, 'index.html'), 'utf8'),
readFile(path.join(frontendRoot, 'src/assets/logo/sylvan-logo.svg'), 'utf8'),
readFile(path.join(frontendRoot, 'src/assets/logo/sylvan-mark.svg'), 'utf8')
])
assert.match(logoComponent, /@\/assets\/logo\/sylvan-logo\.svg/)
assert.match(logoComponent, /@\/assets\/logo\/sylvan-mark\.svg/)
assert.match(toolBuilder, /@\/assets\/logo\/sylvan-mark\.svg/)
assert.match(indexHtml, /href="\/sylvan-mark\.svg"/)
assert.match(fullLogo, /viewBox="0 0 516\.1 194\.52"/)
assert.match(markLogo, /viewBox="0 0 140 140"/)
assert.doesNotMatch(`${logoComponent}\n${toolBuilder}`, /assets\/logo\/logo\.png/)
assert.doesNotMatch(`${fullLogo}\n${markLogo}`, /<script\b|<foreignObject\b|javascript:|\b(?:xlink:)?href=|\bonload=|\bonerror=/i)
})
const expectedRequests = { const expectedRequests = {
'src/api/master/strain.js': [ 'src/api/master/strain.js': [
{ url: "'/master/strain/list'", method: 'get' }, { url: "'/master/strain/list'", method: 'get' },
@@ -885,6 +904,23 @@ function extractButtonBlocks(source, clickHandler) {
.filter((button) => button.includes(`@click="${clickHandler}`)) .filter((button) => button.includes(`@click="${clickHandler}`))
} }
function assertButtonInSingleToolbar(source, relativePath, toolbarClass, clickHandler) {
const buttonIndex = source.indexOf(`@click="${clickHandler}`)
assert.ok(buttonIndex >= 0, `${relativePath} 缺少 ${clickHandler} 按钮`)
const beforeButton = source.slice(0, buttonIndex)
const rowStart = beforeButton.lastIndexOf('<el-row')
const rowEnd = beforeButton.lastIndexOf('</el-row>')
assert.ok(rowStart > rowEnd, `${relativePath} 的 ${clickHandler} 按钮必须位于 el-row 工具栏内`)
const rowTagEnd = source.indexOf('>', rowStart)
const rowTag = source.slice(rowStart, rowTagEnd + 1)
assert.match(rowTag, new RegExp(`class="[^"]*\\b${toolbarClass}\\b`), `${relativePath} 必须使用 ${toolbarClass}`)
const toolbarRows = [...source.matchAll(new RegExp(`<el-row\\b[^>]*class="[^"]*\\b${toolbarClass}\\b[^"]*"`, 'g'))]
assert.equal(toolbarRows.length, 1, `${relativePath} 的操作按钮必须合并到同一个 ${toolbarClass}`)
}
function assertButtonsUsePermission(source, clickHandler, permission) { function assertButtonsUsePermission(source, clickHandler, permission) {
const buttons = extractButtonBlocks(source, clickHandler) const buttons = extractButtonBlocks(source, clickHandler)
assert.ok(buttons.length > 0, `缺少 ${clickHandler} 按钮`) assert.ok(buttons.length > 0, `缺少 ${clickHandler} 按钮`)
@@ -1176,7 +1212,7 @@ test('真实权限门禁解析拒绝注释常量、hasPermiOr 和动态数组假
const missing = expectedPermissions.filter((permission) => permission !== 'master:strain:query') const missing = expectedPermissions.filter((permission) => permission !== 'master:strain:query')
assert.throws( assert.throws(
() => assertExactPermissionLayers({ mysql: missing, postgresql: missing, controller: missing, vue: missing }), () => assertExactPermissionLayers({ mysql: missing, controller: missing, vue: missing }),
/权限集合不精确/ /权限集合不精确/
) )
}) })
@@ -1487,6 +1523,38 @@ test('六个报表 API 只提供 GET /list,不提供导出接口', async () =>
} }
}) })
test('托盘追溯报表将来源和流转状态显示为中文', async () => {
const source = await readFile(path.join(frontendRoot, 'src/views/report/palletTrace/index.vue'), 'utf8')
const sourceLabels = [
['INBOUND', '入库单'],
['FILLING', '装填记录'],
['SHIPMENT', '发货单'],
['USAGE', '使用记录'],
['RETURN', '退回单']
]
const flowStateLabels = [
['UNSTOCKED', '未入库'],
['EMPTY_IN_WAREHOUSE', '仓库空托盘'],
['FILLED_IN_WAREHOUSE', '仓库有料'],
['AT_SITE_UNUSED', '现场未使用'],
['AT_SITE_PARTIAL', '现场部分使用'],
['AT_SITE_EMPTY', '现场空托盘'],
['RETURNING', '退回中']
]
for (const [value, label] of sourceLabels) {
assert.match(source, new RegExp(`value: '${value}', label: '${label}'`))
}
for (const [value, label] of flowStateLabels) {
assert.match(source, new RegExp(`value: '${value}', label: '${label}'`))
}
assert.match(source, /sourceLabel\(scope\.row\.sourceType,\s*scope\.row\.sourceId\)/)
assert.match(source, /flowStateLabel\(scope\.row\.beforeState\)/)
assert.match(source, /flowStateLabel\(scope\.row\.afterState\)/)
assert.match(source, /function sourceLabel\([\s\S]*?sourceTypeOptions\.find\(/)
assert.match(source, /function flowStateLabel\([\s\S]*?flowStateOptions\.find\(/)
})
test('六个只读报表页面逐页满足 API、权限、筛选、列和异步分页契约', async (t) => { test('六个只读报表页面逐页满足 API、权限、筛选、列和异步分页契约', async (t) => {
for (const [resource, contract] of Object.entries(reportPageContracts)) { for (const [resource, contract] of Object.entries(reportPageContracts)) {
await t.test(contract.relativePath, async () => { await t.test(contract.relativePath, async () => {
@@ -1506,6 +1574,53 @@ test('六个只读报表页面逐页满足 API、权限、筛选、列和异步
assert.doesNotMatch(source, /report:[a-z]+:(?:add|edit|remove|export|print)/) assert.doesNotMatch(source, /report:[a-z]+:(?:add|edit|remove|export|print)/)
assert.doesNotMatch(source, /\bhandle(?:Add|Edit|Delete|Remove|Export|Print|Download)\b|proxy\.download\s*\(/) assert.doesNotMatch(source, /\bhandle(?:Add|Edit|Delete|Remove|Export|Print|Download)\b|proxy\.download\s*\(/)
const queryFormTag = source.match(/<el-form\b[^>]*ref="queryRef"[^>]*>/)?.[0] || ''
assert.match(queryFormTag, /v-show="showSearch"/, `${resource} 搜索区必须支持显隐`)
assert.match(queryFormTag, /label-width="88px"/, `${resource} 筛选标签宽度必须统一`)
assert.match(source, /const showSearch = ref\(true\);?/, `${resource} 搜索区必须默认展开`)
const reportFilterFooter = source.match(/<div\s+class="report-filter__footer">[\s\S]*?<\/div>/)?.[0] || ''
assert.ok(reportFilterFooter, `${resource} 日期和搜索操作必须位于统一底部操作栏`)
assert.match(reportFilterFooter, /<el-form-item\b[^>]*class="report-filter__date"/, `${resource} 底部操作栏必须包含日期范围`)
assert.match(reportFilterFooter, /<el-form-item\b[^>]*class="report-filter__actions"/, `${resource} 底部操作栏必须包含搜索操作`)
assert.ok(
reportFilterFooter.indexOf('report-filter__date') < reportFilterFooter.indexOf('report-filter__actions'),
`${resource} 日期范围必须位于搜索操作之前`
)
const reportToolbar = source.match(/<el-row\b[^>]*class="[^"]*\breport-toolbar\b[^"]*"[^>]*>[\s\S]*?<\/el-row>/)?.[0] || ''
assert.ok(reportToolbar, `${resource} 缺少报表操作栏`)
assert.match(reportToolbar, /<right-toolbar\s+v-model:showSearch="showSearch"\s+@queryTable="getList"\s*\/>/, `${resource} 必须提供搜索显隐和刷新入口`)
assert.match(source, /\.report-filter\s*\{[^}]*display:\s*grid;[^}]*grid-template-columns:\s*repeat\(auto-fit,\s*minmax\(260px,\s*1fr\)\)/, `${resource} 筛选区必须使用响应式等宽网格`)
assert.match(
source,
/\.report-filter__footer\s*\{[^}]*grid-column:\s*1\s*\/\s*-1;[^}]*display:\s*flex;[^}]*align-items:\s*flex-end;[^}]*gap:\s*16px;/,
`${resource} 日期和操作项必须位于独占整行的底部操作栏`
)
assert.doesNotMatch(source, /\.report-filter__footer\s*\{[^}]*display:\s*contents;/, `${resource} 底部操作栏不得使用 contents 分散到筛选网格`)
assert.doesNotMatch(source, /\.report-filter__date\s*\{[^}]*grid-column:\s*-3\s*\/\s*-1;/, `${resource} 日期范围不得单独跨最后两列`)
assert.match(
source,
/\.report-filter\s+\.report-filter__date\s*\{[^}]*flex:\s*0\s+1\s+420px;[^}]*width:\s*420px;[^}]*min-width:\s*0;[^}]*max-width:\s*100%;/,
`${resource} 桌面日期范围必须固定基础宽度并覆盖通用表单项宽度`
)
assert.match(source, /\.report-filter\s+\.report-filter__actions\s*\{[^}]*flex:\s*0\s+0\s+auto;[^}]*width:\s*auto;/, `${resource} 操作按钮必须按自身宽度紧邻日期范围`)
assert.match(source, /\.report-filter :deep\(\.el-form-item__content\)\s*\{[^}]*min-width:\s*0;/, `${resource} 筛选内容必须允许收缩`)
assert.match(
source,
/\.report-filter :deep\(\.el-input\),\s*\.report-filter :deep\(\.el-input-number\),\s*\.report-filter :deep\(\.el-select\),\s*\.report-filter :deep\(\.el-date-editor\)\s*\{[^}]*width:\s*100%\s*!important;[^}]*min-width:\s*0;/,
`${resource} 筛选控件必须等宽且不得越界`
)
assert.match(
source,
/@media\s*\(max-width:\s*900px\)[\s\S]*?\.report-filter__footer\s*\{[^}]*grid-column:\s*1;[^}]*flex-direction:\s*column;[^}]*align-items:\s*stretch;/,
`${resource} 窄屏底部操作栏必须恢复纵向布局`
)
assert.match(
source,
/@media\s*\(max-width:\s*900px\)[\s\S]*?\.report-filter\s+\.report-filter__date\s*\{[^}]*flex:\s*0\s+0\s+auto;[^}]*width:\s*100%;[^}]*min-width:\s*0;[^}]*max-width:\s*none;/,
`${resource} 窄屏日期范围必须恢复全宽`
)
for (const queryKey of contract.queryKeys) { for (const queryKey of contract.queryKeys) {
assert.match(source, new RegExp(`\\b${queryKey}\\b`), `${resource} 缺少筛选键 ${queryKey}`) assert.match(source, new RegExp(`\\b${queryKey}\\b`), `${resource} 缺少筛选键 ${queryKey}`)
} }
@@ -1646,6 +1761,20 @@ test('六个基础资料页面逐页满足 API、权限、分页和安全删除
assert.match(source, /const detail\s*=\s*response\.data/) assert.match(source, /const detail\s*=\s*response\.data/)
assert.match(source, /function handleQuery\(\)\s*{[\s\S]*?queryParams\.value\.pageNum\s*=\s*1[\s\S]*?getList\(\)/) assert.match(source, /function handleQuery\(\)\s*{[\s\S]*?queryParams\.value\.pageNum\s*=\s*1[\s\S]*?getList\(\)/)
assert.match(source, /function resetQuery\(\)\s*{[\s\S]*?resetForm\(['"]queryRef['"]\)[\s\S]*?handleQuery\(\)/) assert.match(source, /function resetQuery\(\)\s*{[\s\S]*?resetForm\(['"]queryRef['"]\)[\s\S]*?handleQuery\(\)/)
const queryFormTag = source.match(/<el-form\b[^>]*ref="queryRef"[^>]*>/)?.[0] || ''
assert.match(queryFormTag, /v-show="showSearch"/, `${resource} 搜索区必须支持显隐`)
assert.match(source, /const showSearch = ref\(true\);/, `${resource} 搜索区必须默认展开`)
const masterToolbar = source.match(/<el-row\b[^>]*class="[^"]*\bmaster-toolbar\b[^"]*"[^>]*>[\s\S]*?<\/el-row>/)?.[0] || ''
assert.ok(masterToolbar, `${resource} 缺少基础资料操作栏`)
assert.doesNotMatch(masterToolbar.match(/^<el-row\b[^>]*>/)?.[0] || '', /v-if="isMasterWriteAllowed"/, `${resource} 搜索与刷新入口不得受写权限限制`)
assert.match(masterToolbar, /<template v-if="isMasterWriteAllowed">/, `${resource} 写操作仍需受测试模式限制`)
assert.match(masterToolbar, /<right-toolbar\s+v-model:showSearch="showSearch"\s+@queryTable="getList"\s*\/>/, `${resource} 必须复用右侧搜索与刷新工具栏`)
assert.match(
source,
/\.master-query :deep\(\.el-input\),\s*\.master-query :deep\(\.el-input-number\),\s*\.master-query :deep\(\.el-select\)\s*\{[^}]*min-width:\s*0;/,
`${resource} 查询控件必须允许收缩到网格内容宽度`
)
assert.match(source, /<pagination\b[\s\S]*?v-model:page="queryParams\.pageNum"[\s\S]*?v-model:limit="queryParams\.pageSize"[\s\S]*?@pagination="getList"/) assert.match(source, /<pagination\b[\s\S]*?v-model:page="queryParams\.pageNum"[\s\S]*?v-model:limit="queryParams\.pageSize"[\s\S]*?@pagination="getList"/)
assert.match(source, /<el-table\b[^>]*v-loading="loading"[^>]*empty-text="暂无数据"/) assert.match(source, /<el-table\b[^>]*v-loading="loading"[^>]*empty-text="暂无数据"/)
assert.match(source, /<el-alert\b[^>]*v-if="loadError"/) assert.match(source, /<el-alert\b[^>]*v-if="loadError"/)
@@ -2495,6 +2624,12 @@ test('测试批次管理与旧数据纳入遵守 root、权限和预览提交契
assert.match(source, /v-hasPermi="\['system:testbatch:adopt'\]"/, `${rootType} 纳入入口必须校验批次纳入权限`) assert.match(source, /v-hasPermi="\['system:testbatch:adopt'\]"/, `${rootType} 纳入入口必须校验批次纳入权限`)
assert.match(source, new RegExp(`<test-batch-adoption-dialog\\b[\\s\\S]*?:root-type="['\"]${rootType}['\"][\\s\\S]*?:resource-ids="selectedIds"`)) assert.match(source, new RegExp(`<test-batch-adoption-dialog\\b[\\s\\S]*?:root-type="['\"]${rootType}['\"][\\s\\S]*?:resource-ids="selectedIds"`))
assert.match(source, new RegExp(`selectedIds\\.value\\s*=\\s*selection\\.map\\(\\(item\\)\\s*=>\\s*item\\.${contract.id}\\)`), `${rootType} 必须传递正整数根 ID`) assert.match(source, new RegExp(`selectedIds\\.value\\s*=\\s*selection\\.map\\(\\(item\\)\\s*=>\\s*item\\.${contract.id}\\)`), `${rootType} 必须传递正整数根 ID`)
assertButtonInSingleToolbar(
source,
contract.path,
contract.path.includes('/master/') ? 'master-toolbar' : 'page-toolbar',
'openAdoptionDialog'
)
} }
for (const rootType of ['strain', 'customer', 'site', 'line', 'warehouse', 'pallet']) { for (const rootType of ['strain', 'customer', 'site', 'line', 'warehouse', 'pallet']) {
@@ -2720,3 +2855,21 @@ test('测试批次管理页真实 hydration 拒绝旧版本回写并保留当前
assert.equal(failedPage.state.batchList.value[0].participantCount, undefined) assert.equal(failedPage.state.batchList.value[0].participantCount, undefined)
assert.equal(failedPage.state.loadError.value, '', '当前详情失败必须是单项状态,不得升级为列表失败') assert.equal(failedPage.state.loadError.value, '', '当前详情失败必须是单项状态,不得升级为列表失败')
}) })
test('三个业务菜单公共样式统一使用 Element Plus 主题变量', async () => {
const styles = await source('src/assets/styles/data-pages.scss')
assert.match(styles, /background:\s*var\(--el-bg-color-page,\s*#f5f7fb\)/)
assert.match(styles, /background:\s*var\(--el-bg-color,\s*#fff\)/)
assert.match(styles, /border:\s*1px solid var\(--el-border-color-lighter,\s*#e4e7ed\)/)
assert.match(styles, /background:\s*var\(--el-fill-color-light,\s*#f5f7fa\)/)
assert.match(styles, /color:\s*var\(--el-text-color-regular,\s*#606266\)/)
assert.match(styles, /background:\s*var\(--el-fill-color-lighter,\s*#fafafa\)/)
assert.match(styles, /box-shadow:\s*var\(--el-box-shadow-lighter,/)
assert.doesNotMatch(styles, /background:\s*#f5f7fb\s*;/)
assert.doesNotMatch(styles, /background:\s*#fff\s*;/)
assert.doesNotMatch(styles, /border:\s*1px solid #e7ebf2\s*;/)
assert.doesNotMatch(styles, /background:\s*#f7f9fc\s*!important/)
assert.doesNotMatch(styles, /background:\s*#fbfcfe\s*;/)
})
@@ -0,0 +1,47 @@
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { buildTrendData, getTrendRangeQuery, TREND_RANGE_OPTIONS } from '../src/utils/dashboardTrend.js'
const referenceDate = new Date(2026, 8, 26, 12)
test('趋势下拉提供 7 天、14 天和 1 个月三个选项', () => {
assert.deepEqual(TREND_RANGE_OPTIONS, [
{ value: 7, label: '近 7 天' },
{ value: 14, label: '近 14 天' },
{ value: 30, label: '近 1 个月' }
])
})
test('趋势范围为近 14 天时,查询从 13 天前开始并包含今天', () => {
assert.deepEqual(getTrendRangeQuery(14, referenceDate), {
beginTime: '2026-09-13',
endTime: '2026-09-26'
})
})
test('趋势范围为近 1 个月时最多查询 30 天', () => {
assert.deepEqual(getTrendRangeQuery(30, referenceDate), {
beginTime: '2026-08-28',
endTime: '2026-09-26'
})
})
test('趋势数据按选择的天数生成日期轴并聚合入库单与出库包数', () => {
const result = buildTrendData(
[
{ createTime: '2026-09-20T08:00:00+08:00' },
{ createTime: '2026-09-24T09:00:00+08:00' },
{ createTime: '2026-09-24T10:00:00+08:00' }
],
[
{ confirmedAt: '2026-09-20T11:00:00+08:00', packageQty: 4 },
{ confirmedAt: '2026-09-24T13:00:00+08:00', packageQty: 7 }
],
7,
referenceDate
)
assert.deepEqual(result.labels, ['9/20', '9/21', '9/22', '9/23', '9/24', '9/25', '9/26'])
assert.deepEqual(result.inbound, [1, 0, 0, 0, 2, 0, 0])
assert.deepEqual(result.outbound, [4, 0, 0, 0, 7, 0, 0])
})
Binary file not shown.

Before

Width:  |  Height:  |  Size: 509 KiB

After

Width:  |  Height:  |  Size: 68 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

@@ -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 140 140">
<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

@@ -4,7 +4,8 @@
.app-container.report-page { .app-container.report-page {
min-height: 100%; min-height: 100%;
padding: 18px 20px 24px; padding: 18px 20px 24px;
background: #f5f7fb; background: var(--el-bg-color-page, #f5f7fb);
color: var(--el-text-color-primary, #303133);
} }
.business-page .page-filter, .business-page .page-filter,
@@ -12,10 +13,10 @@
.report-page .page-filter { .report-page .page-filter {
margin: 0 0 14px; margin: 0 0 14px;
padding: 14px 16px 2px; padding: 14px 16px 2px;
border: 1px solid #e7ebf2; border: 1px solid var(--el-border-color-lighter, #e4e7ed);
border-radius: 12px; border-radius: 12px;
background: #fff; background: var(--el-bg-color, #fff);
box-shadow: 0 3px 14px rgba(31, 55, 88, 0.05); box-shadow: var(--el-box-shadow-lighter, 0 3px 14px rgba(31, 55, 88, 0.05));
} }
.business-page .page-filter .el-form-item, .business-page .page-filter .el-form-item,
@@ -58,19 +59,19 @@
.master-page .data-table, .master-page .data-table,
.report-page .data-table { .report-page .data-table {
width: 100%; width: 100%;
border: 1px solid #e7ebf2; border: 1px solid var(--el-border-color-lighter, #e4e7ed);
border-radius: 12px; border-radius: 12px;
overflow: hidden; overflow: hidden;
background: #fff; background: var(--el-bg-color, #fff);
box-shadow: 0 3px 14px rgba(31, 55, 88, 0.04); box-shadow: var(--el-box-shadow-lighter, 0 3px 14px rgba(31, 55, 88, 0.04));
} }
.business-page .data-table .el-table__header th, .business-page .data-table .el-table__header th,
.master-page .data-table .el-table__header th, .master-page .data-table .el-table__header th,
.report-page .data-table .el-table__header th { .report-page .data-table .el-table__header th {
height: 46px !important; height: 46px !important;
background: #f7f9fc !important; background: var(--el-fill-color-light, #f5f7fa) !important;
color: #344054; color: var(--el-text-color-regular, #606266);
font-weight: 650; font-weight: 650;
} }
@@ -83,7 +84,7 @@
.business-page .data-table .el-table__body tr:nth-child(even) > td, .business-page .data-table .el-table__body tr:nth-child(even) > td,
.master-page .data-table .el-table__body tr:nth-child(even) > td, .master-page .data-table .el-table__body tr:nth-child(even) > td,
.report-page .data-table .el-table__body tr:nth-child(even) > td { .report-page .data-table .el-table__body tr:nth-child(even) > td {
background: #fbfcfe; background: var(--el-fill-color-lighter, #fafafa);
} }
.business-page .data-table .el-table__inner-wrapper::before, .business-page .data-table .el-table__inner-wrapper::before,
@@ -107,7 +108,7 @@
.business-page .operation-card { .business-page .operation-card {
border-radius: 12px; border-radius: 12px;
box-shadow: 0 3px 14px rgba(31, 55, 88, 0.05); box-shadow: var(--el-box-shadow-lighter, 0 3px 14px rgba(31, 55, 88, 0.05));
} }
@media (max-width: 767px) { @media (max-width: 767px) {
@@ -1,21 +1,19 @@
<template> <template>
<div class="sidebar-logo-container" :class="{ 'collapse': collapse }"> <div class="sidebar-logo-container" :class="{ 'collapse': collapse }">
<transition name="sidebarLogoFade"> <transition name="sidebarLogoFade">
<router-link v-if="collapse" key="collapse" class="sidebar-logo-link" to="/"> <router-link v-if="collapse" key="collapse" class="sidebar-logo-link" :aria-label="title" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <img :src="logoMark" :alt="title" class="sidebar-logo sidebar-logo-mark" />
<h1 v-else class="sidebar-title">{{ title }}</h1>
</router-link> </router-link>
<router-link v-else key="expand" class="sidebar-logo-link" to="/"> <router-link v-else key="expand" class="sidebar-logo-link" :aria-label="title" to="/">
<img v-if="logo" :src="logo" class="sidebar-logo" /> <img :src="logo" :alt="title" class="sidebar-logo sidebar-logo-full" />
<h1 class="sidebar-title">{{ title }}</h1>
</router-link> </router-link>
</transition> </transition>
</div> </div>
</template> </template>
<script setup> <script setup>
import logo from '@/assets/logo/logo.png' import logo from '@/assets/logo/sylvan-logo.svg'
import useSettingsStore from '@/store/modules/settings' import logoMark from '@/assets/logo/sylvan-mark.svg'
import variables from '@/assets/styles/variables.module.scss' import variables from '@/assets/styles/variables.module.scss'
defineProps({ defineProps({
@@ -26,30 +24,7 @@ defineProps({
}) })
const title = import.meta.env.VITE_APP_TITLE; const title = import.meta.env.VITE_APP_TITLE;
const settingsStore = useSettingsStore(); const logoBackground = variables.menuBg;
const sideTheme = computed(() => settingsStore.sideTheme);
// 获取Logo背景色
const getLogoBackground = computed(() => {
if (settingsStore.isDark) {
return 'var(--sidebar-bg)';
}
if (settingsStore.navType == 3) {
return variables.menuLightBg
}
return sideTheme.value === 'theme-dark' ? variables.menuBg : variables.menuLightBg;
});
// 获取Logo文字颜色
const getLogoTextColor = computed(() => {
if (settingsStore.isDark) {
return 'var(--sidebar-text)';
}
if (settingsStore.navType == 3) {
return variables.menuLightText
}
return sideTheme.value === 'theme-dark' ? '#fff' : variables.menuLightText;
});
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -66,37 +41,39 @@ const getLogoTextColor = computed(() => {
position: relative; position: relative;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
background: v-bind(getLogoBackground); background: v-bind(logoBackground);
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
& .sidebar-logo-link { & .sidebar-logo-link {
display: flex;
align-items: center;
justify-content: center;
height: 100%; height: 100%;
width: 100%; width: 100%;
box-sizing: border-box;
padding: 4px 12px;
& .sidebar-logo { & .sidebar-logo {
width: 32px; display: block;
height: 32px; object-fit: contain;
vertical-align: middle;
margin-right: 12px;
} }
& .sidebar-title { & .sidebar-logo-full {
display: inline-block; width: 132px;
margin: 0; height: 42px;
color: v-bind(getLogoTextColor); }
font-weight: 600;
line-height: 50px; & .sidebar-logo-mark {
font-size: 14px; width: 32px;
font-family: Avenir, Helvetica Neue, Arial, Helvetica, sans-serif; height: 32px;
vertical-align: middle;
} }
} }
&.collapse { &.collapse {
.sidebar-logo { .sidebar-logo-link {
margin-right: 0px; padding: 4px;
} }
} }
} }
</style> </style>
@@ -0,0 +1,55 @@
export const TREND_RANGE_OPTIONS = [
{ value: 7, label: '近 7 天' },
{ value: 14, label: '近 14 天' },
{ value: 30, label: '近 1 个月' }
]
function formatDate(date) {
const year = date.getFullYear()
const month = String(date.getMonth() + 1).padStart(2, '0')
const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
}
function dateKey(value) {
if (value instanceof Date) return formatDate(value)
return typeof value === 'string' ? value.slice(0, 10) : ''
}
export function getTrendRangeQuery(days, today = new Date()) {
const end = new Date(today)
const begin = new Date(end)
begin.setDate(end.getDate() - Number(days) + 1)
return { beginTime: formatDate(begin), endTime: formatDate(end) }
}
export function buildTrendData(inboundRows = [], shipmentRows = [], days = 7, today = new Date()) {
const end = new Date(today)
const dates = []
const inboundMap = new Map()
const shipmentMap = new Map()
for (let offset = Number(days) - 1; offset >= 0; offset -= 1) {
const date = new Date(end)
date.setDate(end.getDate() - offset)
const key = formatDate(date)
dates.push({ key, label: `${date.getMonth() + 1}/${date.getDate()}` })
inboundMap.set(key, 0)
shipmentMap.set(key, 0)
}
inboundRows.forEach((row) => {
const key = dateKey(row.createTime)
if (inboundMap.has(key)) inboundMap.set(key, inboundMap.get(key) + 1)
})
shipmentRows.forEach((row) => {
const key = dateKey(row.confirmedAt)
if (shipmentMap.has(key)) shipmentMap.set(key, shipmentMap.get(key) + (Number(row.packageQty) || 0))
})
return {
labels: dates.map((item) => item.label),
inbound: dates.map((item) => inboundMap.get(item.key) || 0),
outbound: dates.map((item) => shipmentMap.get(item.key) || 0)
}
}
@@ -29,10 +29,12 @@
v-hasPermi="['business:filling:add']" v-hasPermi="['business:filling:add']"
>托盘装填</el-button> >托盘装填</el-button>
</el-col> </el-col>
<el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
<div v-if="userStore.admin === true && !testBatchStore.isTestMode" class="mb8"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></div>
<el-table v-loading="loading" empty-text="暂无数据" :data="fillingList" class="data-table" @selection-change="handleSelectionChange"> <el-table v-loading="loading" empty-text="暂无数据" :data="fillingList" class="data-table" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="装填单号" prop="fillingNo" min-width="170" :show-overflow-tooltip="true" /> <el-table-column label="装填单号" prop="fillingNo" min-width="170" :show-overflow-tooltip="true" />
@@ -38,10 +38,12 @@
v-hasPermi="['business:inbound:add']" v-hasPermi="['business:inbound:add']"
>新增入库草稿</el-button> >新增入库草稿</el-button>
</el-col> </el-col>
<el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
<div v-if="userStore.admin === true && !testBatchStore.isTestMode" class="mb8"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></div>
<el-table v-loading="loading" empty-text="暂无数据" :data="inboundList" class="data-table" @selection-change="handleSelectionChange"> <el-table v-loading="loading" empty-text="暂无数据" :data="inboundList" class="data-table" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="入库单号" prop="inboundNo" min-width="170" :show-overflow-tooltip="true" /> <el-table-column label="入库单号" prop="inboundNo" min-width="170" :show-overflow-tooltip="true" />
@@ -172,8 +172,13 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row :gutter="10" class="mb8 page-toolbar">
<el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
<div v-if="userStore.admin === true && !testBatchStore.isTestMode" class="mb8"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></div>
<el-table v-loading="loading" empty-text="暂无数据" :data="returnList" class="data-table" @selection-change="handleSelectionChange"> <el-table v-loading="loading" empty-text="暂无数据" :data="returnList" class="data-table" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="退回单号" prop="returnNo" min-width="170" :show-overflow-tooltip="true" /> <el-table-column label="退回单号" prop="returnNo" min-width="170" :show-overflow-tooltip="true" />
@@ -35,10 +35,12 @@
v-hasPermi="['business:shipment:add']" v-hasPermi="['business:shipment:add']"
>新增发货草稿</el-button> >新增发货草稿</el-button>
</el-col> </el-col>
<el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
<div v-if="userStore.admin === true && !testBatchStore.isTestMode" class="mb8"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></div>
<el-table v-loading="loading" empty-text="暂无数据" :data="shipmentList" class="data-table" @selection-change="handleSelectionChange"> <el-table v-loading="loading" empty-text="暂无数据" :data="shipmentList" class="data-table" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="发货单号" prop="shipmentNo" min-width="170" :show-overflow-tooltip="true" /> <el-table-column label="发货单号" prop="shipmentNo" min-width="170" :show-overflow-tooltip="true" />
@@ -111,8 +111,13 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row :gutter="10" class="mb8 page-toolbar">
<el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
<div v-if="userStore.admin === true && !testBatchStore.isTestMode" class="mb8"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length || operationPending" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></div>
<el-table v-loading="loading" empty-text="暂无数据" :data="usageList" class="data-table" @selection-change="handleSelectionChange"> <el-table v-loading="loading" empty-text="暂无数据" :data="usageList" class="data-table" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" /> <el-table-column type="selection" width="55" />
<el-table-column label="使用记录号" prop="usageNo" min-width="170" :show-overflow-tooltip="true" /> <el-table-column label="使用记录号" prop="usageNo" min-width="170" :show-overflow-tooltip="true" />
@@ -1,22 +1,5 @@
<template> <template>
<div class="dashboard-page"> <div class="dashboard-page">
<section class="dashboard-header">
<div>
<div class="dashboard-kicker">运营驾驶舱</div>
<h1>仓储运营总览</h1>
<p>聚焦托盘库存、入库出库和待处理业务,快速掌握当前运营状态。</p>
</div>
<div class="dashboard-header-actions">
<div class="dashboard-meta">
<el-tag type="info" effect="plain">数据范围:全部仓库</el-tag>
<span>更新于 {{ updatedAtText }}</span>
</div>
<el-button type="primary" plain :icon="Refresh" :loading="state.loading" @click="loadDashboardData">
刷新数据
</el-button>
</div>
</section>
<div v-if="state.partialError" class="dashboard-alert"> <div v-if="state.partialError" class="dashboard-alert">
<el-icon><Warning /></el-icon> <el-icon><Warning /></el-icon>
<span>部分运营数据暂时无法加载,已保留可用模块。</span> <span>部分运营数据暂时无法加载,已保留可用模块。</span>
@@ -35,13 +18,6 @@
</section> </section>
<section class="dashboard-section quick-section"> <section class="dashboard-section quick-section">
<div class="section-heading">
<div>
<div class="section-kicker">常用流程</div>
<h2>快捷操作</h2>
</div>
<span>从这里直接进入日常仓储操作</span>
</div>
<div class="quick-action-grid"> <div class="quick-action-grid">
<button v-for="item in quickActions" :key="item.label" type="button" class="quick-action" @click="navigateTo(item.path)"> <button v-for="item in quickActions" :key="item.label" type="button" class="quick-action" @click="navigateTo(item.path)">
<span class="quick-action-icon"><el-icon><component :is="item.icon" /></el-icon></span> <span class="quick-action-icon"><el-icon><component :is="item.icon" /></el-icon></span>
@@ -59,16 +35,25 @@
<template #header> <template #header>
<div class="card-heading"> <div class="card-heading">
<div> <div>
<h2>近 7 天入库 / 出库趋势</h2> <h2>{{ trendRangeLabel }}入库 / 出库趋势</h2>
<span>入库以单据数统计,出库以确认包数统计</span> <span>入库以单据数统计,出库以确认包数统计</span>
</div> </div>
<el-tag type="primary" effect="plain">近 7 天</el-tag> <el-select
v-model="selectedTrendDays"
class="trend-range-select"
size="small"
aria-label="趋势时间范围"
:disabled="state.loading || trendLoading"
@change="handleTrendRangeChange"
>
<el-option v-for="option in TREND_RANGE_OPTIONS" :key="option.value" :label="option.label" :value="option.value" />
</el-select>
</div> </div>
</template> </template>
<div class="chart-wrapper"> <div class="chart-wrapper">
<div ref="trendChartRef" class="chart-canvas" /> <div ref="trendChartRef" class="chart-canvas" />
<el-skeleton v-if="state.loading" class="chart-loading" animated :rows="5" /> <el-skeleton v-if="state.loading || trendLoading" class="chart-loading" animated :rows="5" />
<el-empty v-else-if="!trendHasData" class="chart-empty" description="暂无近 7 天业务数据" :image-size="72" /> <el-empty v-else-if="!trendHasData" class="chart-empty" :description="`暂无${trendRangeLabel}业务数据`" :image-size="72" />
</div> </div>
</el-card> </el-card>
@@ -184,13 +169,14 @@
<script setup name="DashBoard"> <script setup name="DashBoard">
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { ArrowRight, Box, CircleCheck, Coin, Download, DocumentAdd, Operation, Refresh, Upload, Van, Warning, WarningFilled } from '@element-plus/icons-vue' import { ArrowRight, Box, CircleCheck, Coin, Download, DocumentAdd, Operation, Upload, Van, Warning, WarningFilled } from '@element-plus/icons-vue'
import { listInbound } from '@/api/business/inbound' import { listInbound } from '@/api/business/inbound'
import { listReturn } from '@/api/business/return' import { listReturn } from '@/api/business/return'
import { listShipment } from '@/api/business/shipment' import { listShipment } from '@/api/business/shipment'
import { listPalletInventory } from '@/api/report/palletInventory' import { listPalletInventory } from '@/api/report/palletInventory'
import { listShipmentReport } from '@/api/report/shipment' import { listShipmentReport } from '@/api/report/shipment'
import useSettingsStore from '@/store/modules/settings' import useSettingsStore from '@/store/modules/settings'
import { buildTrendData, getTrendRangeQuery, TREND_RANGE_OPTIONS } from '@/utils/dashboardTrend'
defineOptions({ name: 'DashBoard' }) defineOptions({ name: 'DashBoard' })
@@ -198,10 +184,11 @@ const router = useRouter()
const settingsStore = useSettingsStore() const settingsStore = useSettingsStore()
const trendChartRef = ref(null) const trendChartRef = ref(null)
const distributionChartRef = ref(null) const distributionChartRef = ref(null)
const selectedTrendDays = ref(7)
const trendLoading = ref(false)
const state = reactive({ const state = reactive({
loading: false, loading: false,
partialError: false, partialError: false,
lastUpdated: null,
inventoryRows: [], inventoryRows: [],
inventoryTotal: null, inventoryTotal: null,
remainingPackages: null, remainingPackages: null,
@@ -236,9 +223,9 @@ const pendingItems = computed(() => state.pendingItems)
const pendingTotal = computed(() => state.pendingTotal) const pendingTotal = computed(() => state.pendingTotal)
const recentInbound = computed(() => state.recentInbound) const recentInbound = computed(() => state.recentInbound)
const recentShipments = computed(() => state.recentShipments) const recentShipments = computed(() => state.recentShipments)
const updatedAtText = computed(() => state.lastUpdated ? formatTime(state.lastUpdated) : '尚未更新')
const inventoryHasData = computed(() => state.inventoryRows.length > 0) const inventoryHasData = computed(() => state.inventoryRows.length > 0)
const trendHasData = computed(() => state.trendInboundRows.length > 0 || state.trendShipmentRows.length > 0) const trendHasData = computed(() => state.trendInboundRows.length > 0 || state.trendShipmentRows.length > 0)
const trendRangeLabel = computed(() => TREND_RANGE_OPTIONS.find((option) => option.value === selectedTrendDays.value)?.label || '近 7 天')
const inventoryStateLabels = { const inventoryStateLabels = {
UNSTOCKED: '未入库', UNSTOCKED: '未入库',
@@ -273,33 +260,7 @@ const warehouseRankings = computed(() => {
return rows.slice(0, 5).map((item) => ({ ...item, percentage: Math.max(4, Math.round(item.packages / maxPackages * 100)) })) return rows.slice(0, 5).map((item) => ({ ...item, percentage: Math.max(4, Math.round(item.packages / maxPackages * 100)) }))
}) })
const trendData = computed(() => { const trendData = computed(() => buildTrendData(state.trendInboundRows, state.trendShipmentRows, selectedTrendDays.value))
const dates = []
const inboundMap = new Map()
const shipmentMap = new Map()
const today = new Date()
for (let offset = 6; offset >= 0; offset -= 1) {
const date = new Date(today)
date.setDate(today.getDate() - offset)
const key = formatDate(date)
dates.push({ key, label: `${date.getMonth() + 1}/${date.getDate()}` })
inboundMap.set(key, 0)
shipmentMap.set(key, 0)
}
state.trendInboundRows.forEach((row) => {
const key = dateKey(row.createTime)
if (inboundMap.has(key)) inboundMap.set(key, inboundMap.get(key) + 1)
})
state.trendShipmentRows.forEach((row) => {
const key = dateKey(row.confirmedAt)
if (shipmentMap.has(key)) shipmentMap.set(key, shipmentMap.get(key) + (Number(row.packageQty) || 0))
})
return {
labels: dates.map((item) => item.label),
inbound: dates.map((item) => inboundMap.get(item.key) || 0),
outbound: dates.map((item) => shipmentMap.get(item.key) || 0)
}
})
function formatNumber(value) { function formatNumber(value) {
return Number(value || 0).toLocaleString('zh-CN') return Number(value || 0).toLocaleString('zh-CN')
@@ -317,10 +278,6 @@ function formatDate(date) {
return `${year}-${month}-${day}` return `${year}-${month}-${day}`
} }
function dateKey(value) {
return typeof value === 'string' ? value.slice(0, 10) : ''
}
function formatTime(value) { function formatTime(value) {
if (!value) return '—' if (!value) return '—'
const date = new Date(value) const date = new Date(value)
@@ -366,26 +323,44 @@ function recentQuery() {
return { pageNum: 1, pageSize: 5 } return { pageNum: 1, pageSize: 5 }
} }
function sevenDayQuery() { async function fetchTrendData() {
const begin = new Date() const query = getTrendRangeQuery(selectedTrendDays.value)
begin.setDate(begin.getDate() - 6) const [inboundTrend, shipmentTrend] = await Promise.all([
return { beginTime: formatDate(begin), endTime: formatDate(new Date()) } requestSafely('入库趋势', () => loadAllPages(listInbound, query), { rows: [], total: 0 }),
requestSafely('出库趋势', () => loadAllPages(listShipmentReport, query), { rows: [], total: 0 })
])
return { inboundRows: inboundTrend.rows, shipmentRows: shipmentTrend.rows }
}
async function loadTrendData() {
trendLoading.value = true
try {
const trend = await fetchTrendData()
state.trendInboundRows = trend.inboundRows
state.trendShipmentRows = trend.shipmentRows
} finally {
trendLoading.value = false
await nextTick()
renderCharts()
}
}
async function handleTrendRangeChange() {
await loadTrendData()
} }
async function loadDashboardData() { async function loadDashboardData() {
state.loading = true state.loading = true
state.partialError = false state.partialError = false
const today = todayQuery() const today = todayQuery()
const sevenDays = sevenDayQuery()
try { try {
const [inventory, todayInbound, todayShipment, recentInboundResponse, recentShipmentResponse, inboundTrend, shipmentTrend, pendingInbound, pendingShipment, pendingReturn] = await Promise.all([ const [inventory, todayInbound, todayShipment, recentInboundResponse, recentShipmentResponse, trend, pendingInbound, pendingShipment, pendingReturn] = await Promise.all([
requestSafely('托盘库存', () => loadAllPages(listPalletInventory), { rows: [], total: 0 }), requestSafely('托盘库存', () => loadAllPages(listPalletInventory), { rows: [], total: 0 }),
requestSafely('今日入库', () => listInbound({ ...today, pageNum: 1, pageSize: 1 }), {}), requestSafely('今日入库', () => listInbound({ ...today, pageNum: 1, pageSize: 1 }), {}),
requestSafely('今日出库', () => listShipment({ ...today, pageNum: 1, pageSize: 1 }), {}), requestSafely('今日出库', () => listShipment({ ...today, pageNum: 1, pageSize: 1 }), {}),
requestSafely('最近入库', () => listInbound(recentQuery()), {}), requestSafely('最近入库', () => listInbound(recentQuery()), {}),
requestSafely('最近出库', () => listShipmentReport(recentQuery()), {}), requestSafely('最近出库', () => listShipmentReport(recentQuery()), {}),
requestSafely('入库趋势', () => loadAllPages(listInbound, sevenDays), { rows: [], total: 0 }), fetchTrendData(),
requestSafely('出库趋势', () => loadAllPages(listShipmentReport, sevenDays), { rows: [], total: 0 }),
requestSafely('待确认入库', () => listInbound({ status: 'DRAFT', pageNum: 1, pageSize: 5 }), {}), requestSafely('待确认入库', () => listInbound({ status: 'DRAFT', pageNum: 1, pageSize: 5 }), {}),
requestSafely('待确认出库', () => listShipment({ status: 'DRAFT', pageNum: 1, pageSize: 5 }), {}), requestSafely('待确认出库', () => listShipment({ status: 'DRAFT', pageNum: 1, pageSize: 5 }), {}),
requestSafely('待确认退回', () => listReturn({ status: 'REQUESTED', pageNum: 1, pageSize: 5 }), {}) requestSafely('待确认退回', () => listReturn({ status: 'REQUESTED', pageNum: 1, pageSize: 5 }), {})
@@ -398,15 +373,14 @@ async function loadDashboardData() {
state.todayShipmentTotal = getTotal(todayShipment) state.todayShipmentTotal = getTotal(todayShipment)
state.recentInbound = getRows(recentInboundResponse) state.recentInbound = getRows(recentInboundResponse)
state.recentShipments = getRows(recentShipmentResponse) state.recentShipments = getRows(recentShipmentResponse)
state.trendInboundRows = inboundTrend.rows state.trendInboundRows = trend.inboundRows
state.trendShipmentRows = shipmentTrend.rows state.trendShipmentRows = trend.shipmentRows
state.pendingItems = [ state.pendingItems = [
...getRows(pendingInbound).map((row) => ({ key: `inbound-${row.inboundId}`, title: row.inboundNo, type: '入库单', status: row.status, time: row.createTime, path: '/businessOperation/inbound', tone: 'orange' })), ...getRows(pendingInbound).map((row) => ({ key: `inbound-${row.inboundId}`, title: row.inboundNo, type: '入库单', status: row.status, time: row.createTime, path: '/businessOperation/inbound', tone: 'orange' })),
...getRows(pendingShipment).map((row) => ({ key: `shipment-${row.shipmentId}`, title: row.shipmentNo, type: '出库单', status: row.status, time: row.createTime, path: '/businessOperation/shipment', tone: 'blue' })), ...getRows(pendingShipment).map((row) => ({ key: `shipment-${row.shipmentId}`, title: row.shipmentNo, type: '出库单', status: row.status, time: row.createTime, path: '/businessOperation/shipment', tone: 'blue' })),
...getRows(pendingReturn).map((row) => ({ key: `return-${row.returnId}`, title: row.returnNo, type: '退回申请', status: row.status, time: row.requestedAt, path: '/businessOperation/return', tone: 'green' })) ...getRows(pendingReturn).map((row) => ({ key: `return-${row.returnId}`, title: row.returnNo, type: '退回申请', status: row.status, time: row.requestedAt, path: '/businessOperation/return', tone: 'green' }))
].slice(0, 6) ].slice(0, 6)
state.pendingTotal = getTotal(pendingInbound) + getTotal(pendingShipment) + getTotal(pendingReturn) state.pendingTotal = getTotal(pendingInbound) + getTotal(pendingShipment) + getTotal(pendingReturn)
state.lastUpdated = new Date()
} finally { } finally {
state.loading = false state.loading = false
await nextTick() await nextTick()
@@ -446,7 +420,7 @@ function renderCharts() {
tooltip: { trigger: 'axis' }, tooltip: { trigger: 'axis' },
legend: { bottom: 0, textStyle: { color: chartTextColor() } }, legend: { bottom: 0, textStyle: { color: chartTextColor() } },
grid: { top: 18, right: 20, bottom: 42, left: 42 }, grid: { top: 18, right: 20, bottom: 42, left: 42 },
xAxis: { type: 'category', boundaryGap: false, data: trendData.value.labels, axisLine: { lineStyle: { color: chartGridColor() } }, axisLabel: { color: chartTextColor() } }, xAxis: { type: 'category', boundaryGap: false, data: trendData.value.labels, axisLine: { lineStyle: { color: chartGridColor() } }, axisLabel: { color: chartTextColor(), interval: selectedTrendDays.value > 14 ? 4 : 0, hideOverlap: true } },
yAxis: { type: 'value', minInterval: 1, splitLine: { lineStyle: { color: chartGridColor() } }, axisLabel: { color: chartTextColor() } }, yAxis: { type: 'value', minInterval: 1, splitLine: { lineStyle: { color: chartGridColor() } }, axisLabel: { color: chartTextColor() } },
series: [ series: [
{ name: '入库单', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: trendData.value.inbound, areaStyle: { opacity: 0.08 } }, { name: '入库单', type: 'line', smooth: true, symbol: 'circle', symbolSize: 7, data: trendData.value.inbound, areaStyle: { opacity: 0.08 } },
@@ -499,23 +473,14 @@ onBeforeUnmount(() => {
color: var(--el-text-color-primary, #1f2937); color: var(--el-text-color-primary, #1f2937);
} }
.dashboard-header,
.section-heading,
.card-heading, .card-heading,
.dashboard-header-actions,
.dashboard-meta,
.warehouse-title { .warehouse-title {
display: flex; display: flex;
align-items: center; align-items: center;
} }
.dashboard-header { justify-content: space-between; gap: 24px; margin-bottom: 20px; } .card-heading h2 { margin: 0; color: var(--el-text-color-primary); font-weight: 700; }
.dashboard-kicker, .section-kicker { margin-bottom: 6px; color: var(--el-color-primary); font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; } .card-heading span { margin: 8px 0 0; color: var(--el-text-color-secondary); font-size: 13px; }
.dashboard-header h1, .section-heading h2, .card-heading h2 { margin: 0; color: var(--el-text-color-primary); font-weight: 700; }
.dashboard-header h1 { font-size: 26px; line-height: 1.25; }
.dashboard-header p, .section-heading > span, .card-heading span { margin: 8px 0 0; color: var(--el-text-color-secondary); font-size: 13px; }
.dashboard-header-actions { flex-direction: column; align-items: flex-end; gap: 12px; }
.dashboard-meta { gap: 12px; color: var(--el-text-color-secondary); font-size: 12px; }
.dashboard-alert { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; padding: 10px 14px; border: 1px solid var(--el-color-warning-light-5); border-radius: 10px; background: var(--el-color-warning-light-9); color: var(--el-color-warning-dark-2); font-size: 13px; } .dashboard-alert { display: flex; align-items: center; gap: 8px; margin-bottom: 16px; padding: 10px 14px; border: 1px solid var(--el-color-warning-light-5); border-radius: 10px; background: var(--el-color-warning-light-9); color: var(--el-color-warning-dark-2); font-size: 13px; }
.dashboard-alert .el-button { margin-left: auto; } .dashboard-alert .el-button { margin-left: auto; }
@@ -527,17 +492,17 @@ onBeforeUnmount(() => {
.kpi-content { min-width: 0; }.kpi-label { display: block; color: var(--el-text-color-secondary); font-size: 13px; }.kpi-content strong { display: block; margin: 7px 0 2px; font-size: 28px; line-height: 1; }.kpi-caption { color: var(--el-text-color-placeholder); font-size: 12px; } .kpi-content { min-width: 0; }.kpi-label { display: block; color: var(--el-text-color-secondary); font-size: 13px; }.kpi-content strong { display: block; margin: 7px 0 2px; font-size: 28px; line-height: 1; }.kpi-caption { color: var(--el-text-color-placeholder); font-size: 12px; }
.dashboard-section, .dashboard-card { border: 1px solid var(--el-border-color-lighter); border-radius: 14px; background: var(--el-bg-color, #fff); box-shadow: 0 5px 18px rgba(31, 55, 88, .04); } .dashboard-section, .dashboard-card { border: 1px solid var(--el-border-color-lighter); border-radius: 14px; background: var(--el-bg-color, #fff); box-shadow: 0 5px 18px rgba(31, 55, 88, .04); }
.quick-section { margin-bottom: 20px; padding: 20px; }.section-heading { justify-content: space-between; gap: 16px; margin-bottom: 16px; }.section-heading > span { margin: 0; }.section-heading h2, .card-heading h2 { font-size: 17px; } .quick-section { margin-bottom: 20px; padding: 20px; }.card-heading h2 { font-size: 17px; }
.quick-action-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }.quick-action { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 12px; border: 1px solid var(--el-border-color-lighter); border-radius: 10px; background: transparent; color: inherit; text-align: left; cursor: pointer; transition: border-color .2s ease, background-color .2s ease, transform .2s ease; }.quick-action:hover { border-color: var(--el-color-primary-light-5); background: var(--el-color-primary-light-9); transform: translateY(-1px); }.quick-action-icon { width: 34px; height: 34px; background: var(--el-color-primary-light-9); color: var(--el-color-primary); font-size: 18px; }.quick-action-copy { display: flex; flex-direction: column; min-width: 0; gap: 3px; }.quick-action-copy strong { font-size: 13px; white-space: nowrap; }.quick-action-copy small { overflow: hidden; color: var(--el-text-color-secondary); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }.quick-action-arrow { margin-left: auto; color: var(--el-text-color-placeholder); } .quick-action-grid { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }.quick-action { display: flex; align-items: center; gap: 10px; min-width: 0; padding: 12px; border: 1px solid var(--el-border-color-lighter); border-radius: 10px; background: transparent; color: inherit; text-align: left; cursor: pointer; transition: border-color .2s ease, background-color .2s ease, transform .2s ease; }.quick-action:hover { border-color: var(--el-color-primary-light-5); background: var(--el-color-primary-light-9); transform: translateY(-1px); }.quick-action-icon { width: 34px; height: 34px; background: var(--el-color-primary-light-9); color: var(--el-color-primary); font-size: 18px; }.quick-action-copy { display: flex; flex-direction: column; min-width: 0; gap: 3px; }.quick-action-copy strong { font-size: 13px; white-space: nowrap; }.quick-action-copy small { overflow: hidden; color: var(--el-text-color-secondary); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }.quick-action-arrow { margin-left: auto; color: var(--el-text-color-placeholder); }
.dashboard-grid { display: grid; gap: 20px; margin-bottom: 20px; }.chart-grid { grid-template-columns: minmax(0, 1.55fr) minmax(340px, 1fr); }.operational-grid { grid-template-columns: minmax(0, 1.1fr) minmax(360px, .9fr); }.activity-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 0; }.dashboard-card :deep(.el-card__header) { padding: 18px 20px; border-bottom-color: var(--el-border-color-lighter); }.dashboard-card :deep(.el-card__body) { padding: 18px 20px; }.dashboard-card { overflow: hidden; }.card-heading { justify-content: space-between; gap: 12px; }.card-heading > div { min-width: 0; }.card-heading span { display: block; margin-top: 5px; font-size: 12px; } .dashboard-grid { display: grid; gap: 20px; margin-bottom: 20px; }.chart-grid { grid-template-columns: minmax(0, 1.55fr) minmax(340px, 1fr); }.operational-grid { grid-template-columns: minmax(0, 1.1fr) minmax(360px, .9fr); }.activity-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); margin-bottom: 0; }.dashboard-card :deep(.el-card__header) { padding: 18px 20px; border-bottom-color: var(--el-border-color-lighter); }.dashboard-card :deep(.el-card__body) { padding: 18px 20px; }.dashboard-card { overflow: hidden; }.card-heading { justify-content: space-between; gap: 12px; }.card-heading > div { min-width: 0; }.card-heading span { display: block; margin-top: 5px; font-size: 12px; }
.chart-wrapper { position: relative; min-height: 290px; }.chart-wrapper--distribution { min-height: 290px; }.chart-canvas { width: 100%; height: 290px; }.chart-loading, .chart-empty { position: absolute; inset: 20px; } .trend-range-select { width: 112px; flex: 0 0 auto; }.chart-wrapper { position: relative; min-height: 290px; }.chart-wrapper--distribution { min-height: 290px; }.chart-canvas { width: 100%; height: 290px; }.chart-loading, .chart-empty { position: absolute; inset: 20px; }
.warehouse-ranking, .pending-list, .activity-list { min-height: 250px; }.warehouse-row { display: flex; align-items: center; gap: 12px; padding: 12px 0; }.warehouse-row + .warehouse-row { border-top: 1px solid var(--el-border-color-lighter); }.warehouse-rank { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 7px; background: var(--el-fill-color-light); color: var(--el-text-color-secondary); font-size: 12px; font-weight: 700; }.warehouse-rank--top { background: var(--el-color-primary-light-9); color: var(--el-color-primary); }.warehouse-main { flex: 1; min-width: 0; }.warehouse-title { justify-content: space-between; gap: 10px; margin-bottom: 8px; font-size: 13px; }.warehouse-title span { color: var(--el-text-color-placeholder); font-size: 12px; }.warehouse-value { flex: 0 0 84px; color: var(--el-text-color-primary); font-size: 13px; text-align: right; } .warehouse-ranking, .pending-list, .activity-list { min-height: 250px; }.warehouse-row { display: flex; align-items: center; gap: 12px; padding: 12px 0; }.warehouse-row + .warehouse-row { border-top: 1px solid var(--el-border-color-lighter); }.warehouse-rank { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px; border-radius: 7px; background: var(--el-fill-color-light); color: var(--el-text-color-secondary); font-size: 12px; font-weight: 700; }.warehouse-rank--top { background: var(--el-color-primary-light-9); color: var(--el-color-primary); }.warehouse-main { flex: 1; min-width: 0; }.warehouse-title { justify-content: space-between; gap: 10px; margin-bottom: 8px; font-size: 13px; }.warehouse-title span { color: var(--el-text-color-placeholder); font-size: 12px; }.warehouse-value { flex: 0 0 84px; color: var(--el-text-color-primary); font-size: 13px; text-align: right; }
.pending-item, .activity-item { display: flex; align-items: center; width: 100%; gap: 10px; padding: 12px 0; border: 0; border-bottom: 1px solid var(--el-border-color-lighter); background: transparent; color: inherit; text-align: left; cursor: pointer; }.pending-item:last-child, .activity-item:last-child { border-bottom: 0; }.pending-item:hover .pending-copy strong, .activity-item:hover .activity-copy strong { color: var(--el-color-primary); }.pending-dot { width: 8px; height: 8px; border-radius: 50%; }.pending-dot--orange { background: #f59e0b; }.pending-dot--blue { background: #1677ff; }.pending-dot--green { background: #16a085; }.pending-copy, .activity-copy { display: flex; flex: 1; flex-direction: column; min-width: 0; gap: 4px; }.pending-copy strong, .activity-copy strong { overflow: hidden; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }.pending-copy small, .activity-copy small { color: var(--el-text-color-secondary); font-size: 12px; }.activity-icon { width: 34px; height: 34px; font-size: 16px; }.activity-icon--inbound { background: #eaf3ff; color: #1677ff; }.activity-icon--outbound { background: #fff1e8; color: #d97706; }.activity-quantity { color: var(--el-color-primary); font-size: 12px; font-weight: 700; white-space: nowrap; } .pending-item, .activity-item { display: flex; align-items: center; width: 100%; gap: 10px; padding: 12px 0; border: 0; border-bottom: 1px solid var(--el-border-color-lighter); background: transparent; color: inherit; text-align: left; cursor: pointer; }.pending-item:last-child, .activity-item:last-child { border-bottom: 0; }.pending-item:hover .pending-copy strong, .activity-item:hover .activity-copy strong { color: var(--el-color-primary); }.pending-dot { width: 8px; height: 8px; border-radius: 50%; }.pending-dot--orange { background: #f59e0b; }.pending-dot--blue { background: #1677ff; }.pending-dot--green { background: #16a085; }.pending-copy, .activity-copy { display: flex; flex: 1; flex-direction: column; min-width: 0; gap: 4px; }.pending-copy strong, .activity-copy strong { overflow: hidden; font-size: 13px; text-overflow: ellipsis; white-space: nowrap; }.pending-copy small, .activity-copy small { color: var(--el-text-color-secondary); font-size: 12px; }.activity-icon { width: 34px; height: 34px; font-size: 16px; }.activity-icon--inbound { background: #eaf3ff; color: #1677ff; }.activity-icon--outbound { background: #fff1e8; color: #d97706; }.activity-quantity { color: var(--el-color-primary); font-size: 12px; font-weight: 700; white-space: nowrap; }
.exception-empty { display: flex; min-height: 250px; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--el-text-color-secondary); text-align: center; }.exception-icon { width: 52px; height: 52px; margin-bottom: 5px; background: var(--el-color-success-light-9); color: var(--el-color-success); font-size: 26px; }.exception-empty strong { color: var(--el-text-color-primary); font-size: 14px; }.exception-empty span { max-width: 230px; font-size: 12px; line-height: 1.6; } .exception-empty { display: flex; min-height: 250px; flex-direction: column; align-items: center; justify-content: center; gap: 8px; color: var(--el-text-color-secondary); text-align: center; }.exception-icon { width: 52px; height: 52px; margin-bottom: 5px; background: var(--el-color-success-light-9); color: var(--el-color-success); font-size: 26px; }.exception-empty strong { color: var(--el-text-color-primary); font-size: 14px; }.exception-empty span { max-width: 230px; font-size: 12px; line-height: 1.6; }
@media (max-width: 1280px) { .kpi-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }.quick-action-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }.activity-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }.activity-card:last-child { grid-column: span 2; } } @media (max-width: 1280px) { .kpi-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }.quick-action-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }.activity-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }.activity-card:last-child { grid-column: span 2; } }
@media (max-width: 900px) { .dashboard-page { padding: 16px; }.dashboard-header { align-items: flex-start; flex-direction: column; }.dashboard-header-actions { align-items: flex-start; flex-direction: row; flex-wrap: wrap; }.chart-grid, .operational-grid { grid-template-columns: 1fr; } } @media (max-width: 900px) { .dashboard-page { padding: 16px; }.chart-grid, .operational-grid { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .dashboard-header h1 { font-size: 22px; }.dashboard-header-actions, .dashboard-meta { align-items: flex-start; flex-direction: column; }.dashboard-meta { gap: 6px; }.kpi-grid, .quick-action-grid, .activity-grid { grid-template-columns: 1fr; }.activity-card:last-child { grid-column: auto; }.quick-action { min-height: 54px; }.dashboard-alert { align-items: flex-start; flex-wrap: wrap; }.dashboard-alert .el-button { margin-left: 0; } } @media (max-width: 640px) { .kpi-grid, .quick-action-grid, .activity-grid { grid-template-columns: 1fr; }.activity-card:last-child { grid-column: auto; }.quick-action { min-height: 54px; }.trend-range-select { width: 104px; }.dashboard-alert { align-items: flex-start; flex-wrap: wrap; }.dashboard-alert .el-button { margin-left: 0; } }
</style> </style>
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container master-page"> <div class="app-container master-page">
<el-form ref="queryRef" class="master-query page-filter" :model="queryParams" :inline="true"> <el-form ref="queryRef" v-show="showSearch" class="master-query page-filter" :model="queryParams" :inline="true">
<el-form-item label="客户编码" prop="customerCode"> <el-form-item label="客户编码" prop="customerCode">
<el-input v-model="queryParams.customerCode" placeholder="请输入客户编码" clearable maxlength="64" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.customerCode" placeholder="请输入客户编码" clearable maxlength="64" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
@@ -18,18 +18,21 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row v-if="isMasterWriteAllowed" :gutter="10" class="mb8 master-toolbar"> <el-row :gutter="10" class="mb8 master-toolbar">
<el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:customer:add']">新增</el-button></el-col> <template v-if="isMasterWriteAllowed">
<el-col :span="1.5"> <el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:customer:add']">新增</el-button></el-col>
<el-button <el-col :span="1.5">
v-if="proxy.$auth.hasPermiAnd(['master:customer:query', 'master:customer:edit'])" <el-button
type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading" v-if="proxy.$auth.hasPermiAnd(['master:customer:query', 'master:customer:edit'])"
@click="handleUpdate()" v-hasPermi="['master:customer:edit']" type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading"
>修改</el-button> @click="handleUpdate()" v-hasPermi="['master:customer:edit']"
</el-col> >修改</el-button>
</el-row> </el-col>
<el-row v-if="userStore.admin === true && !testBatchStore.isTestMode" :gutter="10" class="mb8 master-toolbar"> <el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-col :span="1.5"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></el-col> <el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</template>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
@@ -101,7 +104,8 @@
<style scoped> <style scoped>
.master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; } .master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; }
.master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-form-item) { margin-right:0; width:100%; }
.master-query :deep(.el-input), .master-query :deep(.el-select) { width:100% !important; } .master-query :deep(.el-form-item__content) { flex:1; min-width:0; }
.master-query :deep(.el-input), .master-query :deep(.el-input-number), .master-query :deep(.el-select) { width:100% !important; min-width:0; }
.master-query :deep(.el-form-item:last-child) { align-self:end; } .master-query :deep(.el-form-item:last-child) { align-self:end; }
.master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar { display:flex; flex-wrap:wrap; gap:8px; }
.master-toolbar :deep(.el-col) { width:auto; } .master-toolbar :deep(.el-col) { width:auto; }
@@ -124,6 +128,7 @@ const isMasterWriteAllowed = computed(() => userStore.admin === true || !testBat
const adoptionDialogRef = ref() const adoptionDialogRef = ref()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable"); const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const customerList = ref([]); const customerList = ref([]);
const showSearch = ref(true);
const selectedIds = ref([]); const selectedIds = ref([]);
const loading = ref(false); const loading = ref(false);
const detailLoading = ref(false); const detailLoading = ref(false);
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container master-page"> <div class="app-container master-page">
<el-form ref="queryRef" class="master-query page-filter" :model="queryParams" :inline="true"> <el-form ref="queryRef" v-show="showSearch" class="master-query page-filter" :model="queryParams" :inline="true">
<el-form-item label="现场ID" prop="siteId"> <el-form-item label="现场ID" prop="siteId">
<el-input-number v-model="queryParams.siteId" :min="1" :step="1" step-strictly controls-position="right" placeholder="请输入现场ID" /> <el-input-number v-model="queryParams.siteId" :min="1" :step="1" step-strictly controls-position="right" placeholder="请输入现场ID" />
</el-form-item> </el-form-item>
@@ -21,18 +21,21 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row v-if="isMasterWriteAllowed" :gutter="10" class="mb8 master-toolbar"> <el-row :gutter="10" class="mb8 master-toolbar">
<el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:line:add']">新增</el-button></el-col> <template v-if="isMasterWriteAllowed">
<el-col :span="1.5"> <el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:line:add']">新增</el-button></el-col>
<el-button <el-col :span="1.5">
v-if="proxy.$auth.hasPermiAnd(['master:line:query', 'master:line:edit'])" <el-button
type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading" v-if="proxy.$auth.hasPermiAnd(['master:line:query', 'master:line:edit'])"
@click="handleUpdate()" v-hasPermi="['master:line:edit']" type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading"
>修改</el-button> @click="handleUpdate()" v-hasPermi="['master:line:edit']"
</el-col> >修改</el-button>
</el-row> </el-col>
<el-row v-if="userStore.admin === true && !testBatchStore.isTestMode" :gutter="10" class="mb8 master-toolbar"> <el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-col :span="1.5"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></el-col> <el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</template>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
@@ -107,7 +110,7 @@
<style scoped> <style scoped>
.master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; } .master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; }
.master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-input), .master-query :deep(.el-select) { width:100% !important; } .master-query :deep(.el-form-item:last-child) { align-self:end; } .master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-form-item__content) { flex:1; min-width:0; } .master-query :deep(.el-input), .master-query :deep(.el-input-number), .master-query :deep(.el-select) { width:100% !important; min-width:0; } .master-query :deep(.el-form-item:last-child) { align-self:end; }
.master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; } .master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; }
.master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); } .master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); }
@media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } } @media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } }
@@ -126,6 +129,7 @@ const isMasterWriteAllowed = computed(() => userStore.admin === true || !testBat
const adoptionDialogRef = ref() const adoptionDialogRef = ref()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable"); const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const lineList = ref([]); const lineList = ref([]);
const showSearch = ref(true);
const selectedIds = ref([]); const selectedIds = ref([]);
const loading = ref(false); const loading = ref(false);
const detailLoading = ref(false); const detailLoading = ref(false);
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container master-page"> <div class="app-container master-page">
<el-form ref="queryRef" class="master-query page-filter" :model="queryParams" :inline="true"> <el-form ref="queryRef" v-show="showSearch" class="master-query page-filter" :model="queryParams" :inline="true">
<el-form-item label="托盘编码" prop="palletCode"> <el-form-item label="托盘编码" prop="palletCode">
<el-input v-model="queryParams.palletCode" placeholder="请输入托盘编码" clearable maxlength="64" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.palletCode" placeholder="请输入托盘编码" clearable maxlength="64" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
@@ -15,18 +15,21 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row v-if="isMasterWriteAllowed" :gutter="10" class="mb8 master-toolbar"> <el-row :gutter="10" class="mb8 master-toolbar">
<el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:pallet:add']">新增</el-button></el-col> <template v-if="isMasterWriteAllowed">
<el-col :span="1.5"> <el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:pallet:add']">新增</el-button></el-col>
<el-button <el-col :span="1.5">
v-if="proxy.$auth.hasPermiAnd(['master:pallet:query', 'master:pallet:edit'])" <el-button
type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading" v-if="proxy.$auth.hasPermiAnd(['master:pallet:query', 'master:pallet:edit'])"
@click="handleUpdate()" v-hasPermi="['master:pallet:edit']" type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading"
>修改</el-button> @click="handleUpdate()" v-hasPermi="['master:pallet:edit']"
</el-col> >修改</el-button>
</el-row> </el-col>
<el-row v-if="userStore.admin === true && !testBatchStore.isTestMode" :gutter="10" class="mb8 master-toolbar"> <el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-col :span="1.5"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></el-col> <el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</template>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
@@ -107,7 +110,7 @@
<style scoped> <style scoped>
.master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; } .master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; }
.master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-input), .master-query :deep(.el-select) { width:100% !important; } .master-query :deep(.el-form-item:last-child) { align-self:end; } .master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-form-item__content) { flex:1; min-width:0; } .master-query :deep(.el-input), .master-query :deep(.el-input-number), .master-query :deep(.el-select) { width:100% !important; min-width:0; } .master-query :deep(.el-form-item:last-child) { align-self:end; }
.master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; } .master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; }
.master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); } .master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); }
@media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } } @media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } }
@@ -126,6 +129,7 @@ const isMasterWriteAllowed = computed(() => userStore.admin === true || !testBat
const adoptionDialogRef = ref() const adoptionDialogRef = ref()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable"); const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const palletList = ref([]); const palletList = ref([]);
const showSearch = ref(true);
const selectedIds = ref([]); const selectedIds = ref([]);
const loading = ref(false); const loading = ref(false);
const detailLoading = ref(false); const detailLoading = ref(false);
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container master-page"> <div class="app-container master-page">
<el-form ref="queryRef" class="master-query page-filter" :model="queryParams" :inline="true"> <el-form ref="queryRef" v-show="showSearch" class="master-query page-filter" :model="queryParams" :inline="true">
<el-form-item label="客户ID" prop="customerId"> <el-form-item label="客户ID" prop="customerId">
<el-input-number v-model="queryParams.customerId" :min="1" :step="1" step-strictly controls-position="right" placeholder="请输入客户ID" /> <el-input-number v-model="queryParams.customerId" :min="1" :step="1" step-strictly controls-position="right" placeholder="请输入客户ID" />
</el-form-item> </el-form-item>
@@ -21,19 +21,22 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row v-if="isMasterWriteAllowed" :gutter="10" class="mb8 master-toolbar"> <el-row :gutter="10" class="mb8 master-toolbar">
<el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:site:add']">新增</el-button></el-col> <template v-if="isMasterWriteAllowed">
<el-col :span="1.5"> <el-col :span="1.5"><el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:site:add']">新增</el-button></el-col>
<el-button <el-col :span="1.5">
v-if="proxy.$auth.hasPermiAnd(['master:site:query', 'master:site:edit'])" <el-button
type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading" v-if="proxy.$auth.hasPermiAnd(['master:site:query', 'master:site:edit'])"
@click="handleUpdate()" v-hasPermi="['master:site:edit']" type="success" plain icon="Edit" :disabled="single || detailLoading" :loading="detailLoading"
>修改</el-button> @click="handleUpdate()" v-hasPermi="['master:site:edit']"
</el-col> >修改</el-button>
<el-col :span="1.5"><el-button type="warning" plain icon="User" :disabled="single" @click="handleAssign()" v-hasPermi="['master:site:assign']">分配用户</el-button></el-col> </el-col>
</el-row> <el-col :span="1.5"><el-button type="warning" plain icon="User" :disabled="single" @click="handleAssign()" v-hasPermi="['master:site:assign']">分配用户</el-button></el-col>
<el-row v-if="userStore.admin === true && !testBatchStore.isTestMode" :gutter="10" class="mb8 master-toolbar"> <el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-col :span="1.5"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></el-col> <el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</template>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
@@ -115,7 +118,7 @@
<style scoped> <style scoped>
.master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; } .master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; }
.master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-input), .master-query :deep(.el-select) { width:100% !important; } .master-query :deep(.el-form-item:last-child) { align-self:end; } .master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-form-item__content) { flex:1; min-width:0; } .master-query :deep(.el-input), .master-query :deep(.el-input-number), .master-query :deep(.el-select) { width:100% !important; min-width:0; } .master-query :deep(.el-form-item:last-child) { align-self:end; }
.master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; } .master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; }
.master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); } .master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); }
@media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } } @media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } }
@@ -135,6 +138,7 @@ const isMasterWriteAllowed = computed(() => userStore.admin === true || !testBat
const adoptionDialogRef = ref() const adoptionDialogRef = ref()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable"); const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const siteList = ref([]); const siteList = ref([]);
const showSearch = ref(true);
const selectedIds = ref([]); const selectedIds = ref([]);
const selectedRows = ref([]); const selectedRows = ref([]);
const assignDialogRef = ref(); const assignDialogRef = ref();
@@ -1,6 +1,6 @@
<template> <template>
<div class="app-container master-page"> <div class="app-container master-page">
<el-form ref="queryRef" class="master-query page-filter" :model="queryParams" :inline="true"> <el-form ref="queryRef" v-show="showSearch" class="master-query page-filter" :model="queryParams" :inline="true">
<el-form-item label="菌种编码" prop="strainCode"> <el-form-item label="菌种编码" prop="strainCode">
<el-input v-model="queryParams.strainCode" placeholder="请输入菌种编码" clearable maxlength="64" @keyup.enter="handleQuery" /> <el-input v-model="queryParams.strainCode" placeholder="请输入菌种编码" clearable maxlength="64" @keyup.enter="handleQuery" />
</el-form-item> </el-form-item>
@@ -18,25 +18,28 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<el-row v-if="isMasterWriteAllowed" :gutter="10" class="mb8 master-toolbar"> <el-row :gutter="10" class="mb8 master-toolbar">
<el-col :span="1.5"> <template v-if="isMasterWriteAllowed">
<el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:strain:add']">新增</el-button> <el-col :span="1.5">
</el-col> <el-button type="primary" plain icon="Plus" @click="handleAdd" v-hasPermi="['master:strain:add']">新增</el-button>
<el-col :span="1.5"> </el-col>
<el-button <el-col :span="1.5">
v-if="proxy.$auth.hasPermiAnd(['master:strain:query', 'master:strain:edit'])" <el-button
type="success" v-if="proxy.$auth.hasPermiAnd(['master:strain:query', 'master:strain:edit'])"
plain type="success"
icon="Edit" plain
:disabled="single || detailLoading" icon="Edit"
:loading="detailLoading" :disabled="single || detailLoading"
@click="handleUpdate()" :loading="detailLoading"
v-hasPermi="['master:strain:edit']" @click="handleUpdate()"
>修改</el-button> v-hasPermi="['master:strain:edit']"
</el-col> >修改</el-button>
</el-row> </el-col>
<el-row v-if="userStore.admin === true && !testBatchStore.isTestMode" :gutter="10" class="mb8 master-toolbar"> <el-col v-if="userStore.admin === true && !testBatchStore.isTestMode" :span="1.5">
<el-col :span="1.5"><el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button></el-col> <el-button type="warning" plain icon="FolderAdd" :disabled="!selectedIds.length" @click="openAdoptionDialog" v-hasPermi="['system:testbatch:adopt']">纳入测试批次</el-button>
</el-col>
</template>
<right-toolbar v-model:showSearch="showSearch" @queryTable="getList" />
</el-row> </el-row>
<el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" /> <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" show-icon class="mb8" />
@@ -118,7 +121,7 @@
<style scoped> <style scoped>
.master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; } .master-query { display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:0 14px; padding:16px 18px 4px; margin-bottom:14px; background:var(--el-bg-color); border:1px solid var(--el-border-color-lighter); border-radius:8px; }
.master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-input), .master-query :deep(.el-select) { width:100% !important; } .master-query :deep(.el-form-item:last-child) { align-self:end; } .master-query :deep(.el-form-item) { margin-right:0; width:100%; } .master-query :deep(.el-form-item__content) { flex:1; min-width:0; } .master-query :deep(.el-input), .master-query :deep(.el-input-number), .master-query :deep(.el-select) { width:100% !important; min-width:0; } .master-query :deep(.el-form-item:last-child) { align-self:end; }
.master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; } .master-toolbar { display:flex; flex-wrap:wrap; gap:8px; } .master-toolbar :deep(.el-col) { width:auto; }
.master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); } .master-table :deep(.el-table__header th) { background:var(--el-fill-color-light); font-weight:600; } .master-table :deep(.el-table__cell) { padding:10px 0; } .master-table :deep(.fixed-width) { position:sticky; right:0; z-index:2; background:var(--el-bg-color); box-shadow:-4px 0 8px rgba(0,0,0,.04); }
@media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } } @media (max-width:768px) { .master-query { grid-template-columns:1fr; padding:14px 14px 2px; } .master-query :deep(.el-form-item:last-child) { margin-bottom:12px; } .master-toolbar :deep(.el-button) { margin-left:0; } }
@@ -138,6 +141,7 @@ const adoptionDialogRef = ref()
const { sys_normal_disable } = proxy.useDict("sys_normal_disable"); const { sys_normal_disable } = proxy.useDict("sys_normal_disable");
const strainList = ref([]); const strainList = ref([]);
const showSearch = ref(true);
const selectedIds = ref([]); const selectedIds = ref([]);
const loading = ref(false); const loading = ref(false);
const detailLoading = ref(false); const detailLoading = ref(false);

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