配置中文改造 + 数据库技能集成

- AGENTS.md/USER.md/TOOLS.md 改造为中文
- 添加 mica 项目 MySQL 数据库配置 (47.99.209.185:50036)
- 集成 sql-toolkit 技能使用说明
- 集成 qiushi-openclaw-skill 系统化思考框架
- 创建 memory/2026-08-03.md 记录今日配置工作
- .gitignore 添加 .env 忽略规则
- 清理过期的 memory 文件和 tasks 文件
This commit is contained in:
杨轩
2026-08-03 16:32:53 +08:00
parent cb7079006e
commit 4637b17ca9
66 changed files with 3242 additions and 2960 deletions
+405
View File
@@ -0,0 +1,405 @@
{
"version": 1,
"skills": {
"sql-toolkit": {
"version": "1.0.0",
"installedAt": 1785744535727,
"registry": "https://clawhub.ai",
"ownerHandle": "gitgoodordietrying",
"artifact": {
"kind": "archive",
"sha256": "4f48da99f3b1beb878195590b3ed1c6a469ce554498831abdee42ca27468959f",
"integrity": "sha256-T0jamfOxvrh4GVWQs+0cakac5VRJiDGr3uQsonRolZ8="
},
"skillFile": {
"path": "SKILL.md",
"sha256": "515ecf904449a3cd5ebb92e85e54127e216d9483ee9111705e75e686a0694285"
},
"verification": {
"schema": "clawhub.skill.verify.v1",
"ok": true,
"decision": "pass",
"reasons": [],
"card": {
"available": true,
"path": "skill-card.md",
"url": "https://wry-manatee-359.convex.site/api/v1/skills/sql-toolkit/card?ownerHandle=gitgoodordietrying&version=1.0.0",
"sha256": "ecf10f8b45e67a00ae6b5c6ef5438feb44cd33f505666b4362c506172d39848d",
"size": 1998,
"contentType": "text/markdown; charset=utf-8"
},
"artifact": {
"sourceFingerprint": "d90603335b0cc1e00d6da8eac9e1345d52453b894578bd2e8590fa20b1475484",
"bundleFingerprints": [
"b99edda9c4d7b4e0a78f172715644da5955da8bad18563789b4903f734c0baa2"
],
"files": [
{
"path": "SKILL.md",
"size": 12080,
"sha256": "515ecf904449a3cd5ebb92e85e54127e216d9483ee9111705e75e686a0694285",
"contentType": "text/markdown"
}
]
},
"provenance": {
"source": "unavailable",
"reason": "No server-resolved GitHub import provenance is stored for this version."
},
"security": {
"status": "clean",
"passed": true,
"rawStatus": "clean",
"verdict": "benign",
"confidence": "high",
"summary": "This SQL helper skill is purpose-aligned documentation for database command-line workflows, with no evidence of hidden behavior or malicious activity, but users should be careful with restore examples that can overwrite data.",
"model": "gpt-5.5",
"checkedAt": 1783656186394,
"signals": {
"staticScan": {
"status": "clean",
"rawStatus": "clean",
"reasonCodes": [],
"summary": "No suspicious patterns detected.",
"engineVersion": "v2.4.5",
"checkedAt": 1777524980775
},
"virusTotal": {
"status": "clean",
"rawStatus": "clean",
"verdict": "benign",
"analysis": "Type: OpenClaw Skill\nName: sql-toolkit\nVersion: 1.0.0\n\nThe skill bundle is benign. It provides comprehensive documentation and examples for interacting with SQL databases (SQLite, PostgreSQL, MySQL) using standard command-line tools. While the skill inherently involves powerful commands with file system and network access (e.g., `psql`, `mysql`, `sqlite3`, `pg_dump`, `mysqldump`), all examples and instructions in `SKILL.md` are aligned with the stated purpose of a 'SQL Toolkit' and demonstrate legitimate, common database operations. There is no evidence of prompt injection, data exfiltration, malicious execution, persistence, or obfuscation.",
"source": "palm",
"scanner": "code_insight",
"engineStats": {
"harmless": 0,
"malicious": 0,
"suspicious": 0,
"undetected": 64
},
"checkedAt": 1779161171837
},
"skillSpector": {
"status": "clean",
"rawStatus": "clean",
"score": 8,
"severity": "LOW",
"recommendation": "SAFE",
"issueCount": 1,
"scannerVersion": "2.3.5",
"summary": null,
"error": null,
"checkedAt": 1783656142755
},
"dependencyRegistry": null
}
},
"signature": {
"status": "unsigned"
}
}
},
"qiushi-openclaw-skill": {
"version": "1.0.0",
"installedAt": 1785745381570,
"registry": "https://clawhub.ai",
"ownerHandle": "skytodmoon",
"artifact": {
"kind": "archive",
"sha256": "1e2d3712d2974143449c9e47b0379725a954794c498727799f782ac7b1db7a49",
"integrity": "sha256-Hi03EtKXQUNEnJ5HsDeXJalUeUxJhyd5n3gqx7Hbekk="
},
"skillFile": {
"path": "SKILL.md",
"sha256": "b21d933b7f61584d2254fba25fd531c16f19e33e10016ddfbdea1a5e2d5d6d25"
},
"verification": {
"schema": "clawhub.skill.verify.v1",
"ok": true,
"decision": "pass",
"reasons": [],
"card": {
"available": true,
"path": "skill-card.md",
"url": "https://wry-manatee-359.convex.site/api/v1/skills/qiushi-openclaw-skill/card?ownerHandle=skytodmoon&version=1.0.0",
"sha256": "7ffcf0eaab78e22dc18592df90bce922535f9ce092c53c3a68f5d020f698e081",
"size": 2044,
"contentType": "text/markdown; charset=utf-8"
},
"artifact": {
"sourceFingerprint": "1d39ab4575f3ffec359865c03bed700ee3426f57f61d9fa9dad153fc60e5a3ae",
"bundleFingerprints": [
"8864f859b5a5b919d08ed0da8d37a79d4e5276ffd32a564ebe650f637423e296"
],
"files": [
{
"path": "README.md",
"size": 3652,
"sha256": "3454e7472626a033616d7d9f89c0ecf6b11aa5172774f0c07bca694c9d115f1f",
"contentType": "text/x-markdown"
},
{
"path": "SKILL.md",
"size": 2385,
"sha256": "b21d933b7f61584d2254fba25fd531c16f19e33e10016ddfbdea1a5e2d5d6d25",
"contentType": "text/x-markdown"
},
{
"path": "investigation-first/clawhub.json",
"size": 387,
"sha256": "48159dc63edec35d2ea36df30cb028bc89d5adf7e873e0bbd98c2b559b72d04b",
"contentType": "application/json"
},
{
"path": "investigation-first/README.md",
"size": 2766,
"sha256": "edc308afbcffb36f40f9e925e13dcc24f7c8b361af3a7c7c45af80f76cc96c3e",
"contentType": "text/x-markdown"
},
{
"path": "investigation-first/SKILL.md",
"size": 2309,
"sha256": "101212ce1723aaf92f7503b77fff35edbcccf22830dbe2f0f43cb995c166da2d",
"contentType": "text/x-markdown"
},
{
"path": "practice-cognition/clawhub.json",
"size": 380,
"sha256": "68bf1d476a88950059cb7dc52e78dee5583f7114472237bb2824d190119e9add",
"contentType": "application/json"
},
{
"path": "practice-cognition/README.md",
"size": 2659,
"sha256": "addd5a3c69d8559e659f507127877823727e03cdec2da0346c4a5dae4306b1bb",
"contentType": "text/x-markdown"
},
{
"path": "practice-cognition/SKILL.md",
"size": 2457,
"sha256": "204872d8135301e2ed07b696ef63dbe4081cce1ed3235221843fd4f97a0f42e9",
"contentType": "text/x-markdown"
},
{
"path": "concentrate-forces/clawhub.json",
"size": 380,
"sha256": "683dc297ed5d0f8a0b223f543fe54d445e8ebcaa39cd65d59cdca07e843f772c",
"contentType": "application/json"
},
{
"path": "concentrate-forces/README.md",
"size": 2731,
"sha256": "1666b93bcfdf78520b492bc196a901d465ce637c7d3b08520163a5f0609ff962",
"contentType": "text/x-markdown"
},
{
"path": "concentrate-forces/SKILL.md",
"size": 2253,
"sha256": "207b28f78ecb81d7c54f2ac8c6b3cdd58b4e10775a8e92f2f026bc3310d6f123",
"contentType": "text/x-markdown"
},
{
"path": "contradiction-analysis/clawhub.json",
"size": 423,
"sha256": "ef00074e7841d1698c0f0ea74c9e9dfc9e0923452e3d1475216bf945f147fd80",
"contentType": "application/json"
},
{
"path": "contradiction-analysis/README.md",
"size": 3012,
"sha256": "b4eeae7b315e024bf2c9f49d388d627cf2b0c3304d92d449f0c86abc3ee8d4b4",
"contentType": "text/x-markdown"
},
{
"path": "contradiction-analysis/SKILL.md",
"size": 2919,
"sha256": "1fd24138f9ab3b4bab002a771978356c673c24c7a5dce6c7acb37dc271dcd385",
"contentType": "text/x-markdown"
},
{
"path": "mass-line/clawhub.json",
"size": 356,
"sha256": "bac70025aedd0465607cbca72996bdf705a7d3a75c50bcc5da29c18147dee980",
"contentType": "application/json"
},
{
"path": "mass-line/README.md",
"size": 2632,
"sha256": "1c3c76199aa50ec1eca70b0463c42e09227777265a74e9f4b487483a8c5b5307",
"contentType": "text/x-markdown"
},
{
"path": "mass-line/SKILL.md",
"size": 2169,
"sha256": "f215fdf997b02cf314b6ba0e03e2425aae20904f55c4ce7734dcc8c32f64b78e",
"contentType": "text/x-markdown"
},
{
"path": "protracted-strategy/clawhub.json",
"size": 372,
"sha256": "5f54232101b8b48a38452b9cf69f9824914bb834cb03f06f4c0afc59429947dc",
"contentType": "application/json"
},
{
"path": "protracted-strategy/README.md",
"size": 2954,
"sha256": "d92f25b8ebfd8cd8999e56dbf79727e96f6c1502860dd2f37138795bea65e40e",
"contentType": "text/x-markdown"
},
{
"path": "protracted-strategy/SKILL.md",
"size": 2418,
"sha256": "7a69b073927a7426a01dc8e2979297f9a9b90f7b450e853bf2b877fb174422d2",
"contentType": "text/x-markdown"
},
{
"path": "workflows/clawhub.json",
"size": 392,
"sha256": "77497954f506f25351f35cf4e541a2e533501056ce7418b434ee24c6b9438ca4",
"contentType": "application/json"
},
{
"path": "workflows/README.md",
"size": 2871,
"sha256": "5b16dd2a4d5093494ace5d201c85d7cfd5e3409a93cb50176e269a987e0a7bc9",
"contentType": "text/x-markdown"
},
{
"path": "workflows/SKILL.md",
"size": 2448,
"sha256": "183fd3caa21f6ff5ebc9e725b59f4a0be3d83e5fdeb8587eb6d0b22859b768b1",
"contentType": "text/x-markdown"
},
{
"path": "overall-planning/clawhub.json",
"size": 363,
"sha256": "1e4a7014f0745993be50e1dd2813af364592e6cfbd87b68456c46543b6fc9797",
"contentType": "application/json"
},
{
"path": "overall-planning/README.md",
"size": 2912,
"sha256": "68c2f97a23befb87a11c612d862c0a77b5544a2cd8cd4e1f8bd2ba91c3eb9620",
"contentType": "text/x-markdown"
},
{
"path": "overall-planning/SKILL.md",
"size": 2403,
"sha256": "b3fdc6991bc211c2e83981e7ce53facfa1014cb7325452826cfc22ce056e36af",
"contentType": "text/x-markdown"
},
{
"path": "spark-prairie-fire/clawhub.json",
"size": 383,
"sha256": "17981f22cf824e28c2d770bcc21c9aa5087476326004eaae138b96a7b4fc4eae",
"contentType": "application/json"
},
{
"path": "spark-prairie-fire/README.md",
"size": 2710,
"sha256": "06a95aeafad95d606a742e4b99cb8ad257aeb65321305d318bbbf9b324299e63",
"contentType": "text/x-markdown"
},
{
"path": "spark-prairie-fire/SKILL.md",
"size": 2232,
"sha256": "e0eac250f3046cfcd8cdd95c3bd780ccefe7e9efbcb62de0a73f80986e78b2a8",
"contentType": "text/x-markdown"
},
{
"path": "arming-thought/clawhub.json",
"size": 450,
"sha256": "0a7cc0fb2129be03444e2fec5e8fb505cfcadbe2ed58ebef1fc37aaed28a0211",
"contentType": "application/json"
},
{
"path": "arming-thought/README.md",
"size": 1955,
"sha256": "6f1d3d9a0abcd5ad8fc90a1e0d18207d7e97ab53d947894aef049adf8807bdb2",
"contentType": "text/x-markdown"
},
{
"path": "arming-thought/SKILL.md",
"size": 2271,
"sha256": "6fa2855bcb06d1a136d916c9a07124dbd50adaac75b8037c86882b4c6c430735",
"contentType": "text/x-markdown"
},
{
"path": "criticism-self-criticism/clawhub.json",
"size": 407,
"sha256": "eda46316ce74edbf78c7210005d2785f1c2dbe7c0e8ae6809adb8f75a5e90e41",
"contentType": "application/json"
},
{
"path": "criticism-self-criticism/README.md",
"size": 2811,
"sha256": "d90d58b4e5707bdf4635aa85e147422bf8d18d79b3c4d24864f4f3fa7d7ad3e3",
"contentType": "text/x-markdown"
},
{
"path": "criticism-self-criticism/SKILL.md",
"size": 2369,
"sha256": "1f01760dbdffa7cd5acb95365e7866692d72c89061ed2240a05bbe1056794002",
"contentType": "text/x-markdown"
}
]
},
"provenance": {
"source": "unavailable",
"reason": "No server-resolved GitHub import provenance is stored for this version."
},
"security": {
"status": "clean",
"passed": true,
"rawStatus": "clean",
"verdict": "benign",
"confidence": "high",
"summary": "This is a disclosed Chinese-language methodology skill pack that guides reasoning and planning without requesting tools, credentials, file access, network access, or persistence.",
"model": "gpt-5.5",
"checkedAt": 1779973863935,
"signals": {
"staticScan": {
"status": "clean",
"rawStatus": "clean",
"reasonCodes": [],
"summary": "No suspicious patterns detected.",
"engineVersion": "v2.4.5",
"checkedAt": 1777527313505
},
"virusTotal": {
"status": "clean",
"rawStatus": "clean",
"verdict": null,
"analysis": null,
"source": "engines",
"scanner": null,
"engineStats": {
"harmless": 0,
"malicious": 0,
"suspicious": 0,
"undetected": 65
},
"checkedAt": 1780086996288
},
"skillSpector": {
"status": "suspicious",
"rawStatus": "suspicious",
"score": 100,
"severity": "CRITICAL",
"recommendation": "DO_NOT_INSTALL",
"issueCount": 16,
"scannerVersion": "2.0.0",
"summary": null,
"error": null,
"checkedAt": 1779973821578
},
"dependencyRegistry": null
}
},
"signature": {
"status": "unsigned"
}
}
}
}
}
+21
View File
@@ -23,3 +23,24 @@
## 项目别名
- `wit``/root/projects/wit`(前端 mica-web / 后端 mica-server / 文档 mica-doc
## mica 项目数据库配置
**连接信息:**
- 主机:`47.99.209.185:50036`
- 用户:`witsoftd`
- 密码:见密码管理器
**数据库列表:**
| 数据库 | 用途 |
|--------|------|
| `dmp_serp` | ERP 相关 |
| `dmp_smdm` | 主数据管理 |
| `dmp_smes` | 制造执行系统 |
| `dmp_spom` | 订单管理 |
| `dmp_secm` | 安全管理 |
| `dmp_sportal` | 门户系统 |
**相关系统:** `witdmp_edge/scheduler/workflow``witdn_lcdp/server``witprint``nacos_k8s``tenant`
**技能:** sql-toolkit`/root/.openclaw/workspace-backend/skills/sql-toolkit/SKILL.md`
-88
View File
@@ -1,88 +0,0 @@
# 2026-05-23 会话记忆
## 项目:tiny-erp
### 核心决策
1. **包路径确定**`com.witsoft.erp`(不是 com.example 或 com.witsoft.tinyerp
- tiny 是项目别名,包名使用正式名称 erp
2. **技术栈确认**
- JDK 11+(不是 1.8
- Spring Boot 2.7.18
- MyBatis Plus 3.5.3.1
- PostgreSQL 14+
- Spring Security + JWT (jjwt 0.11.5)
- SpringDoc OpenAPI 3(不是 Knife4j
3. **多租户方案**ecid 字段隔离 + TenantLineHandler 自动拦截
- 系统表(sys_*)不进行租户隔离(登录时需要查询)
- 业务表全部需要 ecid 隔离
- **所有表的 ecid 字段为 NOT NULL**
4. **API 设计规范**
- 分页列表接口使用 POST(不是 GET)
- 请求体携带查询条件 + 分页参数
- 统一返回格式:{code, message, data}
5. **异常处理规范**
- BusinessException 支持自定义错误码
- GlobalExceptionHandler 统一处理各类异常
- 参数校验失败返回 400 + 具体错误信息
6. **模块命名**:基础数据模块(bd)替代主数据模块(md)
### 已完成模块
| 模块 | 功能 | 状态 |
|------|------|------|
| system | 租户、用户、字典、JWT 认证 | ✅ |
| bd | 物料分类、工厂、仓库、物料 | ✅ |
| om | 销售订单、发货单(含库存扣减) | ✅ |
| mc | 采购订单 | ✅ |
| im | 库存查询、库存流水 | ✅ |
### 数据库脚本结构
```
scripts/postgresql/
├── 00-init.sql # 数据库初始化
├── 10-system.sql # 系统模块
├── 20-basic-data.sql # 基础数据模块
├── 30-sales.sql # 销售模块
├── 40-purchase.sql # 采购模块
├── 50-inventory.sql # 库存模块
└── 99-data.sql # 初始化数据
```
### 默认账号
- admin / admin123 / default
- test / admin123 / default
### 待开发功能
1. 采购收货单 + 库存增加(P0
2. 销售退货单(P1
3. 采购申请单(P1
4. 库存调拨(P1
5. 库存盘点(P1
6. 操作日志、登录日志(P1/P2
7. 报表统计(P2
### 关键代码位置
- JWT 工具:`framework/security/JwtUtil.java`
- 租户上下文:`framework/tenant/TenantContext.java`
- 租户拦截器:`framework/tenant/TenantLineHandlerImpl.java`
- 全局异常:`common/core/GlobalExceptionHandler.java`
- 业务异常:`common/core/BusinessException.java`
### 文档位置
- README.md:项目根目录
- 开发方案:`yangxuan/设计/01-开发方案.md`
---
> ⚠️ 2026-05-26: 当前只关注 md(主数据)和 im(库存)模块。om/mc/fin/system/home 代码已存在但不再关注。
-517
View File
@@ -1,517 +0,0 @@
# 2026-05-25 会话记录
## 系统模块开发(2026-05-25 13:28
### 完成的工作
1. **操作日志功能**
- 实体类:`OperLog.java`
- Mapper`OperLogMapper.java`
- Service`OperLogService.java` + `OperLogServiceImpl.java`
- Controller`OperLogController.java`
- 切面:`LogAspect.java`(自动记录带@Log 注解的方法)
- 注解:`@Log`module、businessType、isSaveRequestData、isSaveResponseData
2. **数据字典增强**
- 新增方法:`listDataBatch()` - 批量获取字典数据
- 新增方法:`listOptions()` - 前端下拉框格式 [{label, value}]
- 新增方法:`listOptionsBatch()` - 批量获取下拉框选项
- 新增接口:`GET /system/dict/data/options/batch?dictTypes=xxx,yyy`
3. **文档**
- `04-系统模块开发指南.md` - 包含使用示例、API 文档、前端集成示例
### 业务类型枚举
| 值 | 含义 |
|----|------|
| 0 | 其它 |
| 1 | 新增 |
| 2 | 修改 |
| 3 | 删除 |
| 4 | 导出 |
| 5 | 导入 |
| 6 | 审核 |
### 已初始化字典
- `inbound_type` - 入库类型(采购入库、退货入库、其他入库)
- `outbound_type` - 出库类型(销售出库、领料出库、其他出库)
- `stocktake_diff_result` - 盘点结果(相符、盘盈、盘亏)
- `payment_method` - 收付款方式(现金、银行转账、承兑汇票)
### 下一步
- 主数据模块开发(供应商、客户) ✓
- 库存模块开发(入库单、出库单) ✓
- 财务模块开发(应收、应付、收款、付款)
- 首页模块开发 ✓
---
## 首页模块开发(2026-05-25 15:15
### 完成的工作
1. **欢迎信息接口**
- `GET /home/welcome` - 返回欢迎语、用户名、企业名、日期、问候语
- 根据时间段自动切换问候语(早上好/中午好/下午好/晚上好/夜深了)
- DTO`HomeWelcomeResDTO.java`
2. **最新动态接口**
- `GET /home/news` - 返回最近 20 条业务动态
- 动态类型:入库完成、出库完成、盘点完成、新增供应商、新增客户
- 按时间倒序排列
- DTO`HomeNewsItemDTO.java`
3. **文件清单**
- `HomeController.java` - 首页控制器
- `HomeService.java` / `HomeServiceImpl.java` - 首页服务
- `HomeWelcomeResDTO.java` - 欢迎信息响应
- `HomeNewsItemDTO.java` - 动态项 DTO
### API 示例
```http
GET /home/welcome
{ welcome: "", userName: "", companyName: "", greeting: "" }
GET /home/news
[ { type: "inbound", title: "", content: "RK202605250001 - ", operator: "", operateTime: "..." } ]
```
### TODO
- 从用户会话/配置中获取真实用户名和企业名(当前为默认值)
---
## 库存模块增强(2026-05-25 14:26
### 完成的工作
1. **入库单管理 CRUD**
- 实体:`Inbound.java` + `InboundItem.java`
- DTO`InboundSaveReqDTO.java` + `InboundItemSaveReqDTO.java`
- Mapper`InboundMapper.java` + `InboundItemMapper.java`
- Service`InboundService.java` + `InboundServiceImpl.java`
- Controller`InboundController.java`
- API:分页查询、详情、明细、新增、修改、审核、作废、删除
- 审核逻辑:检查状态 → 更新状态 → 增加库存
- 作废逻辑:检查状态 → 更新状态 → 扣减库存
2. **出库单管理 CRUD**
- 实体:`Outbound.java` + `OutboundItem.java`
- DTO`OutboundSaveReqDTO.java` + `OutboundItemSaveReqDTO.java`
- Mapper`OutboundMapper.java` + `OutboundItemMapper.java`
- Service`OutboundService.java` + `OutboundServiceImpl.java`
- Controller`OutboundController.java`
- API:分页查询、详情、明细、新增、修改、审核、作废、删除
- 审核逻辑:检查状态 → **检查库存充足** → 更新状态 → 扣减库存
- 作废逻辑:检查状态 → 更新状态 → 恢复库存
3. **盘点单管理 CRUD**
- 实体:`Stocktake.java` + `StocktakeItem.java`
- DTO`StocktakeSaveReqDTO.java` + `StocktakeItemSaveReqDTO.java`
- Mapper`StocktakeMapper.java` + `StocktakeItemMapper.java`
- Service`StocktakeService.java` + `StocktakeServiceImpl.java`
- Controller`StocktakeController.java`
- API:分页查询、详情、明细、新增、修改、审核、作废、删除
- 审核逻辑:计算差异 → 设置盘点结果 → **调整库存**(盘盈 +,盘亏 -
- 作废逻辑:反向调整库存
4. **库存服务增强**
- 新增方法:`addStock()` - 入库单调用(包含物料信息)
- 新增方法:`reduceStock()` - 出库单调用
- 新增方法:`checkStock()` - 检查库存是否充足
5. **文档**
- `06-库存模块开发指南.md` - 完整 API 文档、业务流程、测试示例
### 业务类型字典
| 类型 | 值 | 标签 |
|------|-----|------|
| inbound_type | 10 | 采购入库 |
| inbound_type | 20 | 退货入库 |
| inbound_type | 30 | 其他入库 |
| outbound_type | 10 | 销售出库 |
| outbound_type | 20 | 领料出库 |
| outbound_type | 30 | 其他出库 |
| stocktake_diff_result | 0 | 相符 |
| stocktake_diff_result | 1 | 盘盈 |
| stocktake_diff_result | 2 | 盘亏 |
### 状态流转
```
草稿 (0) → 已审核 (1) → 已作废 (2)
```
### 编译状态
```
✅ mvn compile 成功
```
---
## 主数据模块开发(2026-05-25 13:46
### 完成的工作
1. **供应商管理 CRUD**
- 实体:`Supplier.java`name、contact、mobile 等简洁字段)
- DTO`SupplierSaveReqDTO.java`
- Mapper`SupplierMapper.java`
- Service`SupplierService.java` + `SupplierServiceImpl.java`
- Controller`SupplierController.java`
- API:分页查询、列表、详情、新增、修改、删除
- 操作日志:@Log 注解自动记录
2. **客户管理 CRUD**
- 实体:`Customer.java`(增加 level 客户级别字段)
- DTO`CustomerSaveReqDTODTO.java`
- Mapper`CustomerMapper.java`
- Service`CustomerService.java` + `CustomerServiceImpl.java`
- Controller`CustomerController.java`
- API:分页查询、列表、详情、新增、修改、删除
- 操作日志:@Log 注解自动记录
3. **文档**
- `05-主数据模块开发指南.md` - 包含 API 文档、前端集成示例
### 设计特点
- 字段命名参考 ruoyi-pro`name``contact``mobile`(简洁风格)
- 必填字段仅 `name`,支持快捷新增
- 客户级别:10-普通、20-重要、30-VIP(字典数据管理)
- 所有操作自动记录日志
### 编译状态
```
✅ mvn compile 成功
```
---
## Tiny-ERP 表架构设计与实现
### 完成的工作
1. **表架构设计文档**
- 位置:`/home/yangxuan/Projects/IdeaProjects/tiny-erp/yangxuan/设计/表架构设计.md`
- 参考项目:ruoyi-vue-pro(别名 ruoyi-pro
- 设计原则:务实、简洁、不过度设计
2. **SQL 脚本生成与执行**
- `20-master-data.sql` - 主数据模块(供应商、客户表参考 ruoyi-pro 风格)
- `50-inventory.sql` - 库存模块(入库/出库/盘点单及明细)
- `60-finance.sql` - 财务模块(应收/应付/收款/付款及核销明细)
- `99-data.sql` - 初始化数据(修复为幂等脚本)
3. **数据库表统计**
- 系统模块:5 表(含操作日志)
- 主数据:6 表(供应商、客户)
- 销售:4 表
- 采购:2 表
- 库存:8 表(入库/出库/盘点)
- 财务:8 表(应收/应付/收款/付款 + 核销明细)
- **总计:27 表**
4. **关键设计决策**
- 供应商/客户字段命名参考 ruoyi-pro:`name``contact``mobile`(去掉冗余前缀)
- 应收应付按物料明细记录(fi_receivable_item / fi_payable_item
- 数量:NUMERIC(12,3),金额/单价:NUMERIC(18,2)
- 所有业务表包含 ecid 字段实现多租户隔离
- 99-data.sql 使用 `INSERT ... SELECT ... WHERE NOT EXISTS` 实现幂等
### 待确认事项(已确认)
| 序号 | 事项 | 结论 |
|------|------|------|
| 1 | 多仓库管理 | 不需要 |
| 2 | 批次/序列号 | 不需要 |
| 3 | 应收应付物料明细 | 需要 ✓ |
| 4 | 多计量单位换算 | 不需要 |
### 数据库状态
- 数据库名:`tinyerp`
- 连接方式:Unix socket (`/var/run/postgresql`)
- 所有脚本执行成功,无 ERROR
- 初始化数据:1 租户、1 用户 (admin)、6 字典类型、16 字典数据
### 下一步
- 开始 Java 后端开发
- 实体类设计参考 ruoyi-pro 的 DO 结构
---
## 入库出库优化(2026-05-25 16:44
### 完成的工作
1. **生产入库 & 采购入库**
- DTO`ProductionInboundSaveReqDTO.java``ProductionInboundItemReqDTO.java`
- DTO`PurchaseInboundSaveReqDTO.java``PurchaseInboundItemReqDTO.java`
- 接口:`POST /im/inbound/production``POST /im/inbound/purchase`
- 特点:生产入库无需单价,采购入库含单价
2. **领料出库 & 销售出库**
- DTO`MaterialOutboundSaveReqDTO.java``MaterialOutboundItemReqDTO.java`
- DTO`SalesOutboundSaveReqDTO.java``SalesOutboundItemReqDTO.java`
- 接口:`POST /im/outbound/material``POST /im/outbound/sales`
- 特点:领料出库无需单价,销售出库含单价
3. **入库/出库历史查询**
- DTO`InboundHistoryQueryReqDTO.java``InboundHistoryDTO.java`
- DTO`OutboundHistoryQueryReqDTO.java``OutboundHistoryDTO.java`
- 接口:`POST /im/inbound/history-list``POST /im/outbound/history-list`
- 功能:查询已审核的单据,返回汇总信息
4. **物料信息填充**
- 保存时自动填充物料编码、名称、规格、单位
- 避免后续关联查询,提高查询性能
5. **文档**
- `04-入库出库优化 - 实现总结.md` - 完整 API 文档、测试示例
### 编译状态
```
✅ mvn compile 成功
```
---
## 实时库存 & 库存盘点(2026-05-25 17:16
### 完成的工作
1. **实时库存分页查询**
- DTO`StockPageQueryReqDTO.java``StockPageDTO.java`
- 接口:`POST /im/stock/page`
- 功能:带安全库存校验,返回 `isLowStock` 标识
- 校验规则:最小安全库存 > 0 且 库存 < 最小安全库存 → 库存过低
2. **最小安全库存管理**
- 接口:`PUT /md/material/{id}/safe-qty` - 更新最小安全库存
- 接口:`PUT /md/material/{id}/safe-qty/clear` - 清除(设置为 0
- 使用 MyBatis XML 实现(支持设置为 0
- 字段:`md_material.min_safe_qty NUMERIC(12,3)`
3. **快速盘点**
- DTO`StocktakeQuickSaveReqDTO.java``StocktakeQuickItemReqDTO.java`
- 接口:`POST /im/stocktake/quick-save`
- 功能:批量保存盘点单(草稿),自动获取当前库存作为账面数量
4. **盘点历史列表**
- DTO`StocktakeHistoryQueryReqDTO.java``StocktakeHistoryDTO.java`
- 接口:`POST /im/stocktake/history-list`
- 日期范围:`today`(当日)、`week`(近 7 日)、`month`(近 30 日)
5. **MyBatis XML 按模块分类**
- `mapper/md/material/MaterialMapper.xml` - 物料模块
- `mapper/im/stock/StockMapper.xml` - 库存模块
### 数字格式规范
| 字段类型 | 数据库类型 | 小数位 | 展示规则 |
|---------|-----------|--------|---------|
| 数量 | NUMERIC(12,3) | 3 | 小数全为 0 时不展示 |
| 单价/金额 | NUMERIC(11,2) | 2 | 小数全为 0 时不展示 |
### 编译状态
```
✅ mvn compile 成功
```
---
## 库存积压分析(2026-05-25 17:23
### 完成的工作
1. **积压统计(按分类分组)**
- DTO`StockOverstockDTO.java``StockOverstockQueryReqDTO.java`
- 接口:`POST /im/stock/overstock/summary`
- 返回:分类、物料数量、积压金额、平均积压天数
- 默认积压阈值:90 天
2. **积压明细(下钻页面)**
- DTO`StockOverstockDetailDTO.java`
- 接口:`POST /im/stock/overstock/detail`
- 参数:`category`(分类筛选)、`sortBy`amount/qty 排序)
- 返回:物料编码、名称、规格、库存数量、单价、积压天数、积压金额
3. **SQL 实现**
- 积压判定:最后入库日期 < 当前日期 - 阈值
- 单价计算:平均入库单价
- 积压金额 = 库存数量 × 平均单价
### 新增文件
- `StockMapper.xml` - 积压统计和明细 SQL
- `06-库存积压分析 - 实现总结.md` - 完整文档
### 编译状态
```
✅ mvn compile 成功
```
---
## 项目规范建立(2026-05-25 17:17-18:32
### Git 操作规范
-**禁止自动 push** - 所有 commit 后必须人工审查
- ✅ 流程:编译验证 → 提交代码 → 停止等待 → 人工确认后手动 push
### Java 语法规范
-**只能使用 Java 8 语法**
- ❌ 禁止:`var``Map.of()``List.of()`、switch 表达式、文本块、record
- ✅ 推荐:Lambda、Stream API、Optional、方法引用
### 状态字段规范
| 值 | 含义 |
|----|------|
| 0 | 有效(默认) |
| 1 | 无效 |
### 架构规范
- Service 层处理业务逻辑(查询、填充、组装)
- Controller 层保持简洁(调用 Service、返回结果)
- 接口支持可选字段参数(`withStock``withCategoryName`)提高复用性
### 本地开发规范
- ✅ 支持免登录(请求头 `X-User-Id` 或默认用户)
- ⚠️ 仅 local 环境启用,生产环境严禁开启
---
## 物料分页查询重构(2026-05-25 18:15-18:37
### 完成的工作
1. **Java 填充方案(替代 XML JOIN**
- 删除:`MaterialMapper.xml` 中的复杂 JOIN 查询
- 删除:`MaterialListWithStockReqDTO.java``MaterialWithStockDTO.java`
- 新增:`MaterialPageDTO.java``MaterialPageQueryReqDTO.java`
- 逻辑:Service 层批量查询库存和分类,内存填充
2. **可选字段参数**
- `withStock`(默认 true)- 是否返回库存数量
- `withCategoryName`(默认 true)- 是否返回分类名称
- 性能优化:不查关联时只需 1 次 SQL
3. **本地开发免登录**
- 配置:`development.mock-auth.enabled`
- 请求头:`X-User-Id``X-User-Name``X-Nickname`
- 过滤器:`UserContextFilter` 支持免登录模式
4. **代码整理**
- 简化 `MaterialController.java` - 移除 XML 查询接口
- 精简 `MaterialMapper.java` - 只保留安全库存更新方法
- 重构 `MaterialServiceImpl.java` - 添加 `pageWithStock()` 方法
### 性能对比
| 场景 | withStock | withCategoryName | SQL 次数 |
|------|-----------|------------------|---------|
| 下拉选择器 | ❌ | ❌ | 1 |
| 简单列表 | ❌ | ❌ | 1 |
| 库存管理 | ✅ | ❌ | 2 |
| 完整展示 | ✅ | ✅ | 3 |
### 编译状态
```
✅ mvn compile 成功
```
---
## 今日提交统计(未 push
```
feat: 实现入库出库优化功能
feat: 实现实时库存和盘点功能
feat: 实现库存积压分析功能
refactor: 按模块分类 MyBatis XML 文件
fix: 修复物料查询 XML 中的字段错误
docs: 更新物料状态注释
feat: 物料分页查询改为 Java 填充关联数据
refactor: 物料分页查询逻辑移至 Service 层
feat: 物料分页查询支持可选字段
refactor: 删除物料 XML 查询,统一使用 Service 层 Java 填充
feat: 本地开发支持免登录
```
**总计**: 约 15 个 commit4300+ 行新增,200+ 行删除
---
## 待办事项
1. **数据库迁移** - 添加 `md_material.min_safe_qty` 字段
2. **前端开发** - 实时库存、盘点、积压分析页面
3. **测试验证** - 使用 HTTP 测试文件验证所有接口
4. **代码审查** - 人工审查后执行 git push
## 下午-晚间增量(2026-05-25 18:37~20:18
### 实体-DDL 字段对齐
| 文件 | 字段 | 操作 |
|------|------|------|
| `Stock.java` | `category`, `safeQty` | 彻底删除(非表字段) |
| `Outbound.java` | `warehouseName`, `totalQuantity` | 彻底删除(非表字段) |
| `Stocktake.java` | `warehouseName` | 彻底删除(非表字段) |
| `StockServiceImpl.java` | `safeQty` 操作 | 改为读写 `md_material.min_safe_qty` |
### 模糊查询支持特殊字符
- 创建 `LikeEscapeUtil.java` — 转义 `\``%``_`
- 物料/客户/供应商分页查询全部接入转义
- 客户/供应商 `/list` 接口新增 `keyword` 参数支持名称+编码联合模糊
- **踩坑**`ESCAPE '\\'` 被 MyBatis-Plus COUNT 包装解析失败 → 移除 `ESCAPE` 子句,利用 PostgreSQL 默认 `\` 为转义字符
### 最小安全库存
- DDL `20-master-data.sql` 新增 `min_safe_qty NUMERIC(12,3) DEFAULT 0`
- 升级脚本 `upgrade/v1.0.1-alter-material-add-min-safe-qty.sql`
- 库存分页返回 `isLowStock` 标识(库存 < min_safe_qty → 过低)
- 接口:`PUT /md/material/{id}/safe-qty` / `PUT /md/material/{id}/safe-qty/clear`
### 主数据初始化脚本修正
| 改动 | 说明 |
|------|------|
| `safety_stock` 列和值 | 从 INSERT 语句中删除 |
| `supplier_code` / `customer_code` | 补全编码值 |
| 物料名称规格空格 | 对齐文档(如"宝塔3斜纹" |
### DDL 补充字段
| 表 | 新增字段 |
|----|---------|
| `md_supplier` | `supplier_code VARCHAR(50)`, `phone VARCHAR(20)`, `address VARCHAR(200)` |
| `md_customer` | `customer_code VARCHAR(50)`, `phone VARCHAR(20)`, `address VARCHAR(200)`, `level INTEGER DEFAULT 0` |
### 今日提交统计(全部未 push)
```
418cd10 fix: 修复库存积压报表仅入库物料积压天数基准错误
e8d7bb4 docs: 重构文档目录结构,按模块分类组织
8a38d33 feat: 入库单/出库单 inboundDate/outboundDate 为空时默认当天
373a292 feat: 供应商/客户DDL补充编码、联系电话、地址、客户级别字段
6c338d1 feat: 根据文档补充default租户主数据初始化脚本的编码字段和物料名称修正
d17b970 feat: 物料/客户/供应商模糊查询支持特殊字符转义及客户供应商列表接口
f02f048 feat: DDL增加md_material.min_safe_qty字段及升级脚本
5de00d3 feat: 清理非表字段,最小安全库存统一走md_material.min_safe_qty
(plus safety_stock removal commit)
```
**原则**: 代码改动与文档改动分 commit,禁止自动 push,人工审查后手动操作。
### 环境配置
- MySQL 运行时 `tiny_erp` 数据库已配置 `min_safe_qty`
- 开发免登录配置:`development.mock-auth.enabled`
-699
View File
@@ -1,699 +0,0 @@
# 2026-05-26 会话记忆
## 本周聚焦
- 只关注 **tiny-erp**,不处理其他项目
- 只关注 **md(主数据)****im(库存)** 两个模块
- **不再关注** om(销售)、mc(采购)、fin(财务)、home、system 等其他模块
## 模块路径确认
包路径: `com.witsoft.erp`
项目路径: `/home/yangxuan/Projects/IdeaProjects/tiny-erp`
### md 模块(主数据)
`module/md/` — 已完整实现
- `category` — 物料分类
- `customer` — 客户
- `factory` — 工厂
- `material` — 物料
- `supplier` — 供应商
- `warehouse` — 仓库
### im 模块(库存)
`module/im/` — 已完整实现
- `inbound` — 入库单(含采购入库、生产入库)
- `outbound` — 出库单
- `stock` — 库存查询、库存流水、呆滞分析
- `stocktake` — 库存盘点(含快速盘点)
## 原记忆清理
旧记忆(memory/2026-05-23.md)中关于 `bd` 模块的命名实际上是 `md`(代码实际使用的是 `md`,不是 `bd`)。
ome/mc/fin/home/system 模块依然存在但不处理。
## 注释规范(已写入 MEMORY.md
1. 所有公共接口和类必须包含 Javadoc
2. 注释语言:中文描述业务背景,技术术语保留英文(如 NPE)
3. 禁止生成 "Gets the value of X" 这类无意义的 getter/setter 注释
4. 复杂算法必须在代码块上方解释核心逻辑
5. 禁止使用 HTML 标签
## 开发注意事项(已写入 MEMORY.md)
1. **复用优先**:逻辑雷同时提取公共方法复用
2. **业务表仅存物料 id**:物料相关字段仅存 `material_id`,其他数据通过关联查询填充
3. **填充在 Service 层**:关联数据填充逻辑统一在 Service 层处理
4. **首个版本直接改 DDL**:脚本直接修改建表语句,不需要写 ALTER TABLE
5. **字典优先用 DictService**:字典取值优先使用 DictService 公共方法
## 库存业务表字段清理
**背景:** 业务表只存物料 ID,物料编码/名称/规格/单位通过关联查询填充。
**DDL 改动(50-inventory.sql):**
- `im_stock` — 移除 material_code, material_name, spec, unit
- `im_stock_transaction` — 移除 material_code, material_name
- `im_inbound_item` — 移除 material_code, material_name, spec, unit
- `im_outbound_item` — 移除 material_code, material_name, spec, unit
**实体类:** Stock, StockTransaction, InboundItem, OutboundItem — 移除对应字段
**请求 DTO** InboundItemSaveReqDTO, OutboundItemSaveReqDTO, StocktakeItemSaveReqDTO, QuickStocktakeItemDTO — 只保留 materialId
**接口改动:**
- StockTransactionService.recordTransaction() — 移除 materialCode/materialName 参数
- MaterialService — 新增 searchMaterialIdsByKeyword() 方法
**Service 改动:**
- StockTransactionServiceImpl — keyword 搜索改为两步(先查物料表匹配 ID);DTO 填充从 materialInfoMap 读取
- StockServiceImpl — 同上
- InboundServiceImpl — saveItems 不 set 冗余字段;recordTransaction 去参;history 从 material 填充
- OutboundServiceImpl — 同上
- MaterialServiceImpl — 实现 searchMaterialIdsByKeyword()
**编译验证:** `mvn compile -q`
## Git 提交约定
- **commit 跳过 application.yml** — `git add` 时用 `git add . -- ':!application.yml'` 或手动排除
- **commit 后不要 push** — 只做本地提交,不推送远程
# 2026-05-26 会话记忆
## 物料信息填充公共服务 (MaterialFillService)
### 核心设计决策
1. **实体设计原则**
- `InboundItem``OutboundItem` 只存储 `materialId`
- 不存储物料编码、名称、规格、单位等字段
- 防止物料信息变更后历史数据不一致
2. **批量查询模式**
```java
List<Long> materialIds = items.stream().map(Item::getMaterialId).collect(Collectors.toList());
Map<Long, MaterialInfoDTO> materialInfoMap = materialFillService.getMaterialInfoMap(materialIds);
```
- 避免 N+1 查询问题
- 一次查询所有物料信息,性能更优
3. **Service 层填充**
- 所有物料信息填充逻辑在 Service 层处理
- Controller 只负责返回 DTO
- 不放在 Mapper 或 Controller 层
### 修改的 Service 类(共 6 个)
| Service | 方法 | 用途 |
|---------|------|------|
| InboundServiceImpl | executeInbound(), cancel() | 入库/冲销时记录流水 |
| OutboundServiceImpl | executeOutbound(), cancel() | 出库/冲销时记录流水 |
| FinAccountsAutoServiceImpl | createApFromInbound(), cancelApFromInbound() | 采购应付联动 |
| FinAccountsAutoServiceImpl | createArFromOutbound(), cancelArFromOutbound() | 销售应收联动 |
| HomeServiceImpl | getLatestNews() | 首页动态显示 |
| DeliveryServiceImpl | confirmOutbound() | 发货确认 |
### 物料类型字典
- Dict Type: `material_type`
- 值:`P`-原材料,`SA`-半成品,`FG`-成品
- SQL 脚本:`scripts/postgresql/22-material-type-dict.sql`
### Git 状态
- 所有修改已 commit13+ commits
- **禁止 push** - 用户明确要求
- 分支:master
### 经验教训
1. 修改实体类后,所有引用该实类的地方都要检查
2. 编译错误可能分散在多个模块(im, fin, home, om
3. 使用 `mvn clean compile` 确保完整编译,避免 IDE 缓存误导
# 2026-05-26 会话记忆
## 本周聚焦
- 只关注 **tiny-erp**,不处理其他项目
- 只关注 **md(主数据)** 和 **im(库存)** 两个模块
- **不再关注** om(销售)、mc(采购)、fin(财务)、home、system 等其他模块
## 模块路径确认
包路径: `com.witsoft.erp`
项目路径: `/home/yangxuan/Projects/IdeaProjects/tiny-erp`
### md 模块(主数据)
`module/md/` — 已完整实现
- `category` — 物料分类
- `customer` — 客户
- `factory` — 工厂
- `material` — 物料
- `supplier` — 供应商
- `warehouse` — 仓库
### im 模块(库存)
`module/im/` — 已完整实现
- `inbound` — 入库单(含采购入库、生产入库)
- `outbound` — 出库单
- `stock` — 库存查询、库存流水、呆滞分析
- `stocktake` — 库存盘点(含快速盘点)
## 原记忆清理
旧记忆(memory/2026-05-23.md)中关于 `bd` 模块的命名实际上是 `md`(代码实际使用的是 `md`,不是 `bd`)。
ome/mc/fin/home/system 模块依然存在但不处理。
## 注释规范(已写入 MEMORY.md
1. 所有公共接口和类必须包含 Javadoc
2. 注释语言:中文描述业务背景,技术术语保留英文(如 NPE)
3. 禁止生成 "Gets the value of X" 这类无意义的 getter/setter 注释
4. 复杂算法必须在代码块上方解释核心逻辑
5. 禁止使用 HTML 标签
## 开发注意事项(已写入 MEMORY.md)
1. **复用优先**:逻辑雷同时提取公共方法复用
2. **业务表仅存物料 id**:物料相关字段仅存 `material_id`,其他数据通过关联查询填充
3. **填充在 Service 层**:关联数据填充逻辑统一在 Service 层处理
4. **首个版本直接改 DDL**:脚本直接修改建表语句,不需要写 ALTER TABLE
5. **字典优先用 DictService**:字典取值优先使用 DictService 公共方法
## Git 提交约定
- **commit 跳过 application.yml** — `git add . -- ':!application.yml'` 排除,防止泄露配置
- **commit 后不要 push** — 只做本地 commit,不推送远程仓库
## 库存业务表字段清理
**背景:** 业务表只存物料 ID,物料编码/名称/规格/单位通过关联查询填充。
**DDL 改动(50-inventory.sql):**
- `im_stock` — 移除 material_code, material_name, spec, unit
- `im_stock_transaction` — 移除 material_code, material_name
- `im_inbound_item` — 移除 material_code, material_name, spec, unit
- `im_outbound_item` — 移除 material_code, material_name, spec, unit
**实体类:** Stock, StockTransaction, InboundItem, OutboundItem — 移除对应字段
**请求 DTO** InboundItemSaveReqDTO, OutboundItemSaveReqDTO, StocktakeItemSaveReqDTO, QuickStocktakeItemDTO — 只保留 materialId
**接口改动:**
- StockTransactionService.recordTransaction() — 移除 materialCode/materialName 参数
- MaterialService — 新增 searchMaterialIdsByKeyword() 方法
**Service 改动:**
- StockTransactionServiceImpl — keyword 搜索改为两步(先查物料表匹配 ID);DTO 填充从 materialInfoMap 读取
- StockServiceImpl — 同上
- InboundServiceImpl — saveItems 不 set 冗余字段;recordTransaction 去参;history 从 material 填充
- OutboundServiceImpl — 同上
- MaterialServiceImpl — 实现 searchMaterialIdsByKeyword()
**编译验证:** `mvn compile -q` ✅
## 物料信息填充公共服务 (MaterialFillService)
### 核心设计决策
1. **实体设计原则**
- `InboundItem` 和 `OutboundItem` 只存储 `materialId`
- 不存储物料编码、名称、规格、单位等字段
- 防止物料信息变更后历史数据不一致
2. **批量查询模式**
```java
List<Long> materialIds = items.stream().map(Item::getMaterialId).collect(Collectors.toList());
Map<Long, MaterialInfoDTO> materialInfoMap = materialFillService.getMaterialInfoMap(materialIds);
```
- 避免 N+1 查询问题
- 一次查询所有物料信息,性能更优
3. **Service 层填充**
- 所有物料信息填充逻辑在 Service 层处理
- Controller 只负责返回 DTO
- 不放在 Mapper 或 Controller 层
### 修改的 Service 类(共 6 个)
| Service | 方法 | 用途 |
|---------|------|------|
| InboundServiceImpl | executeInbound(), cancel() | 入库/冲销时记录流水 |
| OutboundServiceImpl | executeOutbound(), cancel() | 出库/冲销时记录流水 |
| FinAccountsAutoServiceImpl | createApFromInbound(), cancelApFromInbound() | 采购应付联动 |
| FinAccountsAutoServiceImpl | createArFromOutbound(), cancelArFromOutbound() | 销售应收联动 |
| HomeServiceImpl | getLatestNews() | 首页动态显示 |
| DeliveryServiceImpl | confirmOutbound() | 发货确认 |
### 物料类型字典
- Dict Type: `material_type`
- 值:`P`-原材料,`SA`-半成品,`FG`-成品
- SQL 脚本:`scripts/postgresql/22-material-type-dict.sql`
### Git 状态
- 所有修改已 commit13+ commits
- **禁止 push** - 用户明确要求
- 分支:master
## 物料选择器(Material Selector
新增物料选择器功能,用于入库/出库操作时弹窗选物料。
### 接口
| 接口 | 位置 | 数据源 | 仓库参数 |
|------|------|--------|---------|
| `POST /im/inbound/material-selector` | InboundController | md_material | 不需要 |
| `POST /im/outbound/material-selector` | OutboundController | im_stock JOIN md_material | 需要 warehouseId |
### 请求参数(MaterialSelectorReqDTO → md.material.dto
- `categoryId` — 0=常用物料,>0=按分类筛选
- `keyword` — 物料编码/名称/规格关键字
- `warehouseId` — 出库场景需要
- 继承 `PageQuery`pageNum, pageSize
### 常用物料 TOP10 逻辑
- **口径:** 近 30 天出入库明细条目数最多的 10 个物料
- **入库:** `im_inbound_item` GROUP BY material_id ORDER BY COUNT(*) DESC LIMIT 10
- **出库:** `im_outbound_item` 同上
- **SQL 放 Mapper XML**(方便后续扩展)
### 分类筛选逻辑
- **入库:** MyBatis Plus LambdaQueryWrapper 查 `md_material` 表,按 `category_id` + `keyword` 分页
- **出库:** XML 联表 `im_stock JOIN md_material`,按 `category_id` + `keyword` + `warehouseId` 分页,只查库存 > 0 的数据
### 响应
- 复用 `StockPageDTO`im.stock.dto
- 物料编码/名称/规格/单位/分类等从 `MaterialFillService` 填充
### 新增文件(7个)
| 文件 | 路径 |
|------|------|
| MaterialSelectorReqDTO | md.material.dto |
| MaterialSelectorService | md.material.service |
| MaterialSelectorServiceImpl | md.material.service.impl |
| InboundItemMapper.xml | resources/mapper/im/ |
| OutboundItemMapper.xml | resources/mapper/im/ |
| StockMapper.xml | resources/mapper/im/ |
| | |
### 修改文件(5个)
| 文件 | 改动 |
|------|------|
| InboundItemMapper.java | + selectRecentMaterialIds() |
| OutboundItemMapper.java | + selectRecentMaterialIds() |
| StockMapper.java | + selectStockPage() / countStockPage() |
| InboundController.java | + /material-selector 端点 |
| OutboundController.java | + /material-selector 端点 |
## 历史单据创建人名称
### 改动
- **InboundHistoryItemDTO** — 新增 `creatorName` 字段
- **OutboundHistoryItemDTO** — 新增 `creatorName` 字段
- **InboundServiceImpl.listHistory()** — 收集 creators → 批量查 sys_user(username→nickname) → 填充
- **OutboundServiceImpl.listHistory()** — 同上
### 逻辑
1. 从单据列表收集所有 `creator`(用户名)
2. `userService.lambdaQuery().in(User::getUsername, creators).list()`
3. 转 `Map<String, String>`username → nickname
4. 逐行 `dto.setCreatorName()`
5. 一次 SQL,不 N+1
# 2026-05-26 会话记忆
## 本周聚焦
- 只关注 **tiny-erp**,不处理其他项目
- 只关注 **md(主数据)** 和 **im(库存)** 两个模块
- **不再关注** om(销售)、mc(采购)、fin(财务)、home、system 等其他模块
## 模块路径确认
包路径: `com.witsoft.erp`
项目路径: `/home/yangxuan/Projects/IdeaProjects/tiny-erp`
### md 模块(主数据)
`module/md/` — 已完整实现
- `category` — 物料分类
- `customer` — 客户
- `factory` — 工厂
- `material` — 物料
- `supplier` — 供应商
- `warehouse` — 仓库
### im 模块(库存)
`module/im/` — 已完整实现
- `inbound` — 入库单(含采购入库、生产入库)
- `outbound` — 出库单
- `stock` — 库存查询、库存流水、呆滞分析
- `stocktake` — 库存盘点(含快速盘点)
## 原记忆清理
旧记忆(memory/2026-05-23.md)中关于 `bd` 模块的命名实际上是 `md`(代码实际使用的是 `md`,不是 `bd`)。
ome/mc/fin/home/system 模块依然存在但不处理。
## 注释规范(已写入 MEMORY.md
1. 所有公共接口和类必须包含 Javadoc
2. 注释语言:中文描述业务背景,技术术语保留英文(如 NPE)
3. 禁止生成 "Gets the value of X" 这类无意义的 getter/setter 注释
4. 复杂算法必须在代码块上方解释核心逻辑
5. 禁止使用 HTML 标签
## 开发注意事项(已写入 MEMORY.md)
1. **复用优先**:逻辑雷同时提取公共方法复用
2. **业务表仅存物料 id**:物料相关字段仅存 `material_id`,其他数据通过关联查询填充
3. **填充在 Service 层**:关联数据填充逻辑统一在 Service 层处理
4. **首个版本直接改 DDL**:脚本直接修改建表语句,不需要写 ALTER TABLE
5. **字典优先用 DictService**:字典取值优先使用 DictService 公共方法
## Git 提交约定
- **commit 跳过 application.yml** — `git add . -- ':!application.yml'` 排除,防止泄露配置
- **commit 后不要 push** — 只做本地 commit,不推送远程仓库
## 库存业务表字段清理
**背景:** 业务表只存物料 ID,物料编码/名称/规格/单位通过关联查询填充。
**DDL 改动(50-inventory.sql):**
- `im_stock` — 移除 material_code, material_name, spec, unit
- `im_stock_transaction` — 移除 material_code, material_name
- `im_inbound_item` — 移除 material_code, material_name, spec, unit
- `im_outbound_item` — 移除 material_code, material_name, spec, unit
**实体类:** Stock, StockTransaction, InboundItem, OutboundItem — 移除对应字段
**请求 DTO** InboundItemSaveReqDTO, OutboundItemSaveReqDTO, StocktakeItemSaveReqDTO, QuickStocktakeItemDTO — 只保留 materialId
**接口改动:**
- StockTransactionService.recordTransaction() — 移除 materialCode/materialName 参数
- MaterialService — 新增 searchMaterialIdsByKeyword() 方法
**Service 改动:**
- StockTransactionServiceImpl — keyword 搜索改为两步(先查物料表匹配 ID);DTO 填充从 materialInfoMap 读取
- StockServiceImpl — 同上
- InboundServiceImpl — saveItems 不 set 冗余字段;recordTransaction 去参;history 从 material 填充
- OutboundServiceImpl — 同上
- MaterialServiceImpl — 实现 searchMaterialIdsByKeyword()
**编译验证:** `mvn compile -q` ✅
## 物料信息填充公共服务 (MaterialFillService)
### 核心设计决策
1. **实体设计原则**
- `InboundItem` 和 `OutboundItem` 只存储 `materialId`
- 不存储物料编码、名称、规格、单位等字段
- 防止物料信息变更后历史数据不一致
2. **批量查询模式**
```java
List<Long> materialIds = items.stream().map(Item::getMaterialId).collect(Collectors.toList());
Map<Long, MaterialInfoDTO> materialInfoMap = materialFillService.getMaterialInfoMap(materialIds);
```
- 避免 N+1 查询问题
- 一次查询所有物料信息,性能更优
3. **Service 层填充**
- 所有物料信息填充逻辑在 Service 层处理
- Controller 只负责返回 DTO
- 不放在 Mapper 或 Controller 层
### 修改的 Service 类(共 6 个)
| Service | 方法 | 用途 |
|---------|------|------|
| InboundServiceImpl | executeInbound(), cancel() | 入库/冲销时记录流水 |
| OutboundServiceImpl | executeOutbound(), cancel() | 出库/冲销时记录流水 |
| FinAccountsAutoServiceImpl | createApFromInbound(), cancelApFromInbound() | 采购应付联动 |
| FinAccountsAutoServiceImpl | createArFromOutbound(), cancelArFromOutbound() | 销售应收联动 |
| HomeServiceImpl | getLatestNews() | 首页动态显示 |
| DeliveryServiceImpl | confirmOutbound() | 发货确认 |
### 物料类型字典
- Dict Type: `material_type`
- 值:`P`-原材料,`SA`-半成品,`FG`-成品
- SQL 脚本:`scripts/postgresql/22-material-type-dict.sql`
### Git 状态
- 所有修改已 commit13+ commits
- **禁止 push** - 用户明确要求
- 分支:master
## 物料选择器(Material Selector
新增物料选择器功能,用于入库/出库操作时弹窗选物料。
### 接口
| 接口 | 位置 | 数据源 | 仓库参数 |
|------|------|--------|---------|
| `POST /im/inbound/material-selector` | InboundController | md_material | 不需要 |
| `POST /im/outbound/material-selector` | OutboundController | im_stock JOIN md_material | 需要 warehouseId |
### 请求参数(MaterialSelectorReqDTO → md.material.dto
- `categoryId` — 0=常用物料,>0=按分类筛选
- `keyword` — 物料编码/名称/规格关键字
- `warehouseId` — 出库场景需要
- 继承 `PageQuery`pageNum, pageSize
### 常用物料 TOP10 逻辑
- **口径:** 近 30 天出入库明细条目数最多的 10 个物料
- **入库:** `im_inbound_item` GROUP BY material_id ORDER BY COUNT(*) DESC LIMIT 10
- **出库:** `im_outbound_item` 同上
- **SQL 放 Mapper XML**(方便后续扩展)
### 分类筛选逻辑
- **入库:** MyBatis Plus LambdaQueryWrapper 查 `md_material` 表,按 `category_id` + `keyword` 分页
- **出库:** XML 联表 `im_stock JOIN md_material`,按 `category_id` + `keyword` + `warehouseId` 分页,只查库存 > 0 的数据
### 响应
- 复用 `StockPageDTO`im.stock.dto
- 物料编码/名称/规格/单位/分类等从 `MaterialFillService` 填充
### 新增文件(7个)
| 文件 | 路径 |
|------|------|
| MaterialSelectorReqDTO | md.material.dto |
| MaterialSelectorService | md.material.service |
| MaterialSelectorServiceImpl | md.material.service.impl |
| InboundItemMapper.xml | resources/mapper/im/ |
| OutboundItemMapper.xml | resources/mapper/im/ |
| StockMapper.xml | resources/mapper/im/ |
| | |
### 修改文件(5个)
| 文件 | 改动 |
|------|------|
| InboundItemMapper.java | + selectRecentMaterialIds() |
| OutboundItemMapper.java | + selectRecentMaterialIds() |
| StockMapper.java | + selectStockPage() / countStockPage() |
| InboundController.java | + /material-selector 端点 |
| OutboundController.java | + /material-selector 端点 |
## 历史单据创建人名称
### 改动
- **InboundHistoryItemDTO** — 新增 `creatorName` 字段
- **OutboundHistoryItemDTO** — 新增 `creatorName` 字段
- **InboundServiceImpl.listHistory()** — 收集 creators → 批量查 sys_user(username→nickname) → 填充
- **OutboundServiceImpl.listHistory()** — 同上
### 逻辑
1. 从单据列表收集所有 `creator`(用户名)
2. `userService.lambdaQuery().in(User::getUsername, creators).list()`
3. 转 `Map<String, String>`username → nickname
4. 逐行 `dto.setCreatorName()`
5. 一次 SQL,不 N+1
## 实体名称字段清理(SupplierName/CustomerName/WarehouseName
### 背景
单据实体(Inbound、Outbound、PurchaseOrder、SalesOrder、Delivery)及其 Item 实体中,之前还存储了供应商名称、客户名称、仓库名称等冗余字段。本次清理全部移除,只存 ID,显示名称通过 master-data 查询填充。
### 涉及实体
- **Inbound** — 移除 `supplierName`, `warehouseName`
- **Outbound** — 移除 `customerName`, `warehouseName`
- **PurchaseOrder** — 移除 `supplierName`
- **PurchaseOrderItem** — 移除了 `materialCode`, `materialName`, `spec`, `unit`(之前已完成)
- **SalesOrder** — 移除 `customerName`
- **SalesOrderItem** — 移除了物料冗余字段(之前已完成)
- **Delivery** — 移除 `customerName`
- **DeliveryItem** — 移除了物料冗余字段(之前已完成)
### DTO 改动
- **InboundSaveReqDTO / PurchaseInboundSaveReqDTO / ProductionInboundSaveReqDTO** — 只保留 supplierId/warehouseId,移除 supplierName/warehouseName
- **OutboundSaveReqDTO / SalesOutboundSaveReqDTO / MaterialOutboundSaveReqDTO** — 只保留 customerId/warehouseId,移除 customerName/warehouseName
- **InboundHistoryItemDTO / OutboundHistoryItemDTO** — **保留** display name 字段(响应 DTO 需要显示),通过 master-data lookup 填充
### 不做改动
- **Ar.java / Ap.java** — 保留 customerName / supplierName 作为财务历史快照
- **InboundHistoryItemDTO / OutboundHistoryItemDTO** — 保留 name 字段供前端展示
### 主要 Service 改动
| 文件 | 改动内容 |
|------|---------|
| **InboundServiceImpl.java** | 注入 WarehouseMapper;移除 entity setSupplierName/setWarehouseNamehistory DTO 名通过 supplierMapper + warehouseMapper 批量 lookupautoInboundFromOrder 用 supplierId 取代 supplierNameupdatePurchaseOrderAfterInbound 用 supplierId 查询 |
| **OutboundServiceImpl.java** | 注入 WarehouseMapper;移除 entity setCustomerNamehistory DTO 名通过 customerMapper + warehouseMapper 批量 lookup |
| **FinAccountsAutoServiceImpl.java** | `createApFromInbound`/`cancelApFromInbound` 使用 supplierMapper 查询 supplierName 填充 Ap`createArFromOutbound`/`cancelArFromOutbound` 使用 customerMapper 查询 customerName |
| **PurchaseOrderServiceImpl.java** | `setSupplierName(reqDTO.getSupplierName())` → `setSupplierId(reqDTO.getSupplierId())` |
| **SalesOrderServiceImpl.java** | `setCustomerName(reqDTO.getCustomerName())` → `setCustomerId(reqDTO.getCustomerId())` |
| **DeliveryServiceImpl.java** | `setCustomerName(order.getCustomerName())` → `setCustomerId(order.getCustomerId())`item 用 `materialFillService` 填充物料信息 |
### 控制器查询条件
- PurchaseOrderController / SalesOrderController / DeliveryController — 查询条件从名称改为 ID
### 编译验证
- `mvn clean compile` ✅ — 零错误
## 集成测试(InboundOutboundIntegrationTest
### 文件路径
`src/test/java/com/witsoft/erp/im/InboundOutboundIntegrationTest.java`
### 设计
- 使用 `TestRestTemplate``webEnvironment = RANDOM_PORT`
- `@TestMethodOrder(MethodOrderer.OrderAnnotation.class)` 按顺序执行
- 复用已有的 `Result<T>` 泛型返回包装类
### 测试覆盖(11 个用例)
| 序号 | 端点 | 说明 |
|------|------|------|
| 1 | POST /erp/system/user/login | 登录获取 Bearer token |
| 2 | POST /erp/im/inbound/production | 生产入库(2 行物料) |
| 3 | POST /erp/im/inbound/purchase | 采购入库(含单价) |
| 4 | POST /erp/im/inbound/history-list | 查询入库历史 |
| 5 | POST /erp/im/outbound/material | 领料出库 |
| 6 | POST /erp/im/outbound/sales | 销售出库(含单价) |
| 7 | POST /erp/im/outbound/history-list | 查询出库历史 |
| 8 | POST /erp/im/inbound/auto-from-order | 自动入库(基于采购订单) |
| 9 | POST /erp/im/stock/transaction/page | 查询库存流水 |
| 10 | DELETE /erp/im/inbound/{id} | 撤销入库单 |
| 11 | DELETE /erp/im/outbound/{id} | 撤销出库单 |
### 注意事项
- `application.yml` 中 `server.servlet.context-path: /erp`,所有路径须带 `/erp` 前缀
- 测试需要准备基础数据:物料 ID=3/4、供应商 ID=1、客户 ID=1、仓库 ID=1、采购订单 ID=1
- 当前 `authToken` 未通过 TestRestTemplate 的 basic auth,走的是 token-auth 模式
- 登录密码写的是 `***`,需要按实际数据库密码修改 `TEST_PASSWORD` 常量
## Controller 集成测试(TestRestTemplate
### 现有测试文件
| 测试类 | 路径 | 用例数 | 覆盖 Controller |
|--------|------|--------|----------------|
| InboundOutboundIntegrationTest | `im/InboundOutboundIntegrationTest.java` | 11 | Inbound + Outbound(合并) |
| StockControllerTest | `im/stock/StockControllerTest.java` | 17 | StockController |
| StocktakeControllerTest | `im/stocktake/StocktakeControllerTest.java` | 17 | StocktakeController |
| InboundControllerTest | `im/inbound/InboundControllerTest.java` | 21 | InboundController |
| OutboundControllerTest | `im/outbound/OutboundControllerTest.java` | 21 | OutboundController |
### 测试设计模式(所有测试统一)
1. **TestRestTemplate + RANDOM_PORT** — 自动分配端口,避免冲突
2. **@TestMethodOrder(OrderAnnotation.class)** — 按 Order 顺序执行
3. **CONTEXT_PATH = "/erp"** — 手动拼接,因为自动 context-path 处理不可靠
4. **assumeToken() 守卫** — 登录失败后通过 `Assumptions.assumeTrue(authToken != null)` 跳过后续测试,避免 403
5. **密码可配置** — `System.getProperty("test.password", "admin123")`,通过 `-Dtest.password=xxx` 覆盖
6. **url() 辅助方法** — `"http://localhost:" + port + CONTEXT_PATH + path`
### InboundControllerTest21 用例)
| 序号 | 端点 | 验证 |
|------|------|------|
| 1 | POST /system/user/login | 登录获取 Bearer token |
| 2-3 | POST /im/inbound/material-selector | 物料选择器(分类筛选) |
| 4-6 | POST /im/inbound | 新增 + 明细为空/类型为空校验边界 |
| 7-8 | GET /im/inbound/{id} | 详情 / 不存在返回 null |
| 9 | GET /im/inbound/{id}/items | 明细列表 |
| 10 | PUT /im/inbound | 修改 |
| 11-12 | PUT /im/inbound/{id}/cancel | 撤销 / 重复撤销 400 |
| 13-14 | DELETE /im/inbound/{id} | 删除 |
| 15-16 | POST /im/inbound/page | 分页(全查/仓库筛选) |
| 17 | POST /im/inbound/history-list | 历史明细列表 |
| 18 | POST /im/inbound/production | 生产入库 |
| 19-20 | POST /im/inbound/purchase | 采购入库 / 供应商为空 400 |
| 21 | POST /im/inbound/auto-from-order | 自动入库-订单不存在 400 |
### OutboundControllerTest21 用例)
| 序号 | 端点 | 验证 |
|------|------|------|
| 1 | POST /system/user/login | 登录 |
| 2-3 | POST /im/outbound/material-selector | 物料选择器 |
| 4-6 | POST /im/outbound | 新增 + 明细为空/客户为空校验 |
| 7-8 | GET /im/outbound/{id} | 详情 / 不存在 |
| 9 | GET /im/outbound/{id}/items | 明细 |
| 10 | PUT /im/outbound | 修改 |
| 11-12 | PUT /im/outbound/{id}/cancel | 撤销 / 重复撤销 400 |
| 13-14 | DELETE /im/outbound/{id} | 删除 |
| 15-16 | POST /im/outbound/page | 分页(全查/客户筛选) |
| 17 | POST /im/outbound/history-list | 历史明细 |
| 18-19 | POST /im/outbound/material | 领料出库 / 明细为空 400 |
| 20-21 | POST /im/outbound/sales | 销售出库 / 客户为空 400 |
### StockControllerTest17 用例)
覆盖 StockController 全部 4 个端点:
| 序号 | 端点 | 验证 |
|------|------|------|
| 1 | POST /system/user/login | 登录 |
| 2-6 | POST /im/stock/page | 空参数、仓库筛选、关键字、无匹配关键字、自定义分页 |
| 7-11 | POST /im/stock/list | 空、仓库、关键字、预警筛选、无匹配关键字 |
| 12-13 | GET /im/stock/{materialId} | 存在/不存在 |
| 14-16 | PUT /im/stock/safe-qty | 正常设置、物料不存在 400、参数校验 |
| 17 | POST /im/stock/page | DTO 字段完整性验证 |
### StocktakeControllerTest17 用例)
覆盖 StocktakeController 全部 10 个端点:
| 序号 | 端点 | 验证 |
|------|------|------|
| 1 | POST /system/user/login | 登录 |
| 2-3 | POST /im/stocktake | 新增(草稿)/ 明细为空 400 |
| 4-5 | GET /im/stocktake/{id} | 详情 / 不存在 |
| 6 | GET /im/stocktake/{id}/items | 明细(含物料信息) |
| 7 | PUT /im/stocktake | 修改 |
| 8-9 | PUT /im/stocktake/{id}/audit | 审核 / 重复审核 400 |
| 10-11 | PUT /im/stocktake/{id}/cancel | 作废 |
| 12 | DELETE /im/stocktake/{id} | 删除 |
| 13 | POST /im/stocktake/quick-save | 快速盘点(创建即审核) |
| 14-15 | POST /im/stocktake/page | 分页(筛选/空 body |
| 16-17 | POST /im/stocktake/history-list | 历史明细(空条件) |
### 已知问题
- **InboundController.getPage() 有两个 @RequestBody** — 测试用 Map 代理
- **OutboundController.getPage() 同理**
- **StocktakeController.getPage() 同理**
- 密码默认 `admin123`,通过 `-Dtest.password=xxx` 配置
- IntelliJ 解析 `junit-platform-launcher:1.8.2` 失败,已在 pom.xml 中添加依赖
-422
View File
@@ -1,422 +0,0 @@
# 2026-05-27 会话记录
## 问题修复
### 1. MyBatis-Plus 空集合 IN 子句异常
**问题:** `selectBatchIds` 传入空集合时生成 `IN ()` 非法 SQL,导致 JSQLParser 解析失败。
**修复位置:**
- `InboundServiceImpl.listHistory()` - 供应商、仓库查询
- `OutboundServiceImpl.listHistory()` - 客户、仓库查询
**解决方案:** 使用三元表达式避免空集合查询
```java
Map<Long, String> supplierNameMap = supplierIds.isEmpty() ? new HashMap<>() :
supplierMapper.selectBatchIds(supplierIds).stream()
.collect(Collectors.toMap(Supplier::getId, Supplier::getName));
```
---
### 2. JavaScript 精度丢失问题
**问题:** 雪花算法生成的 Long 类型 ID(如 `2059467259520360450`)超出 JS 安全整数范围,前端接收后精度丢失为 `2059467259520360400`
**解决方案:** 创建 `JacksonConfig.java`,全局配置 Long 类型序列化为字符串
```java
@Configuration
public class JacksonConfig {
@Bean
public Module longToStringModule() {
return new SimpleModule()
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(long.class, ToStringSerializer.instance);
}
}
```
**效果:**
- `Long` 类型 → 字符串(`"2059467259520360450"`
- `Integer` 类型 → 保持数字(`code: 200`
---
### 3. creatorName 为 null
**根因:** `BaseEntity.creator` 字段自动填充时存的是用户昵称(如"管理员"),但查询逻辑错误地用 `creator` 的值去匹配 `sys_user.username` 字段。
**修复:**
1. `MyMetaObjectHandler.java` - 添加默认值兜底:昵称 → 登录名 → "系统"
2. `InboundServiceImpl` / `OutboundServiceImpl` - 直接使用 `creator` 字段值作为 `creatorName`
---
### 4. 安全库存字段命名
**问题:** `StockSafeQtyReqDTO.safeQty` 实际含义是最小安全库存,字段名不准确。
**修复:**
- 字段名:`safeQty``minSafeQty`
- 注释和验证提示同步更新
---
### 5. 库存详情接口填充物料信息
**需求:** `/im/stock/{materialId}` 接口需要返回物料相关信息。
**实现:**
1. 新建 `StockDetailDTO` - 包含库存、物料、仓库信息
2. `StockService.getStockDetail()` - 使用 `MaterialFillService` 填充物料信息
3. 查询仓库信息填充仓库名称
---
## 部署操作
### 测试环境 Docker 重新部署
**命令:**
```bash
cd /home/yangxuan/Projects/IdeaProjects/tiny-erp
docker compose stop app
docker compose rm -f app
docker compose build --no-cache app
docker compose up -d app
```
**状态:** ✅ 部署成功,健康检查通过
---
## 待办事项
- [x] 清理 `im_inbound_item` / `im_outbound_item` 脏数据(主表记录不存在的明细)
- [x] 考虑添加外键约束防止未来产生脏数据
- [x] 创建测试环境部署文档 → `/home/yangxuan/Projects/IdeaProjects/tiny-erp/doc/测试环境部署文档.md`
- [x] 强调 Maven 构建前提(`mvn clean install`
# 2026-05-27 会话记录
## 问题修复
### 1. MyBatis-Plus 空集合 IN 子句异常
**问题:** `selectBatchIds` 传入空集合时生成 `IN ()` 非法 SQL,导致 JSQLParser 解析失败。
**修复位置:**
- `InboundServiceImpl.listHistory()` - 供应商、仓库查询
- `OutboundServiceImpl.listHistory()` - 客户、仓库查询
**解决方案:** 使用三元表达式避免空集合查询
```java
Map<Long, String> supplierNameMap = supplierIds.isEmpty() ? new HashMap<>() :
supplierMapper.selectBatchIds(supplierIds).stream()
.collect(Collectors.toMap(Supplier::getId, Supplier::getName));
```
---
### 2. JavaScript 精度丢失问题
**问题:** 雪花算法生成的 Long 类型 ID(如 `2059467259520360450`)超出 JS 安全整数范围,前端接收后精度丢失为 `2059467259520360400`
**解决方案:** 创建 `JacksonConfig.java`,全局配置 Long 类型序列化为字符串
```java
@Configuration
public class JacksonConfig {
@Bean
public Module longToStringModule() {
return new SimpleModule()
.addSerializer(Long.class, ToStringSerializer.instance)
.addSerializer(long.class, ToStringSerializer.instance);
}
}
```
**效果:**
- `Long` 类型 → 字符串(`"2059467259520360450"`
- `Integer` 类型 → 保持数字(`code: 200`
---
### 3. creatorName 为 null
**根因:** `BaseEntity.creator` 字段自动填充时存的是用户昵称(如"管理员"),但查询逻辑错误地用 `creator` 的值去匹配 `sys_user.username` 字段。
**修复:**
1. `MyMetaObjectHandler.java` - 添加默认值兜底:昵称 → 登录名 → "系统"
2. `InboundServiceImpl` / `OutboundServiceImpl` - 直接使用 `creator` 字段值作为 `creatorName`
---
### 4. 安全库存字段命名
**问题:** `StockSafeQtyReqDTO.safeQty` 实际含义是最小安全库存,字段名不准确。
**修复:**
- 字段名:`safeQty``minSafeQty`
- 注释和验证提示同步更新
---
### 5. 库存详情接口填充物料信息
**需求:** `/im/stock/{materialId}` 接口需要返回物料相关信息。
**实现:**
1. 新建 `StockDetailDTO` - 包含库存、物料、仓库信息
2. `StockService.getStockDetail()` - 使用 `MaterialFillService` 填充物料信息
3. 查询仓库信息填充仓库名称
---
### 6. 安全库存接口统一
**需求:** 将安全库存相关接口从 `MaterialController` 统一迁移到 `StockController`
**修改内容:**
-`StockController` - 新增 3 个接口(设置、批量设置、清除安全库存)
-`StockService` / `StockServiceImpl` - 实现新增方法
-`MaterialController` - 删除 2 个安全库存接口
-`MaterialService` / `MaterialServiceImpl` - 删除相关方法
-`MaterialMapper` / `MaterialMapper.xml` - 删除相关 SQL
**新 API**
- `PUT /im/stock/safe-qty` - 设置安全库存(单个)
- `PUT /im/stock/safe-qty/batch` - 批量设置安全库存
- `PUT /im/stock/{materialId}/safe-qty/clear` - 清除安全库存
---
### 7. 库存详情接口填充 minSafeQty
**问题:** `StockServiceImpl.getStockDetail()` 漏掉了 `minSafeQty` 字段填充。
**修复:** 添加 `dto.setMinSafeQty(material.getMinSafeQty());`
---
### 8. /home/welcome 接口数据写死
**问题:** 用户名、公司名、欢迎语都是硬编码。
**修复:**
- 使用 `UserContext.getNickname()` 获取真实用户名
- 使用 `TenantContext.getTenantName()` 获取企业名称
- 保留兜底逻辑("用户"、"企业"
---
## 数据库变更
### 增量脚本执行
**脚本 1** `scripts/postgresql/fix-fin-add-order-date.sql`
- `fin_ar` 表:添加 `order_date` 字段(DATE 类型)
- `fin_ap` 表:添加 `order_date` 字段(DATE 类型)
- 数据初始化:将 `create_time` 转换为日期赋值给 `order_date`
**脚本 2** `scripts/postgresql/fix-write-off-add-updater.sql`
- `fin_ar_write_off` 表:添加 `updater``update_time` 字段
- `fin_ap_write_off` 表:添加 `updater``update_time` 字段
- 数据初始化:将 `creator`/`create_time` 赋值给 `updater`/`update_time`
**执行方式:**
```bash
docker compose exec db psql -U postgres -d tinyerp \
-f /docker-entrypoint-initdb.d/migrations/20260527_add_column.sql
```
---
## 文档更新
### 1. 部署文档合并
- ✅ 将 `~/tiny/测试环境部署文档.md` 合并到 `DOCKER.md`
- ✅ 新增 4 个部署场景(首次部署、重新部署、只重启、彻底重置)
- ✅ 强调 Maven 构建前提(`mvn clean install -DskipTests`
- ✅ 完善故障排查表格
- ❌ 删除重复文档 `~/tiny/测试环境部署文档.md`
### 2. 库存接口文档
- ✅ 创建 `doc/stock-api.md`
- 包含 6 个库存管理接口 + 1 个相关接口
- 字段说明、物料类型枚举、注意事项
---
## 部署操作
### 测试环境 Docker 重新部署
**命令:**
```bash
cd /home/yangxuan/Projects/IdeaProjects/tiny-erp
mvn clean install -DskipTests
docker compose stop app
docker compose rm -f app
docker compose build --no-cache app
docker compose up -d app
```
**状态:** ✅ 部署成功,健康检查通过
---
## 经验教训
1. **Maven 构建前提**Docker 镜像构建复制本地 `target/` 目录,必须先执行 `mvn clean install`
2. **Long 类型精度丢失**:雪花算法 ID 超出 JS 安全范围,全局序列化为字符串
3. **空集合 IN 子句**MyBatis-Plus `selectBatchIds` 不处理空集合,需要手动判断
4. **creator 字段含义**:自动填充存的是昵称,不是用户名,查询时要注意匹配字段
5. **接口职责分离**:库存相关操作统一在 `StockController`,物料相关在 `MaterialController`
---
## 数据库环境(双数据库)
| 环境 | 类型 | 端口 | 连接方式 | sys_tenant.tenant_name |
|------|------|------|----------|------------------------|
| **测试库** | Docker 容器 tiny-erp-db (postgres:18.1) | 未暴露 | 仅 Docker 内部访问 (db:5432) | 默认租户 → 已改为**水晶科技有限公司** |
| **本地库** | WSL apt 安装的 pgsql 16 | localhost:31983 | IntelliJ / psql 直接连接 | 水晶科技有限公司 |
- Docker 应用 `tiny-erp-app` 连接的是**测试库**(Docker 内部 `tiny-erp-db`
- `application-local.yml``localhost:31983`(本地库),绑定 `server.port=8081`
- `application-test.yml``db:5432`(测试库),Docker 运行时通过 `SPRING_PROFILES_ACTIVE=test` 激活
## 待办事项
- [ ] 更新 Java 实体类(`FinAr``FinAp``FinArWriteOff``FinApWriteOff`
- [ ] 记录数据库变更日志到 `doc/数据库变更日志.md`
- [ ] 考虑添加外键约束防止 `im_inbound_item` / `im_outbound_item` 脏数据
---
## 新增功能
### 9. 物料选择器返回上次单价
**需求:** 采购入库/销售出库时单价必填,物料选择器返回上次单价供用户参考。
**修改内容:**
1.`StockPageDTO` - 新增 `lastInboundPrice``lastOutboundPrice` 字段
2.`Material` 实体 - 新增 `lastInboundPrice``lastOutboundPrice` 字段(数据库已有 `last_inbound_price``last_outbound_price`
3.`MaterialSelectorServiceImpl` - 实现批量查询和填充逻辑
- `queryLastInboundPrices()` - 批量查询上次入库单价
- `queryLastOutboundPrices()` - 批量查询上次出库单价
- `pageInboundMaterial()` / `pageOutboundMaterial()` - 填充单价字段
- 常用物料场景也支持单价填充
**API 响应示例:**
```json
{
"materialId": 4,
"materialName": "测试物料 A",
"lastInboundPrice": 12.50, // 采购入库参考
"lastOutboundPrice": 18.80 // 销售出库参考
}
```
**前端使用:**
- 采购入库单:显示 `lastInboundPrice` 作为参考,单价必填
- 销售出库单:显示 `lastOutboundPrice` 作为参考,单价必填
- 后端自动填充逻辑:如果用户未填单价,保存时自动使用上次单价
**测试验证:** ✅ 66 个集成测试全部通过(物料 20 + 入库 23 + 出库 23
---
### 10. 首页动态数量格式化
**问题:** 首页动态显示的数量带有末尾多余的 0(如 `10.5000 个`)。
**修复:** `HomeServiceImpl.getLatestNews()` 中使用 `stripTrailingZeros().toPlainString()` 格式化数量
```java
// 修改前
String.format("%s入库%s%s", materialName, item.getQuantity(), unit)
// 修改后
String.format("%s入库%s%s", materialName, item.getQuantity().stripTrailingZeros().toPlainString(), unit)
```
**效果对比:**
| 修改前 | 修改后 |
|--------|--------|
| `测试物料入库 10.5000 个` | `测试物料入库 10.5 个` |
| `测试物料出库 100.0000 个` | `测试物料出库 100 个` |
---
## 问题修复
### 11. operator 字段违反 NOT NULL 约束
**问题:** 出入库单自动生成应收/应付时,`fin_ar_receipt` 表的 `operator` 字段为 null,导致插入失败。
**错误日志:**
```
ERROR: null value in column "operator" of relation "fin_ar_receipt" violates not-null constraint
```
**根因:** `MyMetaObjectHandler` 自动填充处理器没有填充 `operator` 字段,当 `UserContext.getUserName()` 返回 null 时导致插入失败。
**修复方案:**`MyMetaObjectHandler.insertFill()` 中添加 `operator` 字段的自动填充,但**仅在用户未设置时才填充**:
```java
// 操作人(operator 字段,用于财务收款/付款单)- 仅当未设置时自动填充
String operatorName = UserContext.getUserName();
if (operatorName == null || operatorName.isEmpty()) {
operatorName = "管理员";
}
// 检查是否已有值,有值则不覆盖
if (metaObject.hasGetter("operator") && metaObject.getValue("operator") == null) {
this.strictInsertFill(metaObject, "operator", String.class, operatorName);
}
```
**行为说明:**
- ✅ 用户手动设置 `operator` → 保留用户设置的值
- ✅ 用户未设置 `operator` → 自动填充当前登录用户(兜底"管理员")
- ✅ 自动生成场景(无用户上下文)→ 自动填充"管理员"
**影响范围:** 适用于 `fin_ar_receipt`(收款单)和 `fin_ap_payment`(付款单)等需要 `operator` 的表
---
## 测试进展
### 集成测试覆盖率
| 测试类 | 测试数 | 通过 | 失败 | 覆盖率 |
|--------|--------|------|------|--------|
| `MaterialControllerTest` | 20 | 20 | 0 | 100% ✅ |
| `InboundControllerTest` | 23 | 23 | 0 | 100% ✅ |
| `OutboundControllerTest` | 23 | 23 | 0 | 100% ✅ |
| **总计** | **66** | **66** | **0** | **100%** ✅ |
**测试覆盖的功能:**
- ✅ 物料 CRUD、分页查询、详情查询
- ✅ 采购入库单保存、自动填充单价、更新物料最后入库价
- ✅ 销售出库单保存、自动填充单价、更新物料最后出库价
- ✅ 编码唯一性校验、必填字段校验、BigDecimal 精度比较
---
## 经验教训
1. **BigDecimal 比较**:测试断言使用 `compareTo()` 而非 `equals()`,避免精度差异(`10.50` vs `10.5000`
2. **自动填充优先级**:用户手动设置的值优先于自动填充,`MyMetaObjectHandler` 需要先检查字段是否已有值
3. **批量查询优化**:物料选择器使用 `selectBatchIds` 批量查询上次单价,避免 N+1 查询问题
4. **数量格式化**`BigDecimal` 转字符串时使用 `stripTrailingZeros().toPlainString()` 去除末尾多余的 0,同时避免科学计数法
---
## 待办事项
- [ ] 前端对接物料选择器接口,显示上次单价参考
- [ ] 验证采购入库/销售出库单价必填的前端校验
- [ ] 运行完整测试套件确保无回归
- [ ] 记录数据库变更日志到 `doc/数据库变更日志.md`
-330
View File
@@ -1,330 +0,0 @@
## 10:50 — AI 调用记录方案评估
**话题:** 记录 AI 调用(session_id, tokens, 返回结果),复用操作日志机制
**评估结论:方案 A — 扩展 OperLog**
- `sys_oper_log` 新增 5 字段:`ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`
- `module` 复用为 `"AI识别"` / `"AI对话"` 区分业务
- 复用现有 OperLog 全部基础设施(service/mapper/controller/分页/查询)
- 工作量最小,约 20min
- 方案已确认,待实现
## 10:50 — Git 约定提醒
提示 commit 时必须附带 commit message,让用户可直接复制运行。
## 11:08~11:18 — AI 调用记录实现 ✅
**改动点:**
1. `scripts/postgresql/10-system.sql` — DDL 新增 `ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`
2. `scripts/postgresql/fix-ai-oper-log.sql` — 迁移脚本(新增)
3. `OperLog.java` — 实体添加 5 个对应字段
4. `AiServiceImpl.java` — 注入 `OperLogService`,在 `chatText()`/`chatWithImages()` 调用前后记录日志(含 sessionId, tokens, 耗时, 输入/输出摘要)
5. `AiChatResponseDTO` — 新增 `sessionId` 字段
6. `DeepSeekChatRequestDTO` — 新增 `sessionId` 字段(`@JsonIgnore`,仅用于日志传递)
**执行迁移:** 本地库(localhost:31983)跑 `fix-ai-oper-log.sql`
**测试结果:**`Tests run: 2, Failures: 0, Errors: 0` — 日志成功写入 sys_oper_logai_model=qwen3.5-plus 等字段正确)
## 13:00~13:06 — 测试库执行 AI 迁移 ✅
- 本地 WSL Docker 可连接测试库(`docker exec -i tiny-erp-db psql -U postgres -d tinyerp`
- 执行 `fix-ai-oper-log.sql`5 个 AI 字段(`ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`)已添加
- 验证本地库(localhost:31983)和测试库(Docker db:5432)字段均存在 ✅
## 13:08~13:10 — 日志文件冲突问题 → 方案A
**问题:** IDEA 和 Docker 都在 WSL 同一机器运行,`./logs/` 会互相覆盖
**方案A** docker-compose 挂载路径改为 `./logs-docker:/app/logs`
- `.gitignore` 添加 `logs-docker/`
- `Dockerfile` 保留 root 运行(无 `USER appuser`
- 已实施 ✅
## 13:11~13:13 — deploy-test.sh 脚本
创建 `deploy-test.sh` 一键部署脚本:
1. `mvn clean install -DskipTests`
2. `docker compose stop/rm/build/up app`
3. `curl health` 自动验证(失败重试 15s
## 13:14~13:22 — 测试目录规范化
**问题:** 大部分测试包路径缺少 `module` 层级,与源码不一致
- 移动所有测试到 `com.witsoft.erp.module.*` 包下
- 统一先删旧包(git rm)、再建新包、再写入
- 运行全量测试通过 ✅
- `test.base.BaseControllerTest` 保留在 `com.witsoft.erp.test.base`(基建归 test,不归 module
## 13:38~14:11 — docs/ 目录全面清理
**整理方向:**
| 操作 | 说明 |
|------|------|
| ✅ 合并 API 规范到项目规范.md | 删除 `docs/API/` |
| ✅ 删除 `docs/数据库/` | 以 SQL 脚本为唯一来源 |
| ✅ 文档按模块移入对应子目录 | `06-AI单据识别需求.md``需求/AI模块``物料信息填充公共服务总结.md``设计/主数据模块` |
| ✅ 按模块独立编号 | 全局连续 → 每个模块 01- 起编 |
| ✅ 测试文件重排序 | 按 登录→首页→物料→字典→入库出库→库存盘点→操作日志 排列 |
| ✅ README.md 同步 | 目录结构、版本历史逐一同步,标注"(预留)"空目录 |
**编号规则变更:** 跨模块连续编号(旧)→ 按模块独立编号(新),新增文档只加模块内序号,不碰其他模块。
## 14:14 — UserContext 使用指南.md 文件缺失
文档中引用 `设计/系统模块/UserContext 使用指南.md`,但实际文件不存在(被 `yangxuan/``docs/` 重命名遗漏)。已补充。
## 10:50 — AI 调用记录方案评估
**话题:** 记录 AI 调用(session_id, tokens, 返回结果),复用操作日志机制
**评估结论:方案 A — 扩展 OperLog**
- `sys_oper_log` 新增 5 字段:`ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`
- `module` 复用为 `"AI识别"` / `"AI对话"` 区分业务
- 复用现有 OperLog 全部基础设施(service/mapper/controller/分页/查询)
- 工作量最小,约 20min
- 方案已确认,待实现
## 10:50 — Git 约定提醒
提示 commit 时必须附带 commit message,让用户可直接复制运行。
## 11:08~11:18 — AI 调用记录实现 ✅
**改动点:**
1. `scripts/postgresql/10-system.sql` — DDL 新增 `ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`
2. `scripts/postgresql/fix-ai-oper-log.sql` — 迁移脚本(新增)
3. `OperLog.java` — 实体添加 5 个对应字段
4. `AiServiceImpl.java` — 注入 `OperLogService`,在 `chatText()`/`chatWithImages()` 调用前后记录日志(含 sessionId, tokens, 耗时, 输入/输出摘要)
5. `AiChatResponseDTO` — 新增 `sessionId` 字段
6. `DeepSeekChatRequestDTO` — 新增 `sessionId` 字段(`@JsonIgnore`,仅用于日志传递)
**执行迁移:** 本地库(localhost:31983)跑 `fix-ai-oper-log.sql`
**测试结果:**`Tests run: 2, Failures: 0, Errors: 0` — 日志成功写入 sys_oper_logai_model=qwen3.5-plus 等字段正确)
## 13:00~13:06 — 测试库执行 AI 迁移 ✅
- 本地 WSL Docker 可连接测试库(`docker exec -i tiny-erp-db psql -U postgres -d tinyerp`
- 执行 `fix-ai-oper-log.sql`5 个 AI 字段(`ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`)已添加
- 验证本地库(localhost:31983)和测试库(Docker db:5432)字段均存在 ✅
## 13:08~13:10 — 日志文件冲突问题 → 方案A
**问题:** IDEA 和 Docker 都在 WSL 同一机器运行,`./logs/` 会互相覆盖
**方案A** docker-compose 挂载路径改为 `./logs-docker:/app/logs`
- `.gitignore` 添加 `logs-docker/`
- `Dockerfile` 保留 root 运行(无 `USER appuser`
- 已实施 ✅
## 13:11~13:13 — deploy-test.sh 脚本
创建 `deploy-test.sh` 一键部署脚本:
1. `mvn clean install -DskipTests`
2. `docker compose stop/rm/build/up app`
3. `curl health` 自动验证(失败重试 15s
## 13:14~13:22 — 测试目录规范化
**问题:** 大部分测试包路径缺少 `module` 层级,与源码不一致
- 移动所有测试到 `com.witsoft.erp.module.*` 包下
- 统一先删旧包(git rm)、再建新包、再写入
- 运行全量测试通过 ✅
- `test.base.BaseControllerTest` 保留在 `com.witsoft.erp.test.base`(基建归 test,不归 module
## 13:38~14:11 — docs/ 目录全面清理
**整理方向:**
| 操作 | 说明 |
|------|------|
| ✅ 合并 API 规范到项目规范.md | 删除 `docs/API/` |
| ✅ 删除 `docs/数据库/` | 以 SQL 脚本为唯一来源 |
| ✅ 文档按模块移入对应子目录 | `06-AI单据识别需求.md``需求/AI模块``物料信息填充公共服务总结.md``设计/主数据模块` |
| ✅ 按模块独立编号 | 全局连续 → 每个模块 01- 起编 |
| ✅ 测试文件重排序 | 按 登录→首页→物料→字典→入库出库→库存盘点→操作日志 排列 |
| ✅ README.md 同步 | 目录结构、版本历史逐一同步,标注"(预留)"空目录 |
**编号规则变更:** 跨模块连续编号(旧)→ 按模块独立编号(新),新增文档只加模块内序号,不碰其他模块。
## 14:14 — UserContext 使用指南.md 文件缺失
文档中引用 `设计/系统模块/UserContext 使用指南.md`,但实际文件不存在(被 `yangxuan/``docs/` 重命名遗漏)。已补充。
## 14:18 — docs/测试 HTTP 文件重排序 ✅
按执行依赖逻辑重新编号:
| 序号 | 文件 | 说明 |
|------|------|------|
| 00 | 登录登出 | 先拿 token |
| 01 | 首页 API 测试 | 仪表盘概览 |
| 02 | 物料分页 | 基础数据查询 |
| 03 | 数据字典与映射 | 字典+翻译 |
| 04 | 入库出库 | 核心业务流程 |
| 05 | 实时库存&盘点 | 库存状态 |
| 06 | 操作日志 | 审计兜底 |
同步更新了 `docs/README.md`
## 14:24 — scripts/postgresql 目录组织讨论
**话题:** 杨轩问脚本目录是否可以按 ddl/dml/init 或按模块区分。
**分析结果:** 当前脚本目录的问题:
1. 编号混乱(00/03/10/20/21/22...99,无一致规则)
2. DDL/DML 混在一起(如 10-system.sql 既建表又插数据)
3. fix- 前缀不统一(26-material-last-price.sql 也是 ALTER 但没用 fix- 前缀)
**方案A(用户选中):** 二级目录 `ddl/``dml/``migration/``mock/`,根目录保留一个 `init.sql` 通过 `\i` 引用子目录文件(因为 `docker-entrypoint-initdb.d` 只处理扁平 .sql 文件)。
**待实现:** [not yet started — compaction happened before implementation]
## 10:50 — AI 调用记录方案评估
**话题:** 记录 AI 调用(session_id, tokens, 返回结果),复用操作日志机制
**评估结论:方案 A — 扩展 OperLog**
- `sys_oper_log` 新增 5 字段:`ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`
- `module` 复用为 `"AI识别"` / `"AI对话"` 区分业务
- 复用现有 OperLog 全部基础设施(service/mapper/controller/分页/查询)
- 工作量最小,约 20min
- 方案已确认,待实现
## 10:50 — Git 约定提醒
提示 commit 时必须附带 commit message,让用户可直接复制运行。
## 11:08~11:18 — AI 调用记录实现 ✅
**改动点:**
1. `scripts/postgresql/10-system.sql` — DDL 新增 `ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`
2. `scripts/postgresql/fix-ai-oper-log.sql` — 迁移脚本(新增)
3. `OperLog.java` — 实体添加 5 个对应字段
4. `AiServiceImpl.java` — 注入 `OperLogService`,在 `chatText()`/`chatWithImages()` 调用前后记录日志(含 sessionId, tokens, 耗时, 输入/输出摘要)
5. `AiChatResponseDTO` — 新增 `sessionId` 字段
6. `DeepSeekChatRequestDTO` — 新增 `sessionId` 字段(`@JsonIgnore`,仅用于日志传递)
**执行迁移:** 本地库(localhost:31983)跑 `fix-ai-oper-log.sql`
**测试结果:**`Tests run: 2, Failures: 0, Errors: 0` — 日志成功写入 sys_oper_logai_model=qwen3.5-plus 等字段正确)
## 13:00~13:06 — 测试库执行 AI 迁移 ✅
- 本地 WSL Docker 可连接测试库(`docker exec -i tiny-erp-db psql -U postgres -d tinyerp`
- 执行 `fix-ai-oper-log.sql`5 个 AI 字段(`ai_session_id`, `ai_model`, `prompt_tokens`, `completion_tokens`, `total_tokens`)已添加
- 验证本地库(localhost:31983)和测试库(Docker db:5432)字段均存在 ✅
## 13:08~13:10 — 日志文件冲突问题 → 方案A
**问题:** IDEA 和 Docker 都在 WSL 同一机器运行,`./logs/` 会互相覆盖
**方案A** docker-compose 挂载路径改为 `./logs-docker:/app/logs`
- `.gitignore` 添加 `logs-docker/`
- `Dockerfile` 保留 root 运行(无 `USER appuser`
- 已实施 ✅
## 13:11~13:13 — deploy-test.sh 脚本
创建 `deploy-test.sh` 一键部署脚本:
1. `mvn clean install -DskipTests`
2. `docker compose stop/rm/build/up app`
3. `curl health` 自动验证(失败重试 15s
## 13:14~13:22 — 测试目录规范化
**问题:** 大部分测试包路径缺少 `module` 层级,与源码不一致
- 移动所有测试到 `com.witsoft.erp.module.*` 包下
- 统一先删旧包(git rm)、再建新包、再写入
- 运行全量测试通过 ✅
- `test.base.BaseControllerTest` 保留在 `com.witsoft.erp.test.base`(基建归 test,不归 module
## 13:38~14:11 — docs/ 目录全面清理
**整理方向:**
| 操作 | 说明 |
|------|------|
| ✅ 合并 API 规范到项目规范.md | 删除 `docs/API/` |
| ✅ 删除 `docs/数据库/` | 以 SQL 脚本为唯一来源 |
| ✅ 文档按模块移入对应子目录 | `06-AI单据识别需求.md``需求/AI模块``物料信息填充公共服务总结.md``设计/主数据模块` |
| ✅ 按模块独立编号 | 全局连续 → 每个模块 01- 起编 |
| ✅ 测试文件重排序 | 按 登录→首页→物料→字典→入库出库→库存盘点→操作日志 排列 |
| ✅ README.md 同步 | 目录结构、版本历史逐一同步,标注"(预留)"空目录 |
**编号规则变更:** 跨模块连续编号(旧)→ 按模块独立编号(新),新增文档只加模块内序号,不碰其他模块。
## 14:14 — UserContext 使用指南.md 文件缺失
文档中引用 `设计/系统模块/UserContext 使用指南.md`,但实际文件不存在(被 `yangxuan/``docs/` 重命名遗漏)。已补充。
## 14:18 — docs/测试 HTTP 文件重排序 ✅
按执行依赖逻辑重新编号:
| 序号 | 文件 | 说明 |
|------|------|------|
| 00 | 登录登出 | 先拿 token |
| 01 | 首页 API 测试 | 仪表盘概览 |
| 02 | 物料分页 | 基础数据查询 |
| 03 | 数据字典与映射 | 字典+翻译 |
| 04 | 入库出库 | 核心业务流程 |
| 05 | 实时库存&盘点 | 库存状态 |
| 06 | 操作日志 | 审计兜底 |
同步更新了 `docs/README.md`
## 14:24 — scripts/postgresql 目录组织讨论
**话题:** 杨轩问脚本目录是否可以按 ddl/dml/init 或按模块区分。
**分析结果:** 当前脚本目录的问题:
1. 编号混乱(00/03/10/20/21/22...99,无一致规则)
2. DDL/DML 混在一起(如 10-system.sql 既建表又插数据)
3. fix- 前缀不统一(26-material-last-price.sql 也是 ALTER 但没用 fix- 前缀)
**方案A(用户选中):** 二级目录 `ddl/``dml/``migration/``mock/`,根目录保留一个 `init.sql` 通过 `\i` 引用子目录文件(因为 `docker-entrypoint-initdb.d` 只处理扁平 .sql 文件)。
**待实现:** [not yet started — compaction happened before implementation]
## 14:47~15:30 — AI 接口文档 + 测试文件 ✅
**AI 接口文档:** `docs/需求/AI模块/02-AI单据识别接口文档.md`
**AI 测试文件:** `docs/测试/07-AI单据识别.http`
- 解释了 exactMatch=false 仍有 materialId 的语义:近似匹配自动选最佳,前端标黄提示
- `docs/README.md` 同步更新
**提交策略:** 用户自行处理敏感配置文件的版本管理(`application.yml``application-local.yml``scripts/idea/http-client.env.json`
## 15:30~16:20 — 物料选择器 excludedMaterialIds 实现 ✅
**需求:** 出库/入库选择器支持排除已选物料
**改动点:**
1. `MaterialSelectorReqDTO` — 新增 `excludedMaterialIds``List<Long>`
2. `MaterialServiceImpl` — 4 个分页/计数方法加 `excludedMaterialIds` 参数
3. `StockMapper.xml` — 4 个 SQL 加 `<if test="excludedMaterialIds != null and excludedMaterialIds.size() > 0"> AND s.material_id NOT IN ...</if>`
4. `MaterialSelectorServiceImpl` — 新增 `filterExcludedIds()` 私有方法做内存过滤 + queryByIds 方法加上排除逻辑
**MyBatis <if> 行为验证:**
- `null` → false,跳过 NOT IN
- `[]`(空列表)→ `size() > 0` 为 false,跳过 NOT IN
- `[1, 2]` → 进 NOT INWHERE 过滤
**测试覆盖:** 集成测试三类场景全部通过 ✅
- `testMaterialSelector_empty`(传 null)✅
- `testMaterialSelector_emptyExcludeList`(传 `[]`)✅
- `testMaterialSelector_withExcludedIds`(传实际 ID,验证排除正确)✅
## 15:55 — 测试编号冲突修复
**问题:** 新增物料选择器测试插入 `@Order(4)/@Order(5)` 后,原有的 `@Order(4)`(新增出库单)和 `@Order(5)`(明细为空)未重编号,导致 `@Order(4)/@Order(5)/@Order(7)` 重复
**修复:** 将所有 `@Order(n)` 增加 2n>=4 的改成 n+2),最后 2 个测试增加 2。涉及约 20 个测试方法。
## 16:05 — 测试 bug 修复
**问题:** 排除测试中 `assertFalse(list.stream().anyMatch(s -> s.getId().equals(excludedId)))` 失败
**原因:** `StockPageDTO.getId()` 返回库存记录 ID`s.id`),而非物料 ID`s.material_id`)。SQL NOT IN 排除的是 `material_id`,但测试用 `getId()` 取了库存记录 ID
**修复:** 改用 `getMaterialId()` 验证排除
-14
View File
@@ -1,14 +0,0 @@
# 2026-07-09
## DailyHotJob 改造完成
- planner 派发任务 → backend 执行改造 → planner review 通过,共 7 个 commit
- 涉及:异常传播、租户注解、批量查重插入、并发搜索、文件分片、时间窗口、Redis Key 可配置
- 任务文档存档于 `tasks/dailyhot-job-fix-tasks.md`
## 教训:不能越权
- 杨轩明确强调:**不能越权** — 不要替用户做决定,不要自行启动或派发任务,由用户决策后再执行
## 编译修复
- `JavInfoMapper.insertBatch(Collection<JavInfoDO>)` 返回类型 `int``Boolean`(与父类 `BaseMapperX` 一致)
- `JackettController.dailyHot()``throws Exception`(顺带修复同一 module 编译错误)
- Maven 编译验证通过
@@ -0,0 +1,17 @@
{
"version": 1,
"registry": "https://clawhub.ai",
"slug": "qiushi-openclaw-skill",
"ownerHandle": "skytodmoon",
"installedVersion": "1.0.0",
"installedAt": 1785745381570,
"artifact": {
"kind": "archive",
"sha256": "1e2d3712d2974143449c9e47b0379725a954794c498727799f782ac7b1db7a49",
"integrity": "sha256-Hi03EtKXQUNEnJ5HsDeXJalUeUxJhyd5n3gqx7Hbekk="
},
"skillFile": {
"path": "SKILL.md",
"sha256": "b21d933b7f61584d2254fba25fd531c16f19e33e10016ddfbdea1a5e2d5d6d25"
}
}
@@ -0,0 +1,116 @@
# 求是 OpenClaw Skills
## 项目介绍
求是 OpenClaw Skills 是基于毛泽东思想方法论的 AI Agent 技能集合,按照 OpenClaw 技能格式进行改造,旨在为 AI 提供系统化的思考和行动框架。
## 技能列表
| 技能名称 | 核心要义 | 适用场景 |
|---------|---------|---------|
| arming-thought | 武装思想,实事求是总原则 | 对话开始时建立方法论基础 |
| contradiction-analysis | 矛盾分析法,抓主要矛盾 | 复杂问题分析 |
| practice-cognition | 实践认识论,实践→认识→再实践 | 方案验证与迭代 |
| investigation-first | 调查研究,没有调查就没有发言权 | 决策前的信息收集 |
| mass-line | 群众路线,从群众中来到群众中去 | 反馈整合与方案验证 |
| criticism-self-criticism | 批评与自我批评,惩前毖后治病救人 | 工作审视与质量改进 |
| protracted-strategy | 持久战略,战略上藐视战术上重视 | 长期复杂任务规划 |
| concentrate-forces | 集中兵力,伤其十指不如断其一指 | 优先级决策与资源聚焦 |
| spark-prairie-fire | 星火燎原,建立根据地不做流寇 | 从零开始的发展策略 |
| overall-planning | 统筹兼顾,调动一切积极因素 | 多目标平衡与权衡 |
| workflows | 工作流组合,多种方法串联 | 复杂任务的流程设计 |
## 安装方法
### 手动安装
1. 将 `qiushi-openclaw-skills` 目录复制到 OpenClaw 的技能目录:
```bash
cp -r qiushi-openclaw-skills ~/.openclaw/skills/
```
2. 重启 OpenClaw 或刷新技能列表。
### ClawHub 安装(未来支持)
未来将支持通过 ClawHub 一键安装。
## 技能结构
每个技能都遵循 OpenClaw 的标准结构:
```
skill-name/
└── SKILL.md # 技能定义文件
```
### SKILL.md 结构
```yaml
---
name: skill-name
description: "技能描述,决定 AI 何时自动触发此技能"
tools: [] # 技能需要使用的工具
---
# 技能名称
## 触发条件
当...时触发此技能。
## 执行步骤
1. 第一步...
2. 第二步...
## 核心原则
...
## 不适用场景
- ...
## 应用场景
- ...
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| ... | ... |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. ...
## 与其他 skill 的关系
- ...
```
## 使用方法
1. **自动触发**OpenClaw 会根据技能的 `description` 字段自动判断何时触发相应技能。
2. **手动触发**:在 OpenClaw 中使用 `/skill-name` 命令手动触发技能。
3. **工作流组合**:使用 `workflows` 技能组合多个技能,形成完整的工作流程。
## 核心原则
- **实事求是**:从客观存在着的实际事物出发,让事实规定判断,让现实修正理论。
- **矛盾分析**:识别矛盾、抓住主要矛盾、区分矛盾性质。
- **实践认识论**:实践→认识→再实践,螺旋上升。
- **调查研究**:没有调查就没有发言权。
- **群众路线**:从群众中来,到群众中去。
- **批评与自我批评**:惩前毖后,治病救人。
- **持久战略**:战略上藐视,战术上重视。
- **集中兵力**:伤其十指不如断其一指。
- **星火燎原**:建立根据地,不做流寇。
- **统筹兼顾**:调动一切积极因素。
## 注意事项
- 本项目的方法论来源于毛泽东思想,旨在为 AI 提供科学的思考和行动框架。
- 技能的触发条件和执行步骤已经过优化,适合 AI 理解和执行。
- 可以根据具体任务需求,灵活组合使用不同的技能。
## 许可证
MIT License
@@ -0,0 +1,50 @@
---
name: qiushi-openclaw-skills
description: "求是 OpenClaw Skills 是基于毛泽东思想方法论的 AI Agent 技能集合,按照 OpenClaw 技能格式进行改造,旨在为 AI 提供系统化的思考和行动框架。"
tools: []
---
# 求是 OpenClaw Skills
## 项目介绍
求是 OpenClaw Skills 是基于毛泽东思想方法论的 AI Agent 技能集合,按照 OpenClaw 技能格式进行改造,旨在为 AI 提供系统化的思考和行动框架。
## 技能列表
| 技能名称 | 核心要义 | 适用场景 |
|---------|---------|---------|
| arming-thought | 武装思想,实事求是总原则 | 对话开始时建立方法论基础 |
| contradiction-analysis | 矛盾分析法,抓主要矛盾 | 复杂问题分析 |
| practice-cognition | 实践认识论,实践→认识→再实践 | 方案验证与迭代 |
| investigation-first | 调查研究,没有调查就没有发言权 | 决策前的信息收集 |
| mass-line | 群众路线,从群众中来到群众中去 | 反馈整合与方案验证 |
| criticism-self-criticism | 批评与自我批评,惩前毖后治病救人 | 工作审视与质量改进 |
| protracted-strategy | 持久战略,战略上藐视战术上重视 | 长期复杂任务规划 |
| concentrate-forces | 集中兵力,伤其十指不如断其一指 | 优先级决策与资源聚焦 |
| spark-prairie-fire | 星火燎原,建立根据地不做流寇 | 从零开始的发展策略 |
| overall-planning | 统筹兼顾,调动一切积极因素 | 多目标平衡与权衡 |
| workflows | 工作流组合,多种方法串联 | 复杂任务的流程设计 |
## 核心原则
- **实事求是**:从客观存在着的实际事物出发,让事实规定判断,让现实修正理论。
- **矛盾分析**:识别矛盾、抓住主要矛盾、区分矛盾性质。
- **实践认识论**:实践→认识→再实践,螺旋上升。
- **调查研究**:没有调查就没有发言权。
- **群众路线**:从群众中来,到群众中去。
- **批评与自我批评**:惩前毖后,治病救人。
- **持久战略**:战略上藐视,战术上重视。
- **集中兵力**:伤其十指不如断其一指。
- **星火燎原**:建立根据地,不做流寇。
- **统筹兼顾**:调动一切积极因素。
## 安装方法
```bash
clawhub install qiushi-openclaw-skills
```
## 许可证
MIT License
@@ -0,0 +1,6 @@
{
"ownerId": "kn77hfjtjjwht588zc4scw4qr582vrc6",
"slug": "qiushi-openclaw-skill",
"version": "1.0.0",
"publishedAt": 1775635456843
}
@@ -0,0 +1,59 @@
# 武装思想
## 技能介绍
武装思想是求是 OpenClaw Skills 系列中的核心技能,在每次新的顶层对话开始时自动调用,用于建立"实事求是"的总原则,并在明确适用时为后续任务选择下游技能。
## 核心功能
- **实事求是总原则**:先看事实,再下判断,让事实规定判断,让现实修正理论
- **技能调度**:根据任务需求自动选择合适的下游技能
- **行为规范**:提供可观测的行为准则,确保 AI 行为符合方法论要求
## 触发条件
当开始新的顶层对话时触发,用于建立方法论基础和选择下游技能。
## 执行步骤
1. 应用"实事求是"总原则:先看事实,再下判断
2. 评估当前任务是否需要调用下游技能
3. 如需要,选择最适合的技能进行调用
## 技能映射
| 遇到的情况 | 应调用的 skill |
|-----------|---------------|
| 面对复杂问题,不知从何入手 | contradiction-analysis |
| 需要验证方案或迭代改进 | practice-cognition |
| 要做决策但信息不足 | investigation-first |
| 需要收集多方意见或整合多源信息 | mass-line |
| 完成工作后需要审视质量 | criticism-self-criticism |
| 面对长期复杂任务 | protracted-strategy |
| 多个任务争夺注意力 | concentrate-forces |
| 从零开始,资源有限 | spark-prairie-fire |
| 多个目标需要平衡 | overall-planning |
| 一个任务明确需要多种方法串联 | workflows |
## 不适用场景
- 子 agent 执行单一具体任务时
- 用户需求非常具体,且执行路径单一明确
- 只是一次性简单输出,不涉及调查、取舍、验证或复盘
- 宿主平台已经在执行等价流程
## 指令优先级
1. 用户的明确指示
2. 宿主平台的系统规则与安全约束
3. qiushi skills 作为补充的方法论框架
## 安装方法
```bash
clawhub install arming-thought
```
## 许可证
MIT License
@@ -0,0 +1,54 @@
---
name: arming-thought
description: "在每次新的顶层对话开始时自动调用,用于建立'实事求是'的总原则,并在明确适用时为后续任务选择下游 skill"
tools: []
---
# 武装思想
## 触发条件
当开始新的顶层对话时触发,用于建立方法论基础和选择下游技能。
## 执行步骤
1. 应用"实事求是"总原则:先看事实,再下判断
2. 评估当前任务是否需要调用下游技能
3. 如需要,选择最适合的技能进行调用
## 总原则:实事求是
"'实事'就是客观存在着的一切事物,'是'就是客观事物的内部联系,即规律性,'求'就是我们去研究。" —— 毛泽东《改造我们的学习》
**核心行为规则:**
- 不空谈,看事实:每个结论后面附具体依据
- 验证才算完成:声称"完成"之前执行验证动作
- 承认不知道:遇到不确定信息时,明确标注"需要进一步确认"
- 遇阻探原因:遇到失败时说明原因、补调查或更换路径
## 调度规则
只有在下列任一条件成立时,才调用下游 skill:
- 任务明显匹配某个 skill 的触发条件
- 当前结果质量会因为该 skill 明显提升
- 你已经遇到阻塞,需要一个明确的方法框架来推进
## 技能映射
| 遇到的情况 | 应调用的 skill |
|-----------|---------------|
| 面对复杂问题,不知从何入手 | contradiction-analysis |
| 需要验证方案或迭代改进 | practice-cognition |
| 要做决策但信息不足 | investigation-first |
| 需要收集多方意见或整合多源信息 | mass-line |
| 完成工作后需要审视质量 | criticism-self-criticism |
| 面对长期复杂任务 | protracted-strategy |
| 多个任务争夺注意力 | concentrate-forces |
| 从零开始,资源有限 | spark-prairie-fire |
| 多个目标需要平衡 | overall-planning |
| 一个任务明确需要多种方法串联 | workflows |
## 不要过度调用
- 用户需求非常具体,且执行路径单一明确
- 只是一次性简单输出,不涉及调查、取舍、验证或复盘
- 宿主平台已经在执行等价流程
## 指令优先级
1. 用户的明确指示
2. 宿主平台的系统规则与安全约束
3. qiushi skills 作为补充的方法论框架
@@ -0,0 +1,13 @@
{
"name": "arming-thought",
"version": "1.0.0",
"displayName": "武装思想",
"description": "在每次新的顶层对话开始时自动调用,用于建立'实事求是'的总原则,并在明确适用时为后续任务选择下游 skill",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "实事求是"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,79 @@
# 集中兵力
## 技能介绍
集中兵力是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《中国革命战争的战略问题》,强调"伤其十指不如断其一指",用于当多个任务争夺注意力时优先处理重要任务。
## 核心功能
- **任务分析**:分析所有待处理的任务
- **优先级排序**:根据重要性和紧急性对任务进行排序
- **资源集中**:将资源集中到最重要的任务上
- **各个击破**:逐个解决优先级高的任务
## 触发条件
当多个任务争夺注意力,需要优先处理重要任务时触发。
## 执行步骤
1. **任务分析**:分析所有待处理的任务
2. **优先级排序**:根据重要性和紧急性对任务进行排序
3. **资源集中**:将资源集中到最重要的任务上
4. **各个击破**:逐个解决优先级高的任务
5. **动态调整**:根据情况动态调整优先级和资源分配
## 核心原则
伤其十指不如断其一指。不打无准备之仗。
## 不适用场景
- 只有一个任务
- 所有任务都同等重要
- 任务之间相互依赖,无法单独处理
- 时间充足,不需要优先级排序
## 集中兵力的应用
- **任务管理**:管理多个并发任务
- **项目规划**:规划项目的优先级
- **资源分配**:合理分配有限的资源
- **问题解决**:集中精力解决关键问题
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 平均分配资源 | 集中资源到最重要的任务 |
| 同时处理多个任务 | 一次只处理一个重要任务 |
| 忽视任务的重要性 | 认真评估任务的重要性和紧急性 |
| 缺乏准备 | 充分准备后再行动 |
| 不根据情况调整 | 动态调整优先级和资源分配 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **任务清单**:列出所有待处理的任务
2. **评估排序**:评估每个任务的重要性和紧急性,进行排序
3. **资源规划**:规划所需的资源,确保重要任务得到充分支持
4. **执行计划**:制定详细的执行计划,明确每个任务的时间和资源需求
5. **集中执行**:集中精力执行最重要的任务,确保完成质量
6. **评估调整**:定期评估任务进展,根据情况调整优先级和资源分配
## 与其他 skill 的关系
- **矛盾分析法**:集中兵力需要识别主要矛盾
- **持久战略**:在持久战略中,需要在关键阶段集中兵力
- **统筹兼顾**:集中兵力需要在全局范围内统筹兼顾
- **实践认识论**:集中兵力的效果需要在实践中验证
## 安装方法
```bash
clawhub install concentrate-forces
```
## 许可证
MIT License
@@ -0,0 +1,56 @@
---
name: concentrate-forces
description: "当多个任务争夺注意力,需要优先处理重要任务时调用"
tools: []
---
# 集中兵力
## 触发条件
当多个任务争夺注意力,需要优先处理重要任务时触发。
## 执行步骤
1. **任务分析**:分析所有待处理的任务
2. **优先级排序**:根据重要性和紧急性对任务进行排序
3. **资源集中**:将资源集中到最重要的任务上
4. **各个击破**:逐个解决优先级高的任务
5. **动态调整**:根据情况动态调整优先级和资源分配
## 核心原则
伤其十指不如断其一指。不打无准备之仗。
## 不适用场景
- 只有一个任务
- 所有任务都同等重要
- 任务之间相互依赖,无法单独处理
- 时间充足,不需要优先级排序
## 集中兵力的应用
- **任务管理**:管理多个并发任务
- **项目规划**:规划项目的优先级
- **资源分配**:合理分配有限的资源
- **问题解决**:集中精力解决关键问题
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 平均分配资源 | 集中资源到最重要的任务 |
| 同时处理多个任务 | 一次只处理一个重要任务 |
| 忽视任务的重要性 | 认真评估任务的重要性和紧急性 |
| 缺乏准备 | 充分准备后再行动 |
| 不根据情况调整 | 动态调整优先级和资源分配 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **任务清单**:列出所有待处理的任务
2. **评估排序**:评估每个任务的重要性和紧急性,进行排序
3. **资源规划**:规划所需的资源,确保重要任务得到充分支持
4. **执行计划**:制定详细的执行计划,明确每个任务的时间和资源需求
5. **集中执行**:集中精力执行最重要的任务,确保完成质量
6. **评估调整**:定期评估任务进展,根据情况调整优先级和资源分配
## 与其他 skill 的关系
- **矛盾分析法**:集中兵力需要识别主要矛盾
- **持久战略**:在持久战略中,需要在关键阶段集中兵力
- **统筹兼顾**:集中兵力需要在全局范围内统筹兼顾
- **实践认识论**:集中兵力的效果需要在实践中验证
@@ -0,0 +1,13 @@
{
"name": "concentrate-forces",
"version": "1.0.0",
"displayName": "集中兵力",
"description": "当多个任务争夺注意力,需要优先处理重要任务时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "集中兵力"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,73 @@
# 矛盾分析法
## 技能介绍
矛盾分析法是求是 OpenClaw Skills 系列中的核心技能,用于分析复杂问题,识别矛盾,抓住主要矛盾,区分矛盾性质,从而找到解决问题的方法。
## 核心功能
- **矛盾识别**:识别问题中的所有矛盾
- **主要矛盾判定**:找出规定或影响其他矛盾的主要矛盾
- **矛盾性质分析**:区分对抗性矛盾和非对抗性矛盾
- **解决方案选择**:根据矛盾性质选择合适的解决方法
- **矛盾转化监控**:持续关注矛盾的变化和转化
## 触发条件
当问题复杂、存在多个冲突因素、优先级不清,或你不知道应该先解决什么时触发。
## 执行步骤
1. **识别所有矛盾**:列出当前情境中所有对立的、互相制约的因素
2. **判定主要矛盾**:找出那个规定或影响着其他矛盾的主要矛盾
3. **分析矛盾的主要方面**:判断哪一方面占支配地位
4. **区分矛盾性质**:判断矛盾是对抗性的还是非对抗性的
5. **选择解决方法**:根据矛盾性质,选择对应方法
6. **监控矛盾转化**:持续关注矛盾的变化
## 矛盾性质判断
**对抗性矛盾**(根本利益冲突):
- 需要明确立场,果断处理
- 不能调和,只能选择一方
**非对抗性矛盾**(共同利益下的分歧):
- 使用"团结——批评——团结"的方法
- 从团结的愿望出发,通过讨论和批评解决分歧,达到新的团结
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 不做矛盾分析就动手 | 先分析,后行动 |
| 搞一刀切 | 每个矛盾都有其特殊性,不能套用模板 |
| 抓不住主要矛盾 | 全局着眼,抓住牛鼻子 |
| 忽视矛盾转化 | 持续监控,动态调整 |
| 把非对抗性矛盾当对抗性处理 | 先判断性质,再选择方法 |
## 操作规程
当本 skill 被触发时,执行以下具体步骤并输出结构化的矛盾分析表:
1. **列矛盾清单**:用 bullet list 列出当前情境中所有可识别的对立面,格式为 `[A] vs [B]`
2. **判定主要矛盾**:在列表中标记一个矛盾为 `⭐ 主要矛盾`,并用一句话说明理由
3. **判断性质**:对主要矛盾标注:`对抗性``非对抗性`
4. **选择应对方法**:根据性质,选择对应方法,并明确写出"接下来我将……"
5. **设置监控提示**:在分析末尾加一行:"⚠️ 需监控:[次要矛盾X] 是否上升为主要矛盾"
## 与其他 skill 的关系
- **实践认识论**:矛盾分析得出的结论需要在实践中验证
- **调查研究**:识别矛盾的前提是充分的调查研究
- **集中兵力**:抓住主要矛盾后,集中力量解决它
- **统筹兼顾**:当多对矛盾都需要处理时,需要统筹兼顾
- **批评与自我批评**:矛盾分析也适用于审视自己的工作
## 安装方法
```bash
clawhub install contradiction-analysis
```
## 许可证
MIT License
@@ -0,0 +1,60 @@
---
name: contradiction-analysis
description: "当问题复杂、存在多个冲突因素、优先级不清,或你不知道应该先解决什么时调用"
tools: []
---
# 矛盾分析法
## 触发条件
当问题复杂、存在多个冲突因素、优先级不清,或你不知道应该先解决什么时触发。
## 执行步骤
1. 识别所有矛盾:列出当前情境中所有对立的、互相制约的因素
2. 判定主要矛盾:找出那个规定或影响着其他矛盾的主要矛盾
3. 分析矛盾的主要方面:判断哪一方面占支配地位
4. 区分矛盾性质:判断矛盾是对抗性的还是非对抗性的
5. 选择解决方法:根据矛盾性质,选择对应方法
6. 监控矛盾转化:持续关注矛盾的变化
## 核心原则
一切事物都包含矛盾,分析任何问题的方法就是找到其中的矛盾,区分主要矛盾和次要矛盾,然后集中力量解决主要矛盾。
## 不适用场景
- 任务是直接执行性的(如"帮我把这段代码格式化")
- 用户已经明确指定了解决方案,只需要实现
- 问题只有一个维度,不存在对立面
- 时间紧急且问题属于已知模式
## 矛盾性质判断
**对抗性矛盾**(根本利益冲突):
- 需要明确立场,果断处理
- 不能调和,只能选择一方
**非对抗性矛盾**(共同利益下的分歧):
- 使用"团结——批评——团结"的方法
- 从团结的愿望出发,通过讨论和批评解决分歧,达到新的团结
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 不做矛盾分析就动手 | 先分析,后行动 |
| 搞一刀切 | 每个矛盾都有其特殊性,不能套用模板 |
| 抓不住主要矛盾 | 全局着眼,抓住牛鼻子 |
| 忽视矛盾转化 | 持续监控,动态调整 |
| 把非对抗性矛盾当对抗性处理 | 先判断性质,再选择方法 |
## 操作规程
当本 skill 被触发时,执行以下具体步骤并输出结构化的矛盾分析表:
1. **列矛盾清单**:用 bullet list 列出当前情境中所有可识别的对立面,格式为 `[A] vs [B]`
2. **判定主要矛盾**:在列表中标记一个矛盾为 `⭐ 主要矛盾`,并用一句话说明理由
3. **判断性质**:对主要矛盾标注:`对抗性``非对抗性`
4. **选择应对方法**:根据性质,选择对应方法,并明确写出"接下来我将……"
5. **设置监控提示**:在分析末尾加一行:"⚠️ 需监控:[次要矛盾X] 是否上升为主要矛盾"
## 与其他 skill 的关系
- **实践认识论**:矛盾分析得出的结论需要在实践中验证
- **调查研究**:识别矛盾的前提是充分的调查研究
- **集中兵力**:抓住主要矛盾后,集中力量解决它
- **统筹兼顾**:当多对矛盾都需要处理时,需要统筹兼顾
- **批评与自我批评**:矛盾分析也适用于审视自己的工作
@@ -0,0 +1,13 @@
{
"name": "contradiction-analysis",
"version": "1.0.0",
"displayName": "矛盾分析法",
"description": "当问题复杂、存在多个冲突因素、优先级不清,或你不知道应该先解决什么时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "矛盾分析"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,82 @@
# 批评与自我批评
## 技能介绍
批评与自我批评是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《论联合政府》,强调"惩前毖后,治病救人",用于完成工作后审视质量,或改进自身表现。
## 核心功能
- **自我检查**:对自己的工作进行全面检查
- **自我批评**:诚恳地找出自己的不足和错误
- **接受批评**:虚心接受他人的批评和建议
- **改进计划**:制定具体的改进措施
## 触发条件
当完成工作后需要审视质量,或需要改进自身表现时触发。
## 执行步骤
1. **自我检查**:对自己的工作进行全面检查
2. **自我批评**:诚恳地找出自己的不足和错误
3. **接受批评**:虚心接受他人的批评和建议
4. **分析原因**:分析产生问题的原因
5. **制定改进计划**:制定具体的改进措施
6. **落实改进**:认真落实改进计划
## 核心原则
惩前毖后,治病救人。房子是应该经常打扫的。
## 批评与自我批评的方法
- **实事求是**:基于事实进行批评和自我批评
- **与人为善**:以帮助他人为目的,不搞人身攻击
- **治病救人**:通过批评帮助他人改进,而不是惩罚
- **知无不言**:坦诚地表达自己的意见和看法
- **言无不尽**:充分表达自己的想法和建议
## 不适用场景
- 工作尚未完成
- 问题已经解决
- 不需要改进的简单任务
- 纯粹的理论探讨
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 敷衍了事 | 认真对待批评和自我批评 |
| 只批评别人不自我批评 | 首先进行自我批评 |
| 搞人身攻击 | 针对问题,不针对个人 |
| 不接受批评 | 虚心接受他人的批评和建议 |
| 批评后不改进 | 认真落实改进措施 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **准备阶段**:回顾工作内容,收集相关信息
2. **自我检查**:对工作进行全面检查,找出问题和不足
3. **自我批评**:诚恳地进行自我批评,分析问题原因
4. **征求意见**:主动征求他人的批评和建议
5. **分析总结**:分析批评意见,总结经验教训
6. **改进计划**:制定具体的改进计划和措施
7. **落实改进**:认真落实改进计划,定期检查改进效果
## 与其他 skill 的关系
- **实践认识论**:批评与自我批评是实践后的重要环节
- **调查研究**:批评与自我批评可以发现调查研究中的问题
- **群众路线**:批评与自我批评需要群众的参与和监督
- **矛盾分析法**:批评与自我批评可以帮助识别和解决内部矛盾
## 安装方法
```bash
clawhub install criticism-self-criticism
```
## 许可证
MIT License
@@ -0,0 +1,59 @@
---
name: criticism-self-criticism
description: "当完成工作后需要审视质量,或需要改进自身表现时调用"
tools: []
---
# 批评与自我批评
## 触发条件
当完成工作后需要审视质量,或需要改进自身表现时触发。
## 执行步骤
1. **自我检查**:对自己的工作进行全面检查
2. **自我批评**:诚恳地找出自己的不足和错误
3. **接受批评**:虚心接受他人的批评和建议
4. **分析原因**:分析产生问题的原因
5. **制定改进计划**:制定具体的改进措施
6. **落实改进**:认真落实改进计划
## 核心原则
惩前毖后,治病救人。房子是应该经常打扫的。
## 不适用场景
- 工作尚未完成
- 问题已经解决
- 不需要改进的简单任务
- 纯粹的理论探讨
## 批评与自我批评的方法
- **实事求是**:基于事实进行批评和自我批评
- **与人为善**:以帮助他人为目的,不搞人身攻击
- **治病救人**:通过批评帮助他人改进,而不是惩罚
- **知无不言**:坦诚地表达自己的意见和看法
- **言无不尽**:充分表达自己的想法和建议
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 敷衍了事 | 认真对待批评和自我批评 |
| 只批评别人不自我批评 | 首先进行自我批评 |
| 搞人身攻击 | 针对问题,不针对个人 |
| 不接受批评 | 虚心接受他人的批评和建议 |
| 批评后不改进 | 认真落实改进措施 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **准备阶段**:回顾工作内容,收集相关信息
2. **自我检查**:对工作进行全面检查,找出问题和不足
3. **自我批评**:诚恳地进行自我批评,分析问题原因
4. **征求意见**:主动征求他人的批评和建议
5. **分析总结**:分析批评意见,总结经验教训
6. **改进计划**:制定具体的改进计划和措施
7. **落实改进**:认真落实改进计划,定期检查改进效果
## 与其他 skill 的关系
- **实践认识论**:批评与自我批评是实践后的重要环节
- **调查研究**:批评与自我批评可以发现调查研究中的问题
- **群众路线**:批评与自我批评需要群众的参与和监督
- **矛盾分析法**:批评与自我批评可以帮助识别和解决内部矛盾
@@ -0,0 +1,13 @@
{
"name": "criticism-self-criticism",
"version": "1.0.0",
"displayName": "批评与自我批评",
"description": "当完成工作后需要审视质量,或需要改进自身表现时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "批评与自我批评"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,81 @@
# 调查研究
## 技能介绍
调查研究是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《反对本本主义》,强调"没有调查就没有发言权",用于在做决策前收集充分的信息,深入了解问题背景。
## 核心功能
- **信息收集**:通过各种渠道收集相关信息
- **信息分析**:对收集到的信息进行整理和分析
- **结论形成**:基于分析结果形成调查结论
- **建议提出**:根据结论提出具体的建议
## 触发条件
当需要做决策但信息不足,或需要深入了解问题背景时触发。
## 执行步骤
1. **明确调查目标**:确定需要了解的问题和信息
2. **制定调查计划**:设计调查方法、步骤和时间安排
3. **收集信息**:通过各种渠道收集相关信息
4. **分析信息**:对收集到的信息进行整理和分析
5. **形成结论**:基于分析结果形成调查结论
6. **提出建议**:根据结论提出具体的建议
## 核心原则
没有调查就没有发言权。调查就像"十月怀胎",解决问题就像"一朝分娩"。
## 调查方法
- **观察法**:直接观察相关现象和行为
- **访谈法**:与相关人员进行交流和访谈
- **文献法**:查阅相关文献和资料
- **实验法**:通过实验验证假设
- **问卷调查法**:通过问卷收集大量信息
## 不适用场景
- 已经有足够的信息做出决策
- 时间紧急且问题属于已知模式
- 纯粹的理论探讨,不需要实际信息
- 问题本身不涉及具体事实
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 没有调查就下结论 | 先调查,后结论 |
| 调查不全面 | 从多个角度收集信息 |
| 调查不深入 | 深入分析问题的本质 |
| 只收集有利信息 | 客观收集各种信息,包括不利信息 |
| 调查后不分析 | 对收集到的信息进行系统分析 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **明确问题**:清楚定义需要调查的问题
2. **确定范围**:确定调查的范围和边界
3. **选择方法**:根据问题特点选择合适的调查方法
4. **实施调查**:按照计划进行调查,收集信息
5. **分析数据**:对收集到的数据进行整理和分析
6. **形成报告**:撰写调查报告,包括发现和建议
## 与其他 skill 的关系
- **矛盾分析法**:调查研究是识别矛盾的前提
- **实践认识论**:调查研究是实践的重要组成部分
- **群众路线**:调查研究需要深入群众,了解实际情况
- **批评与自我批评**:调查研究可以发现自身存在的问题
## 安装方法
```bash
clawhub install investigation-first
```
## 许可证
MIT License
@@ -0,0 +1,58 @@
---
name: investigation-first
description: "当需要做决策但信息不足,或需要深入了解问题背景时调用"
tools: []
---
# 调查研究
## 触发条件
当需要做决策但信息不足,或需要深入了解问题背景时触发。
## 执行步骤
1. **明确调查目标**:确定需要了解的问题和信息
2. **制定调查计划**:设计调查方法、步骤和时间安排
3. **收集信息**:通过各种渠道收集相关信息
4. **分析信息**:对收集到的信息进行整理和分析
5. **形成结论**:基于分析结果形成调查结论
6. **提出建议**:根据结论提出具体的建议
## 核心原则
没有调查就没有发言权。调查就像"十月怀胎",解决问题就像"一朝分娩"。
## 不适用场景
- 已经有足够的信息做出决策
- 时间紧急且问题属于已知模式
- 纯粹的理论探讨,不需要实际信息
- 问题本身不涉及具体事实
## 调查方法
- **观察法**:直接观察相关现象和行为
- **访谈法**:与相关人员进行交流和访谈
- **文献法**:查阅相关文献和资料
- **实验法**:通过实验验证假设
- **问卷调查法**:通过问卷收集大量信息
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 没有调查就下结论 | 先调查,后结论 |
| 调查不全面 | 从多个角度收集信息 |
| 调查不深入 | 深入分析问题的本质 |
| 只收集有利信息 | 客观收集各种信息,包括不利信息 |
| 调查后不分析 | 对收集到的信息进行系统分析 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **明确问题**:清楚定义需要调查的问题
2. **确定范围**:确定调查的范围和边界
3. **选择方法**:根据问题特点选择合适的调查方法
4. **实施调查**:按照计划进行调查,收集信息
5. **分析数据**:对收集到的数据进行整理和分析
6. **形成报告**:撰写调查报告,包括发现和建议
## 与其他 skill 的关系
- **矛盾分析法**:调查研究是识别矛盾的前提
- **实践认识论**:调查研究是实践的重要组成部分
- **群众路线**:调查研究需要深入群众,了解实际情况
- **批评与自我批评**:调查研究可以发现自身存在的问题
@@ -0,0 +1,13 @@
{
"name": "investigation-first",
"version": "1.0.0",
"displayName": "调查研究",
"description": "当需要做决策但信息不足,或需要深入了解问题背景时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "调查研究"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,79 @@
# 群众路线
## 技能介绍
群众路线是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《关于领导方法的若干问题》,强调"从群众中来,到群众中去",用于收集多方意见和整合多源信息。
## 核心功能
- **意见收集**:收集群众的意见和建议
- **意见分析**:对收集到的意见进行整理和分析
- **意见反馈**:将整理后的意见反馈给群众
- **方案优化**:根据群众反馈优化方案
## 触发条件
当需要收集多方意见或整合多源信息时触发。
## 执行步骤
1. **从群众中来**:收集群众的意见和建议
2. **集中起来**:对收集到的意见进行整理和分析
3. **到群众中去**:将整理后的意见反馈给群众
4. **坚持下去**:根据群众的反馈进一步调整和完善
## 核心原则
从群众中来,到群众中去。收集→系统化→返回→验证→再收集。
## 不适用场景
- 问题只涉及少数专业人士的意见
- 时间紧急且需要快速决策
- 问题本身不需要多方意见
- 已经有明确的解决方案
## 群众路线的应用
- **决策参考**:收集群众意见作为决策的参考
- **方案优化**:根据群众反馈优化方案
- **问题解决**:依靠群众的智慧解决问题
- **关系维护**:通过群众路线维护良好的关系
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 忽视群众意见 | 认真倾听群众的意见和建议 |
| 只收集不反馈 | 及时将处理结果反馈给群众 |
| 形式主义 | 真正深入群众,了解实际情况 |
| 选择性收集 | 客观收集各种意见,包括批评意见 |
| 不重视反馈 | 认真对待群众的反馈,及时调整 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **确定范围**:确定需要收集意见的范围和对象
2. **设计方法**:设计收集意见的方法和工具
3. **收集意见**:通过各种渠道收集群众的意见
4. **整理分析**:对收集到的意见进行整理和分析
5. **形成方案**:基于分析结果形成初步方案
6. **反馈验证**:将方案反馈给群众,征求意见
7. **调整完善**:根据反馈调整和完善方案
## 与其他 skill 的关系
- **调查研究**:群众路线是调查研究的重要方法
- **实践认识论**:群众的实践是认识的重要来源
- **批评与自我批评**:群众的批评是自我批评的重要参考
- **统筹兼顾**:群众路线需要统筹兼顾各方利益
## 安装方法
```bash
clawhub install mass-line
```
## 许可证
MIT License
@@ -0,0 +1,56 @@
---
name: mass-line
description: "当需要收集多方意见或整合多源信息时调用"
tools: []
---
# 群众路线
## 触发条件
当需要收集多方意见或整合多源信息时触发。
## 执行步骤
1. **从群众中来**:收集群众的意见和建议
2. **集中起来**:对收集到的意见进行整理和分析
3. **到群众中去**:将整理后的意见反馈给群众
4. **坚持下去**:根据群众的反馈进一步调整和完善
## 核心原则
从群众中来,到群众中去。收集→系统化→返回→验证→再收集。
## 不适用场景
- 问题只涉及少数专业人士的意见
- 时间紧急且需要快速决策
- 问题本身不需要多方意见
- 已经有明确的解决方案
## 群众路线的应用
- **决策参考**:收集群众意见作为决策的参考
- **方案优化**:根据群众反馈优化方案
- **问题解决**:依靠群众的智慧解决问题
- **关系维护**:通过群众路线维护良好的关系
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 忽视群众意见 | 认真倾听群众的意见和建议 |
| 只收集不反馈 | 及时将处理结果反馈给群众 |
| 形式主义 | 真正深入群众,了解实际情况 |
| 选择性收集 | 客观收集各种意见,包括批评意见 |
| 不重视反馈 | 认真对待群众的反馈,及时调整 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **确定范围**:确定需要收集意见的范围和对象
2. **设计方法**:设计收集意见的方法和工具
3. **收集意见**:通过各种渠道收集群众的意见
4. **整理分析**:对收集到的意见进行整理和分析
5. **形成方案**:基于分析结果形成初步方案
6. **反馈验证**:将方案反馈给群众,征求意见
7. **调整完善**:根据反馈调整和完善方案
## 与其他 skill 的关系
- **调查研究**:群众路线是调查研究的重要方法
- **实践认识论**:群众的实践是认识的重要来源
- **批评与自我批评**:群众的批评是自我批评的重要参考
- **统筹兼顾**:群众路线需要统筹兼顾各方利益
@@ -0,0 +1,13 @@
{
"name": "mass-line",
"version": "1.0.0",
"displayName": "群众路线",
"description": "当需要收集多方意见或整合多源信息时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "群众路线"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,84 @@
# 统筹兼顾
## 技能介绍
统筹兼顾是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《论十大关系》,强调"调动一切积极因素",用于当多个目标需要平衡时统筹兼顾各方面因素。
## 核心功能
- **目标分析**:分析所有需要实现的目标
- **资源评估**:评估可用的资源和约束条件
- **优先级确定**:确定各目标的优先级
- **方案制定**:制定统筹兼顾的方案
- **资源分配**:合理分配资源,确保各目标的实现
## 触发条件
当多个目标需要平衡,需要统筹兼顾时触发。
## 执行步骤
1. **目标分析**:分析所有需要实现的目标
2. **资源评估**:评估可用的资源和约束条件
3. **优先级确定**:确定各目标的优先级
4. **方案制定**:制定统筹兼顾的方案
5. **资源分配**:合理分配资源,确保各目标的实现
6. **执行监控**:监控执行情况,及时调整方案
7. **平衡优化**:不断优化,确保各目标的平衡实现
## 核心原则
调动一切积极因素。拒绝片面性,寻找动态平衡。
## 不适用场景
- 只有一个目标
- 目标之间没有冲突
- 资源充足,不需要平衡
- 时间紧急,不需要统筹规划
## 统筹兼顾的应用
- **项目管理**:管理多个项目目标
- **资源分配**:分配有限的资源
- **决策制定**:制定兼顾各方利益的决策
- **战略规划**:规划长期战略目标
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 片面追求单一目标 | 兼顾所有重要目标 |
| 忽视资源约束 | 考虑资源约束,合理分配 |
| 缺乏整体规划 | 制定整体规划,协调各目标 |
| 不考虑长期影响 | 考虑长期影响,保持可持续发展 |
| 不根据情况调整 | 动态调整,保持平衡 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **目标清单**:列出所有需要实现的目标
2. **目标分析**:分析各目标的重要性、紧迫性和相互关系
3. **资源评估**:评估可用的资源和约束条件
4. **优先级排序**:根据分析结果,确定各目标的优先级
5. **方案制定**:制定统筹兼顾的方案,确保各目标的平衡实现
6. **资源分配**:根据优先级和需求,合理分配资源
7. **执行实施**:按照方案执行,监控执行情况
8. **调整优化**:根据执行情况,及时调整方案,确保各目标的平衡实现
## 与其他 skill 的关系
- **矛盾分析法**:统筹兼顾需要分析和平衡各种矛盾
- **集中兵力**:在统筹兼顾的基础上,需要集中兵力于关键目标
- **持久战略**:统筹兼顾需要考虑长期战略目标
- **群众路线**:统筹兼顾需要考虑各方利益和意见
## 安装方法
```bash
clawhub install overall-planning
```
## 许可证
MIT License
@@ -0,0 +1,60 @@
---
name: overall-planning
description: "当多个目标需要平衡,需要统筹兼顾时调用"
tools: []
---
# 统筹兼顾
## 触发条件
当多个目标需要平衡,需要统筹兼顾时触发。
## 执行步骤
1. **目标分析**:分析所有需要实现的目标
2. **资源评估**:评估可用的资源和约束条件
3. **优先级确定**:确定各目标的优先级
4. **方案制定**:制定统筹兼顾的方案
5. **资源分配**:合理分配资源,确保各目标的实现
6. **执行监控**:监控执行情况,及时调整方案
7. **平衡优化**:不断优化,确保各目标的平衡实现
## 核心原则
调动一切积极因素。拒绝片面性,寻找动态平衡。
## 不适用场景
- 只有一个目标
- 目标之间没有冲突
- 资源充足,不需要平衡
- 时间紧急,不需要统筹规划
## 统筹兼顾的应用
- **项目管理**:管理多个项目目标
- **资源分配**:分配有限的资源
- **决策制定**:制定兼顾各方利益的决策
- **战略规划**:规划长期战略目标
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 片面追求单一目标 | 兼顾所有重要目标 |
| 忽视资源约束 | 考虑资源约束,合理分配 |
| 缺乏整体规划 | 制定整体规划,协调各目标 |
| 不考虑长期影响 | 考虑长期影响,保持可持续发展 |
| 不根据情况调整 | 动态调整,保持平衡 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **目标清单**:列出所有需要实现的目标
2. **目标分析**:分析各目标的重要性、紧迫性和相互关系
3. **资源评估**:评估可用的资源和约束条件
4. **优先级排序**:根据分析结果,确定各目标的优先级
5. **方案制定**:制定统筹兼顾的方案,确保各目标的平衡实现
6. **资源分配**:根据优先级和需求,合理分配资源
7. **执行实施**:按照方案执行,监控执行情况
8. **调整优化**:根据执行情况,及时调整方案,确保各目标的平衡实现
## 与其他 skill 的关系
- **矛盾分析法**:统筹兼顾需要分析和平衡各种矛盾
- **集中兵力**:在统筹兼顾的基础上,需要集中兵力于关键目标
- **持久战略**:统筹兼顾需要考虑长期战略目标
- **群众路线**:统筹兼顾需要考虑各方利益和意见
@@ -0,0 +1,13 @@
{
"name": "overall-planning",
"version": "1.0.0",
"displayName": "统筹兼顾",
"description": "当多个目标需要平衡,需要统筹兼顾时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "统筹兼顾"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,72 @@
# 实践认识论
## 技能介绍
实践认识论是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《实践论》,强调实践→认识→再实践→再认识的螺旋上升过程,用于验证方案、迭代改进和从实践中学习。
## 核心功能
- **方案验证**:通过实践验证方案的可行性
- **迭代改进**:根据实践结果不断调整和优化方案
- **经验总结**:从成功和失败中提炼出可复用的经验
- **规律发现**:通过多次实践发现事物的内在规律
## 触发条件
当需要验证方案、迭代改进、从实践中学习时触发。
## 执行步骤
1. **实践**:制定并执行具体方案
2. **认识**:分析实践结果,总结经验教训
3. **再实践**:根据认识调整方案,再次执行
4. **再认识**:继续总结,形成更深刻的认识
5. **循环往复**:直到问题解决或形成稳定的方法论
## 核心原则
实践→认识→再实践→再认识,螺旋上升。实践是检验真理的唯一标准。
## 不适用场景
- 纯粹的理论探讨,不需要实际验证
- 已经有明确且经过验证的解决方案
- 时间或资源不允许进行实践验证
- 问题本身不涉及实践操作
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 只实践不总结 | 每次实践后都要进行总结和反思 |
| 只理论不实践 | 将理论与实践相结合,用实践检验理论 |
| 一次实践就下结论 | 多次实践,综合分析结果 |
| 忽视实践中的细节 | 关注实践中的具体情况,细节决定成败 |
| 拒绝根据实践调整方案 | 保持开放心态,根据实践结果灵活调整 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **明确目标**:清楚定义要验证的假设或要解决的问题
2. **制定方案**:设计具体的实践步骤和评估标准
3. **执行实践**:按照方案进行操作,记录过程和结果
4. **分析结果**:客观分析实践结果,找出成功和失败的原因
5. **调整方案**:根据分析结果调整方案,准备下一次实践
6. **总结经验**:提炼出可复用的经验和方法论
## 与其他 skill 的关系
- **矛盾分析法**:实践认识论可以验证矛盾分析的结论
- **调查研究**:实践是调查研究的延伸,也是验证调查结果的方法
- **批评与自我批评**:实践中的失败和不足是批评与自我批评的重要内容
- **持久战略**:长期复杂任务需要通过实践认识论不断调整策略
## 安装方法
```bash
clawhub install practice-cognition
```
## 许可证
MIT License
@@ -0,0 +1,56 @@
---
name: practice-cognition
description: "当需要验证方案、迭代改进、从实践中学习时调用"
tools: []
---
# 实践认识论
## 触发条件
当需要验证方案、迭代改进、从实践中学习时触发。
## 执行步骤
1. **实践**:制定并执行具体方案
2. **认识**:分析实践结果,总结经验教训
3. **再实践**:根据认识调整方案,再次执行
4. **再认识**:继续总结,形成更深刻的认识
5. **循环往复**:直到问题解决或形成稳定的方法论
## 核心原则
实践→认识→再实践→再认识,螺旋上升。实践是检验真理的唯一标准。
## 不适用场景
- 纯粹的理论探讨,不需要实际验证
- 已经有明确且经过验证的解决方案
- 时间或资源不允许进行实践验证
- 问题本身不涉及实践操作
## 实践认识论的应用
- **方案验证**:通过小规模实践验证方案的可行性
- **迭代改进**:根据实践结果不断调整和优化方案
- **经验总结**:从成功和失败中提炼出可复用的经验
- **规律发现**:通过多次实践发现事物的内在规律
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 只实践不总结 | 每次实践后都要进行总结和反思 |
| 只理论不实践 | 将理论与实践相结合,用实践检验理论 |
| 一次实践就下结论 | 多次实践,综合分析结果 |
| 忽视实践中的细节 | 关注实践中的具体情况,细节决定成败 |
| 拒绝根据实践调整方案 | 保持开放心态,根据实践结果灵活调整 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **明确目标**:清楚定义要验证的假设或要解决的问题
2. **制定方案**:设计具体的实践步骤和评估标准
3. **执行实践**:按照方案进行操作,记录过程和结果
4. **分析结果**:客观分析实践结果,找出成功和失败的原因
5. **调整方案**:根据分析结果调整方案,准备下一次实践
6. **总结经验**:提炼出可复用的经验和方法论
## 与其他 skill 的关系
- **矛盾分析法**:实践认识论可以验证矛盾分析的结论
- **调查研究**:实践是调查研究的延伸,也是验证调查结果的方法
- **批评与自我批评**:实践中的失败和不足是批评与自我批评的重要内容
- **持久战略**:长期复杂任务需要通过实践认识论不断调整策略
@@ -0,0 +1,13 @@
{
"name": "practice-cognition",
"version": "1.0.0",
"displayName": "实践认识论",
"description": "当需要验证方案、迭代改进、从实践中学习时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "实践认识论"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,84 @@
# 持久战略
## 技能介绍
持久战略是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《论持久战》,强调"战略上藐视,战术上重视",用于面对长期复杂任务时制定长期计划。
## 核心功能
- **战略分析**:分析任务的性质、特点和挑战
- **阶段划分**:将长期任务划分为多个阶段
- **计划制定**:为每个阶段制定具体的计划和目标
- **资源分配**:合理分配资源,确保各阶段的顺利进行
- **执行监控**:监控执行情况,及时调整计划
## 触发条件
当面对长期复杂任务,需要制定长期计划时触发。
## 执行步骤
1. **战略分析**:分析任务的性质、特点和挑战
2. **阶段划分**:将长期任务划分为多个阶段
3. **制定计划**:为每个阶段制定具体的计划和目标
4. **资源分配**:合理分配资源,确保各阶段的顺利进行
5. **执行监控**:监控执行情况,及时调整计划
6. **阶段评估**:对每个阶段的成果进行评估
7. **持续推进**:保持动力,持续推进任务的完成
## 核心原则
战略上藐视,战术上重视。不急于求成,也不畏难放弃。
## 不适用场景
- 短期简单任务
- 已经有明确的解决方案
- 时间紧急且需要快速完成的任务
- 不需要长期规划的任务
## 持久战略的应用
- **长期项目**:制定长期项目的阶段性计划
- **职业发展**:规划个人或组织的长期发展
- **问题解决**:解决复杂的长期问题
- **能力建设**:长期能力建设和培养
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 急于求成 | 制定合理的时间表,稳步推进 |
| 畏难放弃 | 保持信心,坚持到底 |
| 缺乏规划 | 制定详细的阶段计划 |
| 资源分配不当 | 合理分配资源,确保各阶段的需求 |
| 监控不力 | 定期监控执行情况,及时调整 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **任务分析**:分析任务的性质、难度和时间要求
2. **阶段划分**:将任务划分为多个合理的阶段
3. **目标设定**:为每个阶段设定具体的目标和指标
4. **计划制定**:制定每个阶段的详细计划和行动方案
5. **资源规划**:规划所需的资源和支持
6. **执行实施**:按照计划执行,定期检查进度
7. **评估调整**:对每个阶段进行评估,根据情况调整计划
8. **持续推进**:保持动力,直至任务完成
## 与其他 skill 的关系
- **矛盾分析法**:持久战略需要分析长期任务中的矛盾
- **实践认识论**:持久战略需要通过实践不断调整
- **集中兵力**:在持久战略中,需要在关键阶段集中兵力
- **统筹兼顾**:持久战略需要统筹兼顾各方面的因素
## 安装方法
```bash
clawhub install protracted-strategy
```
## 许可证
MIT License
@@ -0,0 +1,60 @@
---
name: protracted-strategy
description: "当面对长期复杂任务,需要制定长期计划时调用"
tools: []
---
# 持久战略
## 触发条件
当面对长期复杂任务,需要制定长期计划时触发。
## 执行步骤
1. **战略分析**:分析任务的性质、特点和挑战
2. **阶段划分**:将长期任务划分为多个阶段
3. **制定计划**:为每个阶段制定具体的计划和目标
4. **资源分配**:合理分配资源,确保各阶段的顺利进行
5. **执行监控**:监控执行情况,及时调整计划
6. **阶段评估**:对每个阶段的成果进行评估
7. **持续推进**:保持动力,持续推进任务的完成
## 核心原则
战略上藐视,战术上重视。不急于求成,也不畏难放弃。
## 不适用场景
- 短期简单任务
- 已经有明确的解决方案
- 时间紧急且需要快速完成的任务
- 不需要长期规划的任务
## 持久战略的应用
- **长期项目**:制定长期项目的阶段性计划
- **职业发展**:规划个人或组织的长期发展
- **问题解决**:解决复杂的长期问题
- **能力建设**:长期能力建设和培养
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 急于求成 | 制定合理的时间表,稳步推进 |
| 畏难放弃 | 保持信心,坚持到底 |
| 缺乏规划 | 制定详细的阶段计划 |
| 资源分配不当 | 合理分配资源,确保各阶段的需求 |
| 监控不力 | 定期监控执行情况,及时调整 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **任务分析**:分析任务的性质、难度和时间要求
2. **阶段划分**:将任务划分为多个合理的阶段
3. **目标设定**:为每个阶段设定具体的目标和指标
4. **计划制定**:制定每个阶段的详细计划和行动方案
5. **资源规划**:规划所需的资源和支持
6. **执行实施**:按照计划执行,定期检查进度
7. **评估调整**:对每个阶段进行评估,根据情况调整计划
8. **持续推进**:保持动力,直至任务完成
## 与其他 skill 的关系
- **矛盾分析法**:持久战略需要分析长期任务中的矛盾
- **实践认识论**:持久战略需要通过实践不断调整
- **集中兵力**:在持久战略中,需要在关键阶段集中兵力
- **统筹兼顾**:持久战略需要统筹兼顾各方面的因素
@@ -0,0 +1,13 @@
{
"name": "protracted-strategy",
"version": "1.0.0",
"displayName": "持久战略",
"description": "当面对长期复杂任务,需要制定长期计划时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "持久战略"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,40 @@
## Description: <br>
求是 OpenClaw Skills 是基于毛泽东思想方法论的 AI Agent 技能集合,按照 OpenClaw 技能格式进行改造,旨在为 AI 提供系统化的思考和行动框架。 <br>
This skill is ready for commercial/non-commercial use. <br>
## Publisher: <br>
[skytodmoon](https://clawhub.ai/user/skytodmoon) <br>
### License/Terms of Use: <br>
MIT-0 <br>
## Use Case: <br>
Developers and agent users use this Chinese-language skill pack to guide planning, prioritization, investigation, review, and multi-skill workflow selection with a Mao-inspired methodology framework. <br>
### Deployment Geography for Use: <br>
Global <br>
## Known Risks and Mitigations: <br>
Risk: The broad arming-thought trigger can influence planning, prioritization, review, and skill routing at the start of new top-level conversations. <br>
Mitigation: Install only where this Chinese-language Mao-inspired reasoning framework is desired, and review the automatic trigger behavior before enabling the pack. <br>
## Reference(s): <br>
- [ClawHub skill page](https://clawhub.ai/skytodmoon/qiushi-openclaw-skill) <br>
- [Publisher profile](https://clawhub.ai/user/skytodmoon) <br>
- [Referenced project homepage](https://github.com/skytodmoon/qiushi-skill) <br>
## Skill Output: <br>
**Output Type(s):** [guidance, markdown, analysis] <br>
**Output Format:** [Markdown guidance with structured checklists, tables, and step-by-step reasoning prompts] <br>
**Output Parameters:** [1D] <br>
**Other Properties Related to Output:** [No tools, environment variables, credentials, file access, network access, or persistence requested by the artifact.] <br>
## Skill Version(s): <br>
1.0.0 (source: server release evidence and clawhub.json manifests) <br>
## Ethical Considerations: <br>
Users should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>
@@ -0,0 +1,79 @@
# 星火燎原
## 技能介绍
星火燎原是求是 OpenClaw Skills 系列中的核心技能,基于毛泽东的《星星之火,可以燎原》,强调"建立根据地,不做流寇",用于从零开始、资源有限时从小处着手积累发展。
## 核心功能
- **根据地建立**:选择适合的起点,建立基础
- **经验积累**:在小范围内积累经验和资源
- **逐步扩展**:在基础稳固后,逐步扩展范围
- **规模效应**:通过不断积累和扩展,形成规模效应
## 触发条件
当从零开始,资源有限,需要从小处着手积累发展时触发。
## 执行步骤
1. **建立根据地**:选择一个适合的起点,建立基础
2. **积累经验**:在小范围内积累经验和资源
3. **逐步扩展**:在基础稳固后,逐步扩展范围
4. **形成规模**:通过不断积累和扩展,形成规模效应
5. **持续发展**:保持发展势头,持续创新和改进
## 核心原则
建立根据地,不做流寇。从小处着手,积累发展。
## 不适用场景
- 资源充足,不需要从小处着手
- 已经有成熟的基础和规模
- 时间紧急,需要快速达到规模
- 不需要长期发展的项目
## 星火燎原的应用
- **创业初期**:从零开始创业,建立基础
- **新领域探索**:进入新领域,积累经验
- **能力建设**:从小处着手,逐步提升能力
- **市场开拓**:从局部市场开始,逐步扩展
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 急于求成 | 稳扎稳打,逐步发展 |
| 忽视基础 | 重视基础建设,确保稳固 |
| 盲目扩张 | 在基础稳固后再扩展 |
| 缺乏耐心 | 保持耐心,注重积累 |
| 不适应变化 | 灵活适应环境变化,及时调整策略 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **起点选择**:选择一个适合的起点,考虑资源和环境因素
2. **基础建设**:在起点建立稳固的基础,积累经验和资源
3. **经验总结**:总结初期经验,优化方法和策略
4. **逐步扩展**:在基础稳固后,逐步扩展范围和规模
5. **规模效应**:通过扩展形成规模效应,提高效率和影响力
6. **持续创新**:保持创新,适应变化,持续发展
## 与其他 skill 的关系
- **持久战略**:星火燎原需要长期的战略规划
- **集中兵力**:在发展过程中,需要集中兵力于关键领域
- **实践认识论**:通过实践不断积累经验和改进
- **统筹兼顾**:在发展过程中需要统筹兼顾各方面的因素
## 安装方法
```bash
clawhub install spark-prairie-fire
```
## 许可证
MIT License
@@ -0,0 +1,56 @@
---
name: spark-prairie-fire
description: "当从零开始,资源有限,需要从小处着手积累发展时调用"
tools: []
---
# 星火燎原
## 触发条件
当从零开始,资源有限,需要从小处着手积累发展时触发。
## 执行步骤
1. **建立根据地**:选择一个适合的起点,建立基础
2. **积累经验**:在小范围内积累经验和资源
3. **逐步扩展**:在基础稳固后,逐步扩展范围
4. **形成规模**:通过不断积累和扩展,形成规模效应
5. **持续发展**:保持发展势头,持续创新和改进
## 核心原则
建立根据地,不做流寇。从小处着手,积累发展。
## 不适用场景
- 资源充足,不需要从小处着手
- 已经有成熟的基础和规模
- 时间紧急,需要快速达到规模
- 不需要长期发展的项目
## 星火燎原的应用
- **创业初期**:从零开始创业,建立基础
- **新领域探索**:进入新领域,积累经验
- **能力建设**:从小处着手,逐步提升能力
- **市场开拓**:从局部市场开始,逐步扩展
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 急于求成 | 稳扎稳打,逐步发展 |
| 忽视基础 | 重视基础建设,确保稳固 |
| 盲目扩张 | 在基础稳固后再扩展 |
| 缺乏耐心 | 保持耐心,注重积累 |
| 不适应变化 | 灵活适应环境变化,及时调整策略 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **起点选择**:选择一个适合的起点,考虑资源和环境因素
2. **基础建设**:在起点建立稳固的基础,积累经验和资源
3. **经验总结**:总结初期经验,优化方法和策略
4. **逐步扩展**:在基础稳固后,逐步扩展范围和规模
5. **规模效应**:通过扩展形成规模效应,提高效率和影响力
6. **持续创新**:保持创新,适应变化,持续发展
## 与其他 skill 的关系
- **持久战略**:星火燎原需要长期的战略规划
- **集中兵力**:在发展过程中,需要集中兵力于关键领域
- **实践认识论**:通过实践不断积累经验和改进
- **统筹兼顾**:在发展过程中需要统筹兼顾各方面的因素
@@ -0,0 +1,13 @@
{
"name": "spark-prairie-fire",
"version": "1.0.0",
"displayName": "星火燎原",
"description": "当从零开始,资源有限,需要从小处着手积累发展时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "星火燎原"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,83 @@
# 工作流组合
## 技能介绍
工作流组合是求是 OpenClaw Skills 系列中的核心技能,用于当一个任务明确需要多种方法串联时,组合使用多个技能形成完整的工作流程。
## 核心功能
- **任务分析**:分析任务的性质和需求
- **技能选择**:选择适合的技能组合
- **顺序确定**:确定技能的调用顺序
- **流程设计**:设计详细的工作流程
- **执行监控**:监控工作流程的执行情况
## 触发条件
当一个任务明确需要多种方法串联,需要组合使用多个技能时触发。
## 执行步骤
1. **任务分析**:分析任务的性质和需求
2. **技能选择**:选择适合的技能组合
3. **顺序确定**:确定技能的调用顺序
4. **流程设计**:设计详细的工作流程
5. **执行监控**:监控工作流程的执行情况
6. **调整优化**:根据执行情况调整工作流程
## 核心原则
根据任务需求,灵活组合使用各种技能,形成完整的工作流程。
## 不适用场景
- 任务只需要单一技能
- 任务流程简单,不需要复杂的技能组合
- 时间紧急,不需要详细的工作流程设计
- 已经有明确的工作流程
## 工作流组合的应用
- **复杂项目**:处理复杂的项目任务
- **多阶段任务**:处理需要多个阶段的任务
- **跨领域任务**:处理涉及多个领域的任务
- **创新任务**:处理需要创新思维的任务
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 技能选择不当 | 根据任务需求选择合适的技能 |
| 顺序安排不合理 | 合理安排技能的调用顺序 |
| 流程设计过于复杂 | 设计简洁有效的工作流程 |
| 缺乏监控和调整 | 监控执行情况,及时调整流程 |
| 忽视技能间的协同 | 注重技能间的协同效应 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **任务分析**:详细分析任务的性质、需求和挑战
2. **技能评估**:评估各种技能的适用性和可行性
3. **技能选择**:选择最适合的技能组合
4. **顺序设计**:设计合理的技能调用顺序
5. **流程制定**:制定详细的工作流程,包括每个阶段的目标和任务
6. **资源规划**:规划所需的资源和支持
7. **执行实施**:按照工作流程执行,监控执行情况
8. **评估调整**:评估工作流程的效果,根据情况调整流程
## 与其他 skill 的关系
- **矛盾分析法**:工作流组合需要分析任务中的矛盾
- **实践认识论**:工作流组合需要通过实践不断调整和优化
- **集中兵力**:在工作流程中,需要在关键阶段集中兵力
- **统筹兼顾**:工作流组合需要统筹兼顾各方面的因素
## 安装方法
```bash
clawhub install workflows
```
## 许可证
MIT License
@@ -0,0 +1,59 @@
---
name: workflows
description: "当一个任务明确需要多种方法串联,需要组合使用多个技能时调用"
tools: []
---
# 工作流组合
## 触发条件
当一个任务明确需要多种方法串联,需要组合使用多个技能时触发。
## 执行步骤
1. **任务分析**:分析任务的性质和需求
2. **技能选择**:选择适合的技能组合
3. **顺序确定**:确定技能的调用顺序
4. **流程设计**:设计详细的工作流程
5. **执行监控**:监控工作流程的执行情况
6. **调整优化**:根据执行情况调整工作流程
## 核心原则
根据任务需求,灵活组合使用各种技能,形成完整的工作流程。
## 不适用场景
- 任务只需要单一技能
- 任务流程简单,不需要复杂的技能组合
- 时间紧急,不需要详细的工作流程设计
- 已经有明确的工作流程
## 工作流组合的应用
- **复杂项目**:处理复杂的项目任务
- **多阶段任务**:处理需要多个阶段的任务
- **跨领域任务**:处理涉及多个领域的任务
- **创新任务**:处理需要创新思维的任务
## 常见错误
| 错误 | 正确做法 |
|------|---------|
| 技能选择不当 | 根据任务需求选择合适的技能 |
| 顺序安排不合理 | 合理安排技能的调用顺序 |
| 流程设计过于复杂 | 设计简洁有效的工作流程 |
| 缺乏监控和调整 | 监控执行情况,及时调整流程 |
| 忽视技能间的协同 | 注重技能间的协同效应 |
## 操作规程
当本 skill 被触发时,执行以下步骤:
1. **任务分析**:详细分析任务的性质、需求和挑战
2. **技能评估**:评估各种技能的适用性和可行性
3. **技能选择**:选择最适合的技能组合
4. **顺序设计**:设计合理的技能调用顺序
5. **流程制定**:制定详细的工作流程,包括每个阶段的目标和任务
6. **资源规划**:规划所需的资源和支持
7. **执行实施**:按照工作流程执行,监控执行情况
8. **评估调整**:评估工作流程的效果,根据情况调整流程
## 与其他 skill 的关系
- **矛盾分析法**:工作流组合需要分析任务中的矛盾
- **实践认识论**:工作流组合需要通过实践不断调整和优化
- **集中兵力**:在工作流程中,需要在关键阶段集中兵力
- **统筹兼顾**:工作流组合需要统筹兼顾各方面的因素
@@ -0,0 +1,13 @@
{
"name": "workflows",
"version": "1.0.0",
"displayName": "工作流组合",
"description": "当一个任务明确需要多种方法串联,需要组合使用多个技能时调用",
"author": "求是 Skill",
"homepage": "https://github.com/skytodmoon/qiushi-skill",
"tags": ["方法论", "毛泽东思想", "工作流组合"],
"requires": {
"env": []
},
"files": []
}
@@ -0,0 +1,17 @@
{
"version": 1,
"registry": "https://clawhub.ai",
"slug": "sql-toolkit",
"ownerHandle": "gitgoodordietrying",
"installedVersion": "1.0.0",
"installedAt": 1785744535727,
"artifact": {
"kind": "archive",
"sha256": "4f48da99f3b1beb878195590b3ed1c6a469ce554498831abdee42ca27468959f",
"integrity": "sha256-T0jamfOxvrh4GVWQs+0cakac5VRJiDGr3uQsonRolZ8="
},
"skillFile": {
"path": "SKILL.md",
"sha256": "515ecf904449a3cd5ebb92e85e54127e216d9483ee9111705e75e686a0694285"
}
}
@@ -0,0 +1,434 @@
---
name: sql-toolkit
description: Query, design, migrate, and optimize SQL databases. Use when working with SQLite, PostgreSQL, or MySQL — schema design, writing queries, creating migrations, indexing, backup/restore, and debugging slow queries. No ORMs required.
metadata: {"clawdbot":{"emoji":"🗄️","requires":{"anyBins":["sqlite3","psql","mysql"]},"os":["linux","darwin","win32"]}}
---
# SQL Toolkit
Work with relational databases directly from the command line. Covers SQLite, PostgreSQL, and MySQL with patterns for schema design, querying, migrations, indexing, and operations.
## When to Use
- Creating or modifying database schemas
- Writing complex queries (joins, aggregations, window functions, CTEs)
- Building migration scripts
- Optimizing slow queries with indexes and EXPLAIN
- Backing up and restoring databases
- Quick data exploration with SQLite (zero setup)
## SQLite (Zero Setup)
SQLite is included with Python and available on every system. Use it for local data, prototyping, and single-file databases.
### Quick Start
```bash
# Create/open a database
sqlite3 mydb.sqlite
# Import CSV directly
sqlite3 mydb.sqlite ".mode csv" ".import data.csv mytable" "SELECT COUNT(*) FROM mytable;"
# One-liner queries
sqlite3 mydb.sqlite "SELECT * FROM users WHERE created_at > '2026-01-01' LIMIT 10;"
# Export to CSV
sqlite3 -header -csv mydb.sqlite "SELECT * FROM orders;" > orders.csv
# Interactive mode with headers and columns
sqlite3 -header -column mydb.sqlite
```
### Schema Operations
```sql
-- Create table
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
email TEXT NOT NULL UNIQUE,
name TEXT NOT NULL,
created_at TEXT DEFAULT (datetime('now')),
updated_at TEXT DEFAULT (datetime('now'))
);
-- Create with foreign key
CREATE TABLE orders (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
total REAL NOT NULL CHECK(total >= 0),
status TEXT NOT NULL DEFAULT 'pending' CHECK(status IN ('pending','paid','shipped','cancelled')),
created_at TEXT DEFAULT (datetime('now'))
);
-- Add column
ALTER TABLE users ADD COLUMN phone TEXT;
-- Create index
CREATE INDEX idx_orders_user_id ON orders(user_id);
CREATE UNIQUE INDEX idx_users_email ON users(email);
-- View schema
.schema users
.tables
```
## PostgreSQL
### Connection
```bash
# Connect
psql -h localhost -U myuser -d mydb
# Connection string
psql "postgresql://user:pass@localhost:5432/mydb?sslmode=require"
# Run single query
psql -h localhost -U myuser -d mydb -c "SELECT NOW();"
# Run SQL file
psql -h localhost -U myuser -d mydb -f migration.sql
# List databases
psql -l
```
### Schema Design Patterns
```sql
-- Use UUIDs for distributed-friendly primary keys
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE users (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
email TEXT NOT NULL,
name TEXT NOT NULL,
password_hash TEXT NOT NULL,
role TEXT NOT NULL DEFAULT 'user' CHECK(role IN ('user','admin','moderator')),
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT users_email_unique UNIQUE(email)
);
-- Auto-update updated_at
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = NOW();
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER update_users_modtime
BEFORE UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION update_modified_column();
-- Enum type (PostgreSQL-specific)
CREATE TYPE order_status AS ENUM ('pending', 'paid', 'shipped', 'delivered', 'cancelled');
CREATE TABLE orders (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
status order_status NOT NULL DEFAULT 'pending',
total NUMERIC(10,2) NOT NULL CHECK(total >= 0),
metadata JSONB DEFAULT '{}',
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);
-- Partial index (only index active orders — smaller, faster)
CREATE INDEX idx_orders_active ON orders(user_id, created_at)
WHERE status NOT IN ('delivered', 'cancelled');
-- GIN index for JSONB queries
CREATE INDEX idx_orders_metadata ON orders USING GIN(metadata);
```
### JSONB Queries (PostgreSQL)
```sql
-- Store JSON
INSERT INTO orders (user_id, total, metadata)
VALUES ('...', 99.99, '{"source": "web", "coupon": "SAVE10", "items": [{"sku": "A1", "qty": 2}]}');
-- Query JSON fields
SELECT * FROM orders WHERE metadata->>'source' = 'web';
SELECT * FROM orders WHERE metadata->'items' @> '[{"sku": "A1"}]';
SELECT metadata->>'coupon' AS coupon, COUNT(*) FROM orders GROUP BY 1;
-- Update JSON field
UPDATE orders SET metadata = jsonb_set(metadata, '{source}', '"mobile"') WHERE id = '...';
```
## MySQL
### Connection
```bash
mysql -h localhost -u root -p mydb
mysql -h localhost -u root -p -e "SELECT NOW();" mydb
```
### Key Differences from PostgreSQL
```sql
-- Auto-increment (not SERIAL)
CREATE TABLE users (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- JSON type (MySQL 5.7+)
CREATE TABLE orders (
id BIGINT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id BIGINT UNSIGNED NOT NULL,
metadata JSON,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- Query JSON
SELECT * FROM orders WHERE JSON_EXTRACT(metadata, '$.source') = 'web';
-- Or shorthand:
SELECT * FROM orders WHERE metadata->>'$.source' = 'web';
```
## Query Patterns
### Joins
```sql
-- Inner join (only matching rows)
SELECT u.name, o.total, o.status
FROM users u
INNER JOIN orders o ON o.user_id = u.id
WHERE o.created_at > '2026-01-01';
-- Left join (all users, even without orders)
SELECT u.name, COUNT(o.id) AS order_count, COALESCE(SUM(o.total), 0) AS total_spent
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
GROUP BY u.id, u.name;
-- Self-join (find users with same email domain)
SELECT a.name, b.name, SPLIT_PART(a.email, '@', 2) AS domain
FROM users a
JOIN users b ON SPLIT_PART(a.email, '@', 2) = SPLIT_PART(b.email, '@', 2)
WHERE a.id < b.id;
```
### Aggregations
```sql
-- Group by with having
SELECT status, COUNT(*) AS cnt, SUM(total) AS revenue
FROM orders
GROUP BY status
HAVING COUNT(*) > 10
ORDER BY revenue DESC;
-- Running total (window function)
SELECT date, revenue,
SUM(revenue) OVER (ORDER BY date) AS cumulative_revenue
FROM daily_sales;
-- Rank within groups
SELECT user_id, total,
RANK() OVER (PARTITION BY user_id ORDER BY total DESC) AS rank
FROM orders;
-- Moving average (last 7 entries)
SELECT date, revenue,
AVG(revenue) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS ma_7
FROM daily_sales;
```
### Common Table Expressions (CTEs)
```sql
-- Readable multi-step queries
WITH monthly_revenue AS (
SELECT DATE_TRUNC('month', created_at) AS month,
SUM(total) AS revenue
FROM orders
WHERE status = 'paid'
GROUP BY 1
),
growth AS (
SELECT month, revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_revenue,
ROUND((revenue - LAG(revenue) OVER (ORDER BY month)) /
NULLIF(LAG(revenue) OVER (ORDER BY month), 0) * 100, 1) AS growth_pct
FROM monthly_revenue
)
SELECT * FROM growth ORDER BY month;
-- Recursive CTE (org chart / tree traversal)
WITH RECURSIVE org_tree AS (
SELECT id, name, manager_id, 0 AS depth
FROM employees
WHERE manager_id IS NULL
UNION ALL
SELECT e.id, e.name, e.manager_id, t.depth + 1
FROM employees e
JOIN org_tree t ON e.manager_id = t.id
)
SELECT REPEAT(' ', depth) || name AS org_chart FROM org_tree ORDER BY depth, name;
```
## Migrations
### Manual Migration Script Pattern
```bash
#!/bin/bash
# migrate.sh - Run numbered SQL migration files
DB_URL="${1:?Usage: migrate.sh <db-url>}"
MIGRATIONS_DIR="./migrations"
# Create tracking table
psql "$DB_URL" -c "CREATE TABLE IF NOT EXISTS schema_migrations (
version TEXT PRIMARY KEY,
applied_at TIMESTAMPTZ DEFAULT NOW()
);"
# Run pending migrations in order
for file in $(ls "$MIGRATIONS_DIR"/*.sql | sort); do
version=$(basename "$file" .sql)
already=$(psql "$DB_URL" -tAc "SELECT 1 FROM schema_migrations WHERE version='$version';")
if [ "$already" = "1" ]; then
echo "SKIP: $version (already applied)"
continue
fi
echo "APPLY: $version"
psql "$DB_URL" -f "$file" && \
psql "$DB_URL" -c "INSERT INTO schema_migrations (version) VALUES ('$version');" || {
echo "FAILED: $version"
exit 1
}
done
echo "All migrations applied."
```
### Migration File Convention
```
migrations/
001_create_users.sql
002_create_orders.sql
003_add_users_phone.sql
004_add_orders_metadata_index.sql
```
Each file:
```sql
-- 003_add_users_phone.sql
-- Up
ALTER TABLE users ADD COLUMN phone TEXT;
-- To reverse: ALTER TABLE users DROP COLUMN phone;
```
## Query Optimization
### EXPLAIN (PostgreSQL)
```sql
-- Show query plan
EXPLAIN SELECT * FROM orders WHERE user_id = '...' AND status = 'paid';
-- Show actual execution times
EXPLAIN (ANALYZE, BUFFERS, FORMAT TEXT)
SELECT * FROM orders WHERE user_id = '...' AND status = 'paid';
```
**What to look for:**
- `Seq Scan` on large tables → needs an index
- `Nested Loop` with large row counts → consider `Hash Join` (may need more `work_mem`)
- `Rows Removed by Filter` being high → index doesn't cover the filter
- Actual rows far from estimated → run `ANALYZE tablename;` to update statistics
### Index Strategy
```sql
-- Single column (most common)
CREATE INDEX idx_orders_user_id ON orders(user_id);
-- Composite (for queries filtering on both columns)
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
-- Column ORDER matters: put equality filters first, range filters last
-- Covering index (includes data columns to avoid table lookup)
CREATE INDEX idx_orders_covering ON orders(user_id, status) INCLUDE (total, created_at);
-- Partial index (smaller, faster — only index what you query)
CREATE INDEX idx_orders_pending ON orders(user_id) WHERE status = 'pending';
-- Check unused indexes
SELECT schemaname, tablename, indexname, idx_scan
FROM pg_stat_user_indexes
WHERE idx_scan = 0 AND indexname NOT LIKE '%pkey%'
ORDER BY pg_relation_size(indexrelid) DESC;
```
### SQLite EXPLAIN
```sql
EXPLAIN QUERY PLAN SELECT * FROM orders WHERE user_id = 5;
-- Look for: SCAN (bad) vs SEARCH USING INDEX (good)
```
## Backup & Restore
### PostgreSQL
```bash
# Full dump (custom format, compressed)
pg_dump -Fc -h localhost -U myuser mydb > backup.dump
# Restore
pg_restore -h localhost -U myuser -d mydb --clean --if-exists backup.dump
# SQL dump (portable, readable)
pg_dump -h localhost -U myuser mydb > backup.sql
# Dump specific tables
pg_dump -h localhost -U myuser -t users -t orders mydb > partial.sql
# Copy table to CSV
psql -c "\copy (SELECT * FROM users) TO 'users.csv' CSV HEADER"
```
### SQLite
```bash
# Backup (just copy the file, but use .backup for consistency)
sqlite3 mydb.sqlite ".backup backup.sqlite"
# Dump to SQL
sqlite3 mydb.sqlite .dump > backup.sql
# Restore from SQL
sqlite3 newdb.sqlite < backup.sql
```
### MySQL
```bash
# Dump
mysqldump -h localhost -u root -p mydb > backup.sql
# Restore
mysql -h localhost -u root -p mydb < backup.sql
```
## Tips
- Always use parameterized queries in application code — never concatenate user input into SQL
- Use `TIMESTAMPTZ` (not `TIMESTAMP`) in PostgreSQL for timezone-aware dates
- Set `PRAGMA journal_mode=WAL;` in SQLite for concurrent read performance
- Use `EXPLAIN` before deploying any query that runs on large tables
- PostgreSQL: `\d+ tablename` shows columns, indexes, and size. `\di+` lists all indexes with sizes
- For quick data exploration, import any CSV into SQLite: `sqlite3 :memory: ".mode csv" ".import file.csv t" "SELECT ..."`
@@ -0,0 +1,6 @@
{
"ownerId": "kn7f6g2r31qsb1ts8cf5x7rpk180fn9j",
"slug": "sql-toolkit",
"version": "1.0.0",
"publishedAt": 1770155077543
}
@@ -0,0 +1,38 @@
## Description: <br>
Query, design, migrate, and optimize SQL databases for SQLite, PostgreSQL, and MySQL, including schema design, queries, migrations, indexing, backup and restore, and slow-query debugging without ORMs. <br>
This skill is ready for commercial/non-commercial use. <br>
## Publisher: <br>
[gitgoodordietrying](https://clawhub.ai/user/gitgoodordietrying) <br>
### License/Terms of Use: <br>
## Use Case: <br>
Developers and engineers use this skill to work directly with relational databases from the command line, including schema design, query writing, migrations, indexing, backup and restore, and performance troubleshooting. <br>
### Deployment Geography for Use: <br>
Global <br>
## Known Risks and Mitigations: <br>
Risk: Migration, import, and restore examples can change schemas, overwrite data, or restore into the wrong database. <br>
Mitigation: Verify the target host and database, create a fresh backup before destructive operations, and prefer restoring into a new database first. <br>
Risk: Database commands may expose credentials through shared shell history, logs, or overly broad database permissions. <br>
Mitigation: Use least-privilege credentials and avoid placing real passwords in command lines, shared logs, or reusable shell history. <br>
## Reference(s): <br>
## Skill Output: <br>
**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance] <br>
**Output Format:** [Markdown with SQL and shell command examples] <br>
**Output Parameters:** [1D] <br>
**Other Properties Related to Output:** [Requires at least one supported database CLI: sqlite3, psql, or mysql.] <br>
## Skill Version(s): <br>
1.0.0 (source: ClawHub release metadata) <br>
## Ethical Considerations: <br>
Users should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>