sync: update auto sync (A@67794d69b70f7d291333020c5ffd071a7836d177)
This commit is contained in:
parent
ad0f058baa
commit
6517a3f4cd
3
.assets_mapping
Normal file
3
.assets_mapping
Normal file
@ -0,0 +1,3 @@
|
||||
CLAUDE.md | 文档 | https://conversation.cdn.meoo.host/conversations/312782936418197504/file/2026-05-23/1779512821061-CLAUDE.md?auth_key=d58c5d879e91e544e0693fab745459373d600d09a97cc7811e0af491c03cbf51 | /home/project/assets/CLAUDE.md
|
||||
入库流程图.docx | 文档 | https://conversation.cdn.meoo.host/conversations/312782936418197504/file/2026-05-23/1779512821057-入库流程图.docx?auth_key=800c9bb00af9dd353cdb91d1966494e87255c6ae7b7e21c6e226b58b224d89b6 | /home/project/assets/入库流程图.docx
|
||||
微信图片_20260525195238_49_125.jpg | 图片 | https://conversation.cdn.meoo.host/conversations/312782936418197504/image/2026-05-25/1779711506188-微信图片_20260525195238_49_125.jpg?auth_key=55d04ced266880baebbf150fa6cb06fd546e28a2aca7fd99022b2b887e978d5f | /home/project/assets/微信图片_20260525195238_49_125.jpg
|
||||
19
.env.example
Normal file
19
.env.example
Normal file
@ -0,0 +1,19 @@
|
||||
# Supabase 配置
|
||||
VITE_SUPABASE_URL=https://your-project.supabase.co
|
||||
VITE_SUPABASE_ANON_KEY=your-anon-key
|
||||
|
||||
# 应用配置
|
||||
VITE_APP_NAME=织机(Demo版)
|
||||
VITE_APP_VERSION=1.0.0
|
||||
VITE_APP_ENV=development
|
||||
|
||||
# 功能开关
|
||||
VITE_ENABLE_ANALYTICS=false
|
||||
VITE_ENABLE_SENTRY=false
|
||||
|
||||
# API 配置
|
||||
VITE_API_TIMEOUT=30000
|
||||
VITE_API_RETRY_COUNT=3
|
||||
|
||||
# 缓存配置
|
||||
VITE_CACHE_DURATION=5000
|
||||
6
.env.production
Normal file
6
.env.production
Normal file
@ -0,0 +1,6 @@
|
||||
# 生产环境配置
|
||||
VITE_APP_ENV=production
|
||||
VITE_ENABLE_ANALYTICS=true
|
||||
VITE_ENABLE_SENTRY=true
|
||||
VITE_API_TIMEOUT=60000
|
||||
VITE_CACHE_DURATION=10000
|
||||
106
.gitignore
vendored
Normal file
106
.gitignore
vendored
Normal file
@ -0,0 +1,106 @@
|
||||
# 通用
|
||||
*.log
|
||||
*.tmp
|
||||
*.temp
|
||||
*.swp
|
||||
*.swo
|
||||
*.bak
|
||||
*.orig
|
||||
|
||||
# 环境变量与密钥
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
*.pem
|
||||
*.key
|
||||
|
||||
# 系统文件
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# 编辑器与 IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
|
||||
# Node.js / JavaScript / TypeScript
|
||||
node_modules/
|
||||
dist/
|
||||
build/
|
||||
.next/
|
||||
.nuxt/
|
||||
.cache/
|
||||
coverage/
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
.pnpm-store/
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*.pyo
|
||||
*.pyd
|
||||
.pytest_cache/
|
||||
.mypy_cache/
|
||||
.ruff_cache/
|
||||
.venv/
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
pip-wheel-metadata/
|
||||
*.egg-info/
|
||||
.coverage
|
||||
htmlcov/
|
||||
|
||||
# Java / Kotlin
|
||||
target/
|
||||
*.class
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
.gradle/
|
||||
out/
|
||||
|
||||
# Go
|
||||
bin/
|
||||
*.test
|
||||
coverage.out
|
||||
|
||||
# C / C++
|
||||
*.o
|
||||
*.obj
|
||||
*.so
|
||||
*.a
|
||||
*.lib
|
||||
*.dll
|
||||
*.dylib
|
||||
*.exe
|
||||
CMakeFiles/
|
||||
CMakeCache.txt
|
||||
cmake-build-*/
|
||||
compile_commands.json
|
||||
Makefile
|
||||
|
||||
# Rust
|
||||
target/
|
||||
|
||||
# C#
|
||||
*.user
|
||||
*.suo
|
||||
*.userosscache
|
||||
*.sln.docstates
|
||||
bin/
|
||||
obj/
|
||||
|
||||
# Ruby & PHP / Composer:`/vendor/` 仅忽略仓库根目录下的 vendor(不包含 src/pages/vendor/ 等)
|
||||
.bundle/
|
||||
/vendor/
|
||||
|
||||
# OneDay 中间产物目录(文件处理时的临时文件,不需要持久化)
|
||||
tmp/
|
||||
|
||||
# other
|
||||
.stats
|
||||
.config
|
||||
.accesslog
|
||||
74
.plan/34a2df39-85b1-4ed9-8a3e-34f56d54af64/plan.md
Normal file
74
.plan/34a2df39-85b1-4ed9-8a3e-34f56d54af64/plan.md
Normal file
@ -0,0 +1,74 @@
|
||||
# 分享链接导入并同步关联计划功能 - 实现计划
|
||||
|
||||
## 功能概述
|
||||
|
||||
采购商(布行)在计划总览页面可以为每个计划生成分享链接,发送给纺织厂/水洗厂。对方通过链接打开系统后,自动导入并关联该计划到自己的公司,实现跨角色协作。
|
||||
|
||||
## 核心流程
|
||||
|
||||
1. **采购商生成分享链接**:在计划总览页面,点击"分享链接"按钮,生成包含计划ID的URL(如 `#/import?plan=xxx&type=textile`)
|
||||
2. **工厂方打开链接**:纺织厂/水洗厂用户收到链接后打开,系统识别URL参数,展示计划详情和导入确认页面
|
||||
3. **确认导入**:工厂方确认后,系统在 `plan_factories` 表中创建关联记录,将计划绑定到工厂公司
|
||||
4. **同步生效**:导入成功后,工厂方的工作台和计划总览自动显示该计划
|
||||
|
||||
## 实现步骤
|
||||
|
||||
### 步骤1:新增路由和导入页面
|
||||
|
||||
- 在 `App.tsx` 中添加路由:`/import` → `ImportPlanPage`
|
||||
- 创建 `src/pages/ImportPlanPage.tsx`,处理URL参数中的 `plan` 和 `type`
|
||||
|
||||
### 步骤2:采购商计划总览 - 生成分享链接
|
||||
|
||||
修改 `src/pages/purchaser/PlanOverview.tsx`:
|
||||
- 将现有的"分享链接"按钮从工厂级别移到计划级别
|
||||
- 点击后生成链接:`#/import?plan={planId}&type={factoryType}`
|
||||
- 显示复制链接的弹窗,支持一键复制
|
||||
|
||||
### 步骤3:创建 ImportPlanPage 导入确认页面
|
||||
|
||||
创建 `src/pages/ImportPlanPage.tsx`:
|
||||
- 从URL参数读取 `plan`(计划ID)和 `type`(工厂类型:textile/washing)
|
||||
- 检查用户是否已登录且角色匹配(纺织厂用户只能导入textile类型,水洗厂只能导入washing类型)
|
||||
- 展示计划详情(产品名、颜色、坯布码、计划产量、纱线配比等)
|
||||
- 提供"确认导入"按钮
|
||||
- 导入逻辑:向 `plan_factories` 表插入 `{plan_id, factory_id: 当前公司ID, factory_type: type}`
|
||||
- 导入成功后跳转到对应工作台
|
||||
|
||||
### 步骤4:防重复导入
|
||||
|
||||
- 导入前检查 `plan_factories` 是否已存在相同关联
|
||||
- 如果已存在,提示"该计划已导入"并跳转到工作台
|
||||
|
||||
### 步骤5:更新 AGENTS.md 路由表
|
||||
|
||||
添加 `/import` 路由记录
|
||||
|
||||
## 涉及文件
|
||||
|
||||
| 文件 | 操作 | 说明 |
|
||||
|------|------|------|
|
||||
| `src/App.tsx` | 编辑 | 添加 `/import` 路由 |
|
||||
| `src/pages/ImportPlanPage.tsx` | 新建 | 导入确认页面 |
|
||||
| `src/pages/purchaser/PlanOverview.tsx` | 编辑 | 分享链接按钮改为计划级别,添加复制链接弹窗 |
|
||||
| `AGENTS.md` | 编辑 | 添加路由记录 |
|
||||
|
||||
## 数据库变更
|
||||
|
||||
无需新增表或字段。使用现有的 `plan_factories` 表存储关联关系。
|
||||
|
||||
## URL格式设计
|
||||
|
||||
```
|
||||
#/import?plan={planId}&type={textile|washing}
|
||||
```
|
||||
|
||||
- `plan`: 生产计划的UUID
|
||||
- `type`: 工厂类型,决定纺织厂还是水洗厂可以导入
|
||||
|
||||
## ImportPlanPage 页面设计
|
||||
|
||||
1. 未登录 → 提示登录并跳转到 `/login`
|
||||
2. 已登录但角色不匹配 → 提示角色不匹配
|
||||
3. 已登录且角色匹配 → 展示计划详情 + 确认导入按钮
|
||||
4. 已导入 → 提示已导入 + 跳转工作台
|
||||
20
.todo/0589cf52-b6c9-4f19-af07-9eb17e004557/todos.json
Normal file
20
.todo/0589cf52-b6c9-4f19-af07-9eb17e004557/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修改入库记录为生产记录",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修改仓库管理为生产仓库管理",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "修复坯布入库状态显示为进行中",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
26
.todo/0810f58f-05ef-46ac-91b1-4c05f22a70f4/todos.json
Normal file
26
.todo/0810f58f-05ef-46ac-91b1-4c05f22a70f4/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "在 App.tsx 中添加 DemoWatermark 组件",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "在采购商工作台添加限时免费标签",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "在纺织厂工作台添加限时免费标签",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "在水洗厂工作台添加限时免费标签",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
26
.todo/09dd1b69-c113-4ca2-a83a-044bf9c00003/todos.json
Normal file
26
.todo/09dd1b69-c113-4ca2-a83a-044bf9c00003/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修改坯布入库,仓库位置默认为工厂地址或名称",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "添加进度97%时弹出计划完成确认",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "实现完成后记录锁定不可更改",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "运行测试验证功能正常",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
32
.todo/09f94466-5d0a-457b-b49d-42af313a8245/todos.json
Normal file
32
.todo/09f94466-5d0a-457b-b49d-42af313a8245/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "数据库迁移:为 products 表添加图片字段",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "更新类型定义:ProductWithInventory 添加图片字段",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "修改 ProductForm:添加图片上传功能",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修改 ProductList:显示产品图片",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "修改 WarehouseManage:处理图片数据",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
32
.todo/0c6171a6-6db8-467a-80b3-94728c411830/todos.json
Normal file
32
.todo/0c6171a6-6db8-467a-80b3-94728c411830/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修改 Product 类型添加 last_in_time 字段",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修改 fetchData 查询最近入库时间",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "在移动端卡片显示入库时间",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "在桌面端表格显示入库时间",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "验证修改",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
26
.todo/116bc950-799c-4fc3-84b3-9dc8fe9c321c/todos.json
Normal file
26
.todo/116bc950-799c-4fc3-84b3-9dc8fe9c321c/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"content": "创建子账号管理页面 MemberManage.tsx",
|
||||
"id": "1",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
},
|
||||
{
|
||||
"content": "在 App.tsx 添加子账号管理路由",
|
||||
"id": "2",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
},
|
||||
{
|
||||
"content": "在各角色 Dashboard 添加子账号管理入口",
|
||||
"id": "3",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
},
|
||||
{
|
||||
"content": "类型检查和编译验证",
|
||||
"id": "4",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
}
|
||||
]
|
||||
20
.todo/1287da78-b83f-458a-bb81-b5389a8d9bf4/todos.json
Normal file
20
.todo/1287da78-b83f-458a-bb81-b5389a8d9bf4/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "统一纺织厂仪表台与采购商仪表台设计风格",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "统一水洗厂仪表台与采购商仪表台设计风格",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "验证修改后的页面运行正常",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
14
.todo/16757baf-4462-461a-8427-1c8f99592c3c/todos.json
Normal file
14
.todo/16757baf-4462-461a-8427-1c8f99592c3c/todos.json
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "更新 AGENTS.md 文档",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "更新 README.md 文档",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
20
.todo/17d26d13-5ca3-4b05-86c1-24a8b4c04f6f/todos.json
Normal file
20
.todo/17d26d13-5ca3-4b05-86c1-24a8b4c04f6f/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修改纺织厂PlanOverview,在流程节点显示最近一次入库时间",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修改采购商PlanOverview,显示入库进度和最近入库时间",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "更新ProcessFlow组件,支持显示入库时间",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
20
.todo/21334c3e-e7b7-44af-8a00-547aa2bc901e/todos.json
Normal file
20
.todo/21334c3e-e7b7-44af-8a00-547aa2bc901e/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "创建采购商成品仓库页面",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "添加路由配置",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "更新采购商Dashboard导航",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
20
.todo/229c2dad-a2d1-40fe-9472-aa756ad3bcaa/todos.json
Normal file
20
.todo/229c2dad-a2d1-40fe-9472-aa756ad3bcaa/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修复采购商计划详情无法展开问题",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修复仓库管理入库记录详情展示",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "添加采购价变动记录功能",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
38
.todo/2ab0661d-b5c8-41b8-8e7b-80adcd21c257/todos.json
Normal file
38
.todo/2ab0661d-b5c8-41b8-8e7b-80adcd21c257/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "重构水洗厂 Dashboard 页面,添加快捷操作、导入关联计划、水洗记录时间戳",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "创建水洗厂待处理坯布页面",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "创建水洗厂已完成坯布页面(含水洗时间、缩水率记录)",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "创建水洗厂待结款页面",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "更新 App.tsx 添加新路由",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "验证构建和运行",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
26
.todo/2bb16aa0-0012-4d1d-9856-fb883e451936/todos.json
Normal file
26
.todo/2bb16aa0-0012-4d1d-9856-fb883e451936/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "将分享链接加密改为 JWT 标准方案",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "添加 JWT token 过期时间支持",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "优化实时订阅,合并订阅通道",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "验证修改后代码运行正常",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
38
.todo/2f822c41-126f-49ca-a958-de257d6d0ed4/todos.json
Normal file
38
.todo/2f822c41-126f-49ca-a958-de257d6d0ed4/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "创建成品仓库表 finished_products 和 finished_inventory_records",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "创建水洗厂完成计划页面 WashingPlanComplete",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "实现水洗完成自动导入成品仓库逻辑",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "创建成品仓库管理页面 FinishedWarehouse",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "更新路由和导航",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "验证类型检查和功能测试",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
44
.todo/347045da-9152-4f26-b622-d0ee136c7b40/todos.json
Normal file
44
.todo/347045da-9152-4f26-b622-d0ee136c7b40/todos.json
Normal file
@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"content": "重写 LoginPage 对接 Supabase 认证",
|
||||
"id": "2b",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
},
|
||||
{
|
||||
"content": "重写 RoleSelectPage 对接真实数据",
|
||||
"id": "2c",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
},
|
||||
{
|
||||
"content": "重写采购商首页对接真实数据",
|
||||
"id": "3",
|
||||
"priority": "high",
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"content": "重写计划总览/新建计划对接真实数据",
|
||||
"id": "4",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"content": "重写纺织厂/水洗厂页面对接真实数据",
|
||||
"id": "5",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"content": "重写仓库/工厂管理对接真实数据",
|
||||
"id": "6",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"content": "类型检查和编译验证",
|
||||
"id": "7",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
38
.todo/34a2df39-85b1-4ed9-8a3e-34f56d54af64/todos.json
Normal file
38
.todo/34a2df39-85b1-4ed9-8a3e-34f56d54af64/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"content": "优化 LoginPage 桌面端布局",
|
||||
"id": "d1",
|
||||
"priority": "high",
|
||||
"status": "completed"
|
||||
},
|
||||
{
|
||||
"content": "优化 RoleSelectPage 桌面端布局",
|
||||
"id": "d2",
|
||||
"priority": "high",
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"content": "优化各 Dashboard 桌面端布局",
|
||||
"id": "d3",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"content": "优化 PlanOverview 桌面端布局",
|
||||
"id": "d4",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"content": "优化 ImportPlanPage 桌面端布局",
|
||||
"id": "d5",
|
||||
"priority": "medium",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"content": "类型检查和编译验证",
|
||||
"id": "d6",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
20
.todo/41ab6bdf-945b-425c-8371-6f56f7ba76d0/todos.json
Normal file
20
.todo/41ab6bdf-945b-425c-8371-6f56f7ba76d0/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修复采购商计划详情无法展开问题",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修复仓库管理入库记录详情展示",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "添加采购价变动记录功能",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
32
.todo/47a8e2c7-1664-4543-b230-beaa5434928c/todos.json
Normal file
32
.todo/47a8e2c7-1664-4543-b230-beaa5434928c/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "PlanOverview.tsx 添加分页查询(limit/offset)",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "WarehouseManage.tsx 添加分页查询",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "添加分页UI组件(页码/加载更多)",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "优化Realtime订阅,改为增量更新",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "运行类型检查和测试",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
32
.todo/4f7ca20a-5b75-47ae-85a8-131ccb45ebe3/todos.json
Normal file
32
.todo/4f7ca20a-5b75-47ae-85a8-131ccb45ebe3/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"status": "completed",
|
||||
"content": "修改 Product 类型添加 last_in_time 字段",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"status": "completed",
|
||||
"content": "修改 fetchData 查询最近入库时间",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"status": "completed",
|
||||
"content": "在移动端卡片显示入库时间",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"status": "completed",
|
||||
"content": "在桌面端表格显示入库时间",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"status": "completed",
|
||||
"content": "验证修改",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
26
.todo/59064931-0eb6-44bb-a507-73ab6e47ab9f/todos.json
Normal file
26
.todo/59064931-0eb6-44bb-a507-73ab6e47ab9f/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "创建通知数据库表和RLS策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "创建通知组件和通知中心",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "在流程节点完成时发送通知",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "在Dashboard添加通知入口",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
44
.todo/6579237b-6a42-4416-ad83-850b5860b33c/todos.json
Normal file
44
.todo/6579237b-6a42-4416-ad83-850b5860b33c/todos.json
Normal file
@ -0,0 +1,44 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "为 inventory_records 表添加 company_id 字段",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "为 yarn_ratios 表添加 company_id 字段",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "为 plan_process_steps 表添加 company_id 字段",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "更新 inventory_records 的 RLS 策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "更新 yarn_ratios 的 RLS 策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "更新 plan_process_steps 的 RLS 策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "7",
|
||||
"content": "同步更新现有数据的 company_id",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
14
.todo/7357498c-c6e9-43c5-95e5-a0d7e8ebe2a9/todos.json
Normal file
14
.todo/7357498c-c6e9-43c5-95e5-a0d7e8ebe2a9/todos.json
Normal file
@ -0,0 +1,14 @@
|
||||
[
|
||||
{
|
||||
"content": "修改 FactoryManage 添加新建工厂按钮和弹窗",
|
||||
"id": "1",
|
||||
"priority": "high",
|
||||
"status": "in_progress"
|
||||
},
|
||||
{
|
||||
"content": "类型检查和编译验证",
|
||||
"id": "2",
|
||||
"priority": "high",
|
||||
"status": "pending"
|
||||
}
|
||||
]
|
||||
20
.todo/749df53a-50ed-4cc7-90fa-83707e71b2bf/todos.json
Normal file
20
.todo/749df53a-50ed-4cc7-90fa-83707e71b2bf/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修改 WarehouseManage.tsx 数据获取逻辑,按工厂分组汇总",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修改入库记录展示,按工厂分组显示",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "更新产品库存统计,显示各工厂明细",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
26
.todo/7d5c44a7-611c-46f4-a2e1-290eacae62f5/todos.json
Normal file
26
.todo/7d5c44a7-611c-46f4-a2e1-290eacae62f5/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "创建水洗厂计划总览页面 WashingPlanOverview.tsx",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "创建水洗厂仓库管理页面 WashingWarehouse.tsx",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "更新 App.tsx 添加水洗厂路由",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "更新 Dashboard.tsx 修正快捷操作路径",
|
||||
"status": "pending",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
32
.todo/92c47652-da34-40c6-bc61-d8e1ef7ddd1d/todos.json
Normal file
32
.todo/92c47652-da34-40c6-bc61-d8e1ef7ddd1d/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "优化登录页移动端适配",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "优化仪表盘移动端适配",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "优化计划总览移动端适配",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "优化仓库管理移动端适配",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "验证所有修改",
|
||||
"status": "pending",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
38
.todo/996001fe-2c20-461e-9233-fb6ef3c9da3c/todos.json
Normal file
38
.todo/996001fe-2c20-461e-9233-fb6ef3c9da3c/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "读取存储相关文档,了解图片上传实现方式",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "查看现有产品管理相关代码和数据结构",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "创建数据库迁移 - 添加产品图片字段和存储桶",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修改产品列表组件 - 添加图片展示和上传功能",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "修改产品表单组件 - 添加图片上传功能",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "验证功能并运行测试",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
32
.todo/b2daccc6-f74f-41b7-aafb-ddbf6739eaa3/todos.json
Normal file
32
.todo/b2daccc6-f74f-41b7-aafb-ddbf6739eaa3/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修复 useTheme hook 类型定义",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修复测试文件类型错误",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "修复 ImportPlanPage 类型错误",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修复 MemberManage 类型错误",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "验证修复结果",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
56
.todo/b7465073-2e3e-4d4f-b1be-94ce569b640e/todos.json
Normal file
56
.todo/b7465073-2e3e-4d4f-b1be-94ce569b640e/todos.json
Normal file
@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "读取数据库参考文档,了解RLS策略规范",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "创建成品仓库表 finished_products 及相关表结构",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "创建水洗计划完成记录表 washing_plan_completions",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "创建自动导入成品仓库的数据库函数",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "更新类型定义文件",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "创建水洗厂计划完成页面UI",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "7",
|
||||
"content": "创建成品仓库管理页面",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "8",
|
||||
"content": "更新路由配置",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "9",
|
||||
"content": "验证功能并运行测试",
|
||||
"status": "completed",
|
||||
"priority": "low"
|
||||
}
|
||||
]
|
||||
38
.todo/bade5c70-612b-440d-847c-f7312c88187f/todos.json
Normal file
38
.todo/bade5c70-612b-440d-847c-f7312c88187f/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "读取 meoo-cloud Edge Functions 参考文档",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "创建入库事务处理 Edge Function",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "创建数据校验修复 Edge Function",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修改前端入库逻辑调用 Edge Function",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "部署 Edge Functions",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "验证功能",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
38
.todo/c495fd12-8fd0-47c2-9e5a-6fe7782d386f/todos.json
Normal file
38
.todo/c495fd12-8fd0-47c2-9e5a-6fe7782d386f/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "查看纺织厂工作台当前代码结构",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "查看现有YarnWarehouse页面结构",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "创建原坯布仓库页面",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修改纺织厂工作台添加两个仓库快捷操作",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "添加路由配置",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "验证所有修改",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
26
.todo/c63f2258-1a62-4039-b263-f4e9501ce51f/todos.json
Normal file
26
.todo/c63f2258-1a62-4039-b263-f4e9501ce51f/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "创建产品价格变更历史表",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "执行数据库迁移",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "修改产品编辑逻辑,记录价格变更",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "在产品详情中显示价格变更历史",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
20
.todo/cf7031fa-bf57-44a6-b961-008a2c550470/todos.json
Normal file
20
.todo/cf7031fa-bf57-44a6-b961-008a2c550470/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "更新 AGENTS.md 记录 webpack devServer 预览加载失败问题",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "更新 README.md 添加问题排查和解决方案",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "总结学习反思",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
26
.todo/d83d49e4-ff14-4373-bff0-a2a0f09d04f1/todos.json
Normal file
26
.todo/d83d49e4-ff14-4373-bff0-a2a0f09d04f1/todos.json
Normal file
@ -0,0 +1,26 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "数据库迁移:profiles 表添加 display_name 字段",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修改注册逻辑:存储用户名到 username,姓名到 display_name",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "修改账号管理:显示和编辑 display_name",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修改首页副标题:引用 display_name 而非 username",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
38
.todo/dbcebc28-e199-47a0-b809-f8b84a38513b/todos.json
Normal file
38
.todo/dbcebc28-e199-47a0-b809-f8b84a38513b/todos.json
Normal file
@ -0,0 +1,38 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "创建产品定义相关数据库表(products, product_yarn_ratios, fabric_batches)",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "更新仓库管理页为三级菜单结构",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "实现产品管理功能(列表、新建、编辑)",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "实现原坯布入库功能(关联产品、记录批号和时间戳)",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "更新路由配置",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "运行测试验证",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
56
.todo/dd1e01c7-7aa6-45fd-84b7-b9dc727a7b42/todos.json
Normal file
56
.todo/dd1e01c7-7aa6-45fd-84b7-b9dc727a7b42/todos.json
Normal file
@ -0,0 +1,56 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "检查 RLS 策略对数据查询的影响",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "检查 RLS 策略对数据插入的影响",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "检查 RLS 策略对数据更新的影响",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "修复 plan_process_steps 查询策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "修复 inventory_records 插入策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "6",
|
||||
"content": "修复 payments 插入策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "7",
|
||||
"content": "修复 yarn_ratios 删除策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "8",
|
||||
"content": "修复 plan_process_steps 查询策略",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "9",
|
||||
"content": "验证修复后的功能",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
20
.todo/ee057eda-9766-4be1-82a2-181874851cc5/todos.json
Normal file
20
.todo/ee057eda-9766-4be1-82a2-181874851cc5/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修改纺织厂PlanOverview,在流程节点显示最近一次入库时间",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "修改采购商PlanOverview,显示入库进度和最近入库时间",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "更新ProcessFlow组件,支持显示入库时间",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
20
.todo/f4105905-3cab-4ede-a5be-885cae061d16/todos.json
Normal file
20
.todo/f4105905-3cab-4ede-a5be-885cae061d16/todos.json
Normal file
@ -0,0 +1,20 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "修复导入计划页面支持水洗厂",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "添加水洗计划分享链接生成",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "验证数据同步机制",
|
||||
"status": "in_progress",
|
||||
"priority": "high"
|
||||
}
|
||||
]
|
||||
32
.todo/fcb48bf9-bcf9-4a85-9e32-eb3bcae83c1f/todos.json
Normal file
32
.todo/fcb48bf9-bcf9-4a85-9e32-eb3bcae83c1f/todos.json
Normal file
@ -0,0 +1,32 @@
|
||||
[
|
||||
{
|
||||
"id": "1",
|
||||
"content": "阅读采购商工作台 Dashboard 和仓库管理相关代码",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "2",
|
||||
"content": "设计水洗计划数据库表结构",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "3",
|
||||
"content": "创建新建水洗计划页面组件",
|
||||
"status": "completed",
|
||||
"priority": "high"
|
||||
},
|
||||
{
|
||||
"id": "4",
|
||||
"content": "添加路由配置",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
},
|
||||
{
|
||||
"id": "5",
|
||||
"content": "在 Dashboard 添加入口按钮",
|
||||
"status": "completed",
|
||||
"priority": "medium"
|
||||
}
|
||||
]
|
||||
690
README.md
690
README.md
@ -1,2 +1,688 @@
|
||||
# iloom-flatten
|
||||
auto sync from kihaneseifu/iloom
|
||||
# 纺织行业采购计划管理系统
|
||||
|
||||
一款专为纺织行业设计的全流程协作管理平台,连接采购商(布行)、纺织厂、水洗厂三方,实现从计划制定到成品交付的数字化管理。
|
||||
|
||||
## 核心功能
|
||||
|
||||
### 多角色协作
|
||||
- **采购商/布行**:创建生产计划、管理坯布库存、跟踪生产进度、处理结款
|
||||
- **纺织厂**:接收生产计划、管理生产流程、坯布入库、纱线库存管理
|
||||
- **水洗厂**:接收水洗订单、管理水洗流程
|
||||
|
||||
### 计划管理
|
||||
- 自动生成唯一计划编号和坯布识别码
|
||||
- 纱线配比配置与用量自动计算
|
||||
- 生产流程节点跟踪(确认计划 → 采纱 → 染纱 → 上机 → 坯布入库)
|
||||
- 实时进度可视化,支持97%完成度自动提醒
|
||||
|
||||
### 库存管理
|
||||
- **原坯布仓库**:按坯布码分组管理,入库记录追溯
|
||||
- 产品管理:支持按名称、克重、颜色多级分组展示
|
||||
- 出入库历史:查看每个产品的完整库存变动记录
|
||||
- 价格历史:追踪采购价格变动
|
||||
- **原料纱仓库**:库存预警、最低库存提醒
|
||||
- 实时库存数据同步,入库自动更新
|
||||
|
||||
### 结款管理
|
||||
- 按完成米数自动计算结款金额
|
||||
- 待结款汇总统计
|
||||
- 一键确认结款,记录结款时间
|
||||
|
||||
### 分享与导入
|
||||
- 加密分享链接,保护敏感信息
|
||||
- 支持剪贴板自动识别导入
|
||||
- 扫码或链接快速关联计划
|
||||
|
||||
## 技术特性
|
||||
|
||||
### 前端技术栈
|
||||
- **React 18** + TypeScript - 类型安全的函数组件开发
|
||||
- **TailwindCSS** - 原子化CSS,快速构建响应式界面
|
||||
- **Framer Motion** - 流畅的页面过渡和交互动画
|
||||
- **Lucide React** - 现代化图标库
|
||||
|
||||
### 移动端优化
|
||||
- 响应式布局,适配手机、平板、桌面端
|
||||
- 触控优化:44px最小触控区域、防双击缩放
|
||||
- 输入优化:数字键盘自动唤起、输入模式适配
|
||||
- 动画优化:硬件加速、自然动画曲线
|
||||
|
||||
### 后端服务
|
||||
- **Meoo Cloud (Supabase)** - 云数据库 + 认证 + 实时订阅
|
||||
- **PostgreSQL** - 关系型数据库,支持复杂查询
|
||||
- **Row Level Security** - 行级安全策略,基于公司 ID 的数据隔离
|
||||
- **Realtime** - 实时数据同步,入库记录即时更新
|
||||
|
||||
### 数据安全
|
||||
- **RLS 策略** - 所有表启用行级安全,严格的数据访问控制
|
||||
- **公司隔离** - 基于 company_id 的数据隔离,确保数据安全
|
||||
- **子账号支持** - 主账号/子账号权限继承,统一公司数据访问
|
||||
- **分享加密** - 分享链接使用 Base64 + 盐值混淆加密,保护敏感信息
|
||||
|
||||
## 快速开始
|
||||
|
||||
### 环境要求
|
||||
- Node.js 18+
|
||||
- pnpm 8+
|
||||
|
||||
### 安装依赖
|
||||
```bash
|
||||
pnpm install
|
||||
```
|
||||
|
||||
### 开发模式
|
||||
```bash
|
||||
pnpm run dev
|
||||
```
|
||||
服务启动在 http://localhost:3015
|
||||
|
||||
### 构建生产版本
|
||||
```bash
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
### 数据库迁移
|
||||
```bash
|
||||
# 查看云服务状态
|
||||
meoo-cli cloud status
|
||||
|
||||
# 执行数据库迁移
|
||||
meoo-cli cloud migrate --sql "..." --name "migration_name" --changes "变更说明"
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
src/
|
||||
├── components/ # 公共组件
|
||||
│ ├── ProcessFlow.tsx # 生产流程节点
|
||||
│ ├── PlanCard.tsx # 计划卡片
|
||||
│ ├── StatusBadge.tsx # 状态标签
|
||||
│ ├── InventoryRecordsModal.tsx # 入库记录弹窗
|
||||
│ ├── OnboardingGuide.tsx # 新用户引导
|
||||
│ ├── DemoDisclaimerModal.tsx # Demo免责声明
|
||||
│ └── ComingSoonModal.tsx # 功能开发中提示
|
||||
├── pages/ # 页面组件
|
||||
│ ├── purchaser/ # 采购商页面
|
||||
│ │ ├── Dashboard.tsx
|
||||
│ │ ├── PlanOverview.tsx
|
||||
│ │ ├── NewPlan.tsx
|
||||
│ │ ├── WarehouseManage.tsx
|
||||
│ │ └── FactoryManage.tsx
|
||||
│ ├── textile/ # 纺织厂页面
|
||||
│ │ ├── Dashboard.tsx
|
||||
│ │ ├── PlanOverview.tsx
|
||||
│ │ ├── YarnWarehouse.tsx
|
||||
│ │ ├── FabricWarehouse.tsx
|
||||
│ │ └── PaymentPending.tsx
|
||||
│ ├── washing/ # 水洗厂页面
|
||||
│ │ └── Dashboard.tsx
|
||||
│ ├── LoginPage.tsx
|
||||
│ ├── RegisterPage.tsx
|
||||
│ ├── RoleSelectPage.tsx
|
||||
│ ├── MemberManage.tsx
|
||||
│ └── ImportPlanPage.tsx
|
||||
├── hooks/ # 自定义Hooks
|
||||
│ ├── useResponsive.ts # 响应式检测
|
||||
│ └── useTheme.ts # 主题管理
|
||||
├── contexts/ # React上下文
|
||||
│ └── AuthContext.tsx # 认证上下文
|
||||
├── styles/ # 全局样式
|
||||
│ └── index.css
|
||||
├── supabase/ # Supabase客户端
|
||||
│ ├── client.ts
|
||||
│ └── types.ts
|
||||
└── utils/ # 工具函数
|
||||
├── crypto.ts
|
||||
└── shareCrypto.ts
|
||||
```
|
||||
|
||||
## 组件说明
|
||||
|
||||
### InventoryRecordsModal 入库记录弹窗
|
||||
统一风格的入库记录详情弹窗,支持采购商和纺织厂页面复用。
|
||||
|
||||
**特性:**
|
||||
- 统计摘要:显示总匹数和总米数
|
||||
- 记录列表:按时间倒序显示所有入库记录
|
||||
- 详细信息:日期时间、计划编号、工厂名称、批号、匹数、米数
|
||||
- 动画效果:Framer Motion 平滑动画
|
||||
|
||||
**使用示例:**
|
||||
```tsx
|
||||
import { InventoryRecordsModal } from '../../components/InventoryRecordsModal';
|
||||
|
||||
<InventoryRecordsModal
|
||||
isOpen={recordsModalOpen}
|
||||
onClose={() => setRecordsModalOpen(false)}
|
||||
records={selectedRecords}
|
||||
title="产品名称 - 入库记录"
|
||||
/>
|
||||
```
|
||||
|
||||
### OnboardingGuide 新用户引导
|
||||
首次进入系统时展示的功能引导动画,支持采购商和纺织厂角色。
|
||||
|
||||
**特性:**
|
||||
- 分步骤功能介绍
|
||||
- 支持跳转到对应功能区
|
||||
- 进度条和步骤指示器
|
||||
- 可跳过引导
|
||||
|
||||
### DemoDisclaimerModal Demo免责声明
|
||||
访问网站时显示的Demo阶段免责声明弹窗。
|
||||
|
||||
### ComingSoonModal 功能开发中
|
||||
点击未开发功能时显示的提示弹窗。
|
||||
|
||||
## 使用指南
|
||||
|
||||
### 采购商操作流程
|
||||
1. 注册/登录账号,选择"采购商"角色
|
||||
2. 创建新计划,填写产品信息、纱线配比
|
||||
3. 通过分享链接将计划发送给纺织厂
|
||||
4. 实时查看生产进度,管理坯布库存
|
||||
5. 生产完成后确认结款
|
||||
|
||||
### 纺织厂操作流程
|
||||
1. 注册/登录账号,选择"纺织厂"角色
|
||||
2. 通过分享链接或剪贴板导入计划
|
||||
3. 按流程节点确认生产进度
|
||||
4. 坯布入库时填写入库数量和匹数
|
||||
5. 查看待结款,确认收款
|
||||
|
||||
### 子账号管理
|
||||
- 主账号可创建子账号,分配不同权限
|
||||
- 子账号可独立操作,数据归属主账号公司
|
||||
- **用户名全局唯一**:子账号用户名不可与其他主账号或子账号重复
|
||||
|
||||
## 数据安全
|
||||
|
||||
- 分享链接采用加密传输,不包含敏感信息
|
||||
- 导入页面隐藏成品名称、颜色、色号等敏感字段
|
||||
- RLS策略确保数据隔离,仅授权用户可访问
|
||||
- 虚拟邮箱格式 `{username}@meoo.local` 保护隐私
|
||||
|
||||
## 浏览器支持
|
||||
|
||||
- Chrome 90+
|
||||
- Safari 14+
|
||||
- Firefox 88+
|
||||
- Edge 90+
|
||||
|
||||
## 更新日志
|
||||
|
||||
### 2025-05-25
|
||||
- **产品图片上传功能**
|
||||
- 为采购商原坯布仓库产品管理添加图片上传功能
|
||||
- 支持在产品创建和编辑时上传产品图片(JPG、PNG格式,最大5MB)
|
||||
- 产品列表展示40x40px缩略图,无图片时显示默认占位图标
|
||||
- 产品表单支持图片预览、重新上传和删除功能
|
||||
- 使用 Supabase Storage `product_images` 存储桶存储图片
|
||||
- 数据库 `products` 表新增 `image_url` 字段
|
||||
- **UI 优化**
|
||||
- 纺织厂工作台"原坯布仓库"更名为"已生产坯布"(页面标题和首页快捷操作)
|
||||
|
||||
### 2025-05-24
|
||||
- **新增出入库历史功能**
|
||||
- 采购商原坯布仓库产品列表新增"出入库历史"按钮
|
||||
- 支持查看每个产品的完整库存变动记录(批号、匹数、米数、时间)
|
||||
- 桌面端和移动端均支持
|
||||
- **类型系统优化**
|
||||
- 修复 `ProductInRecord` 类型定义,与数据库表结构保持一致
|
||||
- 区分数据库必需字段和前端展示扩展字段
|
||||
- **新增组件**
|
||||
- `OutboundForm.tsx` - 出库表单组件
|
||||
- `PlanEditModal.tsx` - 计划编辑弹窗
|
||||
- `NotificationCenter.tsx` - 通知中心
|
||||
- `NetworkStatusBar.tsx` - 网络状态栏
|
||||
- `VirtualList.tsx` - 虚拟列表组件
|
||||
- `ErrorBoundary.tsx` - 错误边界组件
|
||||
|
||||
### 2025-05-23
|
||||
- 优化纺织厂工作台UI动画流畅度
|
||||
- 全面适配移动端,优化触控体验
|
||||
- 添加实时数据订阅,入库记录自动更新
|
||||
- 优化坯布入库输入框布局
|
||||
- 修复采购商仓库管理数据同步问题
|
||||
- 创建统一的入库记录弹窗组件 `InventoryRecordsModal`
|
||||
|
||||
### 2025-05-22
|
||||
- 项目初始化
|
||||
- 完成基础架构搭建
|
||||
- 实现用户认证系统
|
||||
- 完成数据库设计和迁移
|
||||
|
||||
## 测试
|
||||
|
||||
### 类型检查
|
||||
```bash
|
||||
pnpm run typecheck
|
||||
```
|
||||
|
||||
### 代码规范
|
||||
```bash
|
||||
pnpm run lint
|
||||
```
|
||||
|
||||
### 构建验证
|
||||
```bash
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
## CI/CD 配置
|
||||
|
||||
项目使用 GitHub Actions 进行持续集成和部署:
|
||||
|
||||
### 工作流配置
|
||||
```yaml
|
||||
# .github/workflows/ci.yml
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, develop]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: pnpm/action-setup@v2
|
||||
with:
|
||||
version: 8
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 18
|
||||
cache: 'pnpm'
|
||||
- run: pnpm install
|
||||
- run: pnpm run typecheck
|
||||
- run: pnpm run lint
|
||||
- run: pnpm run build
|
||||
```
|
||||
|
||||
## 环境变量配置
|
||||
|
||||
项目使用以下环境变量:
|
||||
|
||||
### 开发环境 (.env.local)
|
||||
```env
|
||||
# Supabase 配置
|
||||
VITE_SUPABASE_URL=https://your-project.supabase.co
|
||||
VITE_SUPABASE_ANON_KEY=your-anon-key
|
||||
|
||||
# 应用配置
|
||||
VITE_APP_NAME=织机(Demo版)
|
||||
VITE_APP_VERSION=1.0.0
|
||||
```
|
||||
|
||||
### 生产环境
|
||||
生产环境变量通过 CI/CD 流水线注入,请勿在代码中硬编码敏感信息。
|
||||
|
||||
## API 文档
|
||||
|
||||
### Supabase 数据库 Schema
|
||||
|
||||
#### 核心表结构
|
||||
|
||||
**companies** - 公司表
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| name | TEXT | 公司名称 |
|
||||
| role | app_role | 角色:purchaser/textile/washing |
|
||||
| address | TEXT | 地址 |
|
||||
| contact_phone | TEXT | 联系电话 |
|
||||
|
||||
**production_plans** - 生产计划表
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| plan_code | TEXT | 计划编号 |
|
||||
| product_name | TEXT | 产品名称 |
|
||||
| color | TEXT | 颜色 |
|
||||
| fabric_code | TEXT | 坯布码 |
|
||||
| color_code | TEXT | 色号 |
|
||||
| purchaser_id | UUID | 采购商ID |
|
||||
| target_quantity | INTEGER | 计划产量 |
|
||||
| completed_quantity | INTEGER | 已完成产量 |
|
||||
| status | plan_status | 状态 |
|
||||
|
||||
**plan_factories** - 计划工厂关联表
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| plan_id | UUID | 计划ID |
|
||||
| factory_id | UUID | 工厂ID |
|
||||
| factory_type | factory_type | 工厂类型 |
|
||||
|
||||
**inventory_records** - 入库记录表
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| plan_id | UUID | 计划ID |
|
||||
| warehouse_id | UUID | 仓库ID |
|
||||
| quantity | DECIMAL | 入库数量 |
|
||||
| rolls | INTEGER | 入库匹数 |
|
||||
| operator_id | UUID | 操作人ID |
|
||||
|
||||
**product_inventory_records** - 产品出入库记录表
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | UUID | 主键 |
|
||||
| product_id | UUID | 产品ID |
|
||||
| company_id | UUID | 公司ID |
|
||||
| batch_no | TEXT | 批号 |
|
||||
| rolls | INTEGER | 匹数 |
|
||||
| meters | DECIMAL | 米数 |
|
||||
| notes | TEXT | 备注 |
|
||||
| operator_id | UUID | 操作人ID |
|
||||
| created_at | TIMESTAMPTZ | 创建时间 |
|
||||
|
||||
### 枚举类型
|
||||
|
||||
```sql
|
||||
-- 应用角色
|
||||
app_role: purchaser | textile | washing
|
||||
|
||||
-- 计划状态
|
||||
plan_status: pending | producing | completed
|
||||
|
||||
-- 工厂类型
|
||||
factory_type: textile | washing
|
||||
|
||||
-- 仓库类型
|
||||
warehouse_type: raw_fabric | fabric | finished | yarn
|
||||
|
||||
-- 结款状态
|
||||
payment_status: pending | completed
|
||||
```
|
||||
|
||||
### RLS 策略
|
||||
|
||||
所有表启用 Row Level Security,基于 company_id 进行数据隔离:
|
||||
|
||||
```sql
|
||||
-- 示例:production_plans 表 RLS 策略
|
||||
CREATE POLICY company_select_plans ON production_plans
|
||||
FOR SELECT USING (purchaser_id = get_user_master_company_id());
|
||||
|
||||
CREATE POLICY company_insert_plans ON production_plans
|
||||
FOR INSERT WITH CHECK (purchaser_id = get_user_master_company_id());
|
||||
```
|
||||
|
||||
### API 调用示例
|
||||
|
||||
**查询计划列表**
|
||||
```typescript
|
||||
const { data } = await supabase
|
||||
.from('production_plans')
|
||||
.select('*')
|
||||
.eq('purchaser_id', companyId)
|
||||
.order('created_at', { ascending: false });
|
||||
```
|
||||
|
||||
**创建入库记录**
|
||||
```typescript
|
||||
await supabase.from('inventory_records').insert({
|
||||
plan_id: planId,
|
||||
warehouse_id: warehouseId,
|
||||
quantity: quantity,
|
||||
rolls: rolls,
|
||||
operator_id: userId
|
||||
});
|
||||
```
|
||||
|
||||
**实时订阅库存更新**
|
||||
```typescript
|
||||
supabase
|
||||
.channel('inventory_changes')
|
||||
.on('postgres_changes', {
|
||||
event: '*',
|
||||
schema: 'public',
|
||||
table: 'inventory_records'
|
||||
}, callback)
|
||||
.subscribe();
|
||||
```
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License
|
||||
|
||||
## 技术支持
|
||||
|
||||
如有问题或建议,请联系开发团队。
|
||||
|
||||
---
|
||||
|
||||
## 常见问题与解决方案
|
||||
|
||||
### Q1: 页面白屏/无法加载
|
||||
**可能原因**:
|
||||
- Webpack 热更新失败
|
||||
- 类型检查错误阻止构建
|
||||
- 环境变量配置错误
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 清除缓存重新构建
|
||||
rm -rf node_modules dist
|
||||
pnpm install
|
||||
pnpm run dev
|
||||
|
||||
# 2. 检查类型错误
|
||||
pnpm run typecheck
|
||||
|
||||
# 3. 检查环境变量
|
||||
cat .env.local
|
||||
```
|
||||
|
||||
### Q2: 数据无法保存/读取
|
||||
**可能原因**:
|
||||
- RLS 策略限制
|
||||
- 网络连接问题
|
||||
- 权限不足
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查云服务状态
|
||||
meoo-cli cloud status
|
||||
|
||||
# 2. 检查 RLS 策略
|
||||
meoo-cli cloud query --sql "\dt"
|
||||
meoo-cli cloud query --sql "SELECT * FROM pg_policies WHERE tablename = 'your_table'"
|
||||
|
||||
# 3. 检查用户权限
|
||||
meoo-cli cloud query --sql "SELECT * FROM profiles WHERE id = 'your-user-id'"
|
||||
```
|
||||
|
||||
### Q3: 移动端样式错乱
|
||||
**可能原因**:
|
||||
- Tailwind 配置问题
|
||||
- 响应式断点使用错误
|
||||
- CSS 未正确加载
|
||||
|
||||
**解决方案**:
|
||||
```bash
|
||||
# 1. 检查 Tailwind 配置
|
||||
cat tailwind.config.js
|
||||
|
||||
# 2. 检查 PostCSS 配置
|
||||
cat postcss.config.js
|
||||
|
||||
# 3. 重新构建样式
|
||||
pnpm run build
|
||||
```
|
||||
|
||||
### Q4: 实时数据不更新
|
||||
**可能原因**:
|
||||
- Realtime 未启用
|
||||
- 订阅配置错误
|
||||
- 网络问题
|
||||
|
||||
**解决方案**:
|
||||
```typescript
|
||||
// 检查订阅是否正确设置
|
||||
const channel = supabase
|
||||
.channel('table_changes')
|
||||
.on('postgres_changes', {
|
||||
event: '*',
|
||||
schema: 'public',
|
||||
table: 'your_table'
|
||||
}, (payload) => {
|
||||
console.log('Change received:', payload);
|
||||
})
|
||||
.subscribe((status) => {
|
||||
console.log('Subscription status:', status);
|
||||
});
|
||||
```
|
||||
|
||||
### Q5: 开发服务器预览加载失败(沙箱环境)
|
||||
**现象**:
|
||||
- `pnpm run dev` 启动正常,端口 3015 在监听
|
||||
- 但浏览器预览无法加载,curl 请求超时
|
||||
|
||||
**根本原因**:
|
||||
- 沙箱环境网络限制:`net.ipv4.conf.all.forwarding = 0`
|
||||
- Webpack devServer 配置不当:`host: '127.0.0.1'` 无法在沙箱访问
|
||||
|
||||
**解决方案**:
|
||||
```javascript
|
||||
// webpack.config.js - 正确配置
|
||||
devServer: {
|
||||
port: 3015,
|
||||
host: '0.0.0.0', // 必须使用 0.0.0.0
|
||||
allowedHosts: 'all',
|
||||
hot: true,
|
||||
historyApiFallback: true,
|
||||
// 不要配置 static 和 devMiddleware
|
||||
}
|
||||
```
|
||||
|
||||
**验证方法**:
|
||||
```bash
|
||||
# 1. 类型检查
|
||||
pnpm run typecheck
|
||||
|
||||
# 2. 构建验证(关键)
|
||||
pnpm run build
|
||||
|
||||
# 3. 检查产物
|
||||
ls -la dist/
|
||||
|
||||
# 4. 启动服务器(沙箱中预览可能受限,但构建成功即可部署)
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
**注意**:沙箱环境中 curl 可能仍超时,这不影响实际部署。只要 `pnpm run build` 成功,应用即可正常发布。
|
||||
|
||||
---
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
### 1. 图片优化
|
||||
- 使用 WebP 格式
|
||||
- 实现懒加载
|
||||
- 使用 CDN 加速
|
||||
|
||||
### 2. 代码分割
|
||||
```typescript
|
||||
// 使用 React.lazy 进行代码分割
|
||||
const HeavyComponent = React.lazy(() => import('./HeavyComponent'));
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Suspense fallback={<Loading />}>
|
||||
<HeavyComponent />
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 数据缓存
|
||||
```typescript
|
||||
// 使用 SWR 或 React Query 进行数据缓存
|
||||
import useSWR from 'swr';
|
||||
|
||||
const { data, error } = useSWR('/api/data', fetcher, {
|
||||
revalidateOnFocus: false,
|
||||
dedupingInterval: 5000
|
||||
});
|
||||
```
|
||||
|
||||
### 4. 虚拟列表
|
||||
对于大数据列表,使用虚拟列表组件避免渲染过多 DOM 节点。
|
||||
|
||||
---
|
||||
|
||||
## 安全最佳实践
|
||||
|
||||
### 1. 输入验证
|
||||
```typescript
|
||||
// 始终验证用户输入
|
||||
const validateInput = (input: string): boolean => {
|
||||
// 防止 XSS
|
||||
const xssPattern = /<script|javascript:|onerror=/i;
|
||||
if (xssPattern.test(input)) return false;
|
||||
|
||||
// 防止 SQL 注入(虽然 Supabase 已防护)
|
||||
const sqlPattern = /(\b(SELECT|INSERT|UPDATE|DELETE|DROP|CREATE)\b)/i;
|
||||
if (sqlPattern.test(input)) return false;
|
||||
|
||||
return true;
|
||||
};
|
||||
```
|
||||
|
||||
### 2. 敏感数据处理
|
||||
```typescript
|
||||
// 不要在客户端暴露敏感信息
|
||||
// ❌ 错误
|
||||
const apiKey = 'sk-live-xxx';
|
||||
|
||||
// ✅ 正确 - 使用环境变量
|
||||
const apiKey = process.env.VITE_API_KEY;
|
||||
```
|
||||
|
||||
### 3. 认证检查
|
||||
```typescript
|
||||
// 每个需要认证的页面都添加检查
|
||||
useEffect(() => {
|
||||
const checkAuth = async () => {
|
||||
const { data: { user } } = await supabase.auth.getUser();
|
||||
if (!user) {
|
||||
navigate('/login');
|
||||
}
|
||||
};
|
||||
checkAuth();
|
||||
}, []);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 贡献指南
|
||||
|
||||
### 提交代码
|
||||
1. Fork 项目
|
||||
2. 创建功能分支 (`git checkout -b feature/xxx`)
|
||||
3. 提交更改 (`git commit -m 'Add xxx'`)
|
||||
4. 推送到分支 (`git push origin feature/xxx`)
|
||||
5. 创建 Pull Request
|
||||
|
||||
### 代码规范
|
||||
- 使用 TypeScript 严格模式
|
||||
- 遵循 ESLint 规则
|
||||
- 编写单元测试
|
||||
- 更新相关文档
|
||||
|
||||
### 提交信息规范
|
||||
```
|
||||
feat: 新增功能
|
||||
fix: 修复 bug
|
||||
docs: 文档更新
|
||||
style: 代码格式调整
|
||||
refactor: 重构代码
|
||||
test: 测试相关
|
||||
chore: 构建/工具相关
|
||||
```
|
||||
|
||||
65
assets/CLAUDE.md
Normal file
65
assets/CLAUDE.md
Normal file
@ -0,0 +1,65 @@
|
||||
# CLAUDE.md
|
||||
|
||||
Behavioral guidelines to reduce common LLM coding mistakes. Merge with project-specific instructions as needed.
|
||||
|
||||
**Tradeoff:** These guidelines bias toward caution over speed. For trivial tasks, use judgment.
|
||||
|
||||
## 1. Think Before Coding
|
||||
|
||||
**Don't assume. Don't hide confusion. Surface tradeoffs.**
|
||||
|
||||
Before implementing:
|
||||
- State your assumptions explicitly. If uncertain, ask.
|
||||
- If multiple interpretations exist, present them - don't pick silently.
|
||||
- If a simpler approach exists, say so. Push back when warranted.
|
||||
- If something is unclear, stop. Name what's confusing. Ask.
|
||||
|
||||
## 2. Simplicity First
|
||||
|
||||
**Minimum code that solves the problem. Nothing speculative.**
|
||||
|
||||
- No features beyond what was asked.
|
||||
- No abstractions for single-use code.
|
||||
- No "flexibility" or "configurability" that wasn't requested.
|
||||
- No error handling for impossible scenarios.
|
||||
- If you write 200 lines and it could be 50, rewrite it.
|
||||
|
||||
Ask yourself: "Would a senior engineer say this is overcomplicated?" If yes, simplify.
|
||||
|
||||
## 3. Surgical Changes
|
||||
|
||||
**Touch only what you must. Clean up only your own mess.**
|
||||
|
||||
When editing existing code:
|
||||
- Don't "improve" adjacent code, comments, or formatting.
|
||||
- Don't refactor things that aren't broken.
|
||||
- Match existing style, even if you'd do it differently.
|
||||
- If you notice unrelated dead code, mention it - don't delete it.
|
||||
|
||||
When your changes create orphans:
|
||||
- Remove imports/variables/functions that YOUR changes made unused.
|
||||
- Don't remove pre-existing dead code unless asked.
|
||||
|
||||
The test: Every changed line should trace directly to the user's request.
|
||||
|
||||
## 4. Goal-Driven Execution
|
||||
|
||||
**Define success criteria. Loop until verified.**
|
||||
|
||||
Transform tasks into verifiable goals:
|
||||
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
||||
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
||||
- "Refactor X" → "Ensure tests pass before and after"
|
||||
|
||||
For multi-step tasks, state a brief plan:
|
||||
```
|
||||
1. [Step] → verify: [check]
|
||||
2. [Step] → verify: [check]
|
||||
3. [Step] → verify: [check]
|
||||
```
|
||||
|
||||
Strong success criteria let you loop independently. Weak criteria ("make it work") require constant clarification.
|
||||
|
||||
---
|
||||
|
||||
**These guidelines are working if:** fewer unnecessary changes in diffs, fewer rewrites due to overcomplication, and clarifying questions come before implementation rather than after mistakes.
|
||||
BIN
assets/入库流程图.docx
Normal file
BIN
assets/入库流程图.docx
Normal file
Binary file not shown.
BIN
assets/微信图片_20260525195238_49_125.jpg
Normal file
BIN
assets/微信图片_20260525195238_49_125.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.4 KiB |
18
e2e/auth.setup.ts
Normal file
18
e2e/auth.setup.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { test as setup } from '@playwright/test';
|
||||
|
||||
const authFile = 'e2e/.auth/user.json';
|
||||
|
||||
setup('authenticate', async ({ page }) => {
|
||||
// 这里可以设置测试账号的登录状态
|
||||
// 实际项目中应该使用测试账号登录并保存状态
|
||||
|
||||
// 示例:登录流程
|
||||
// await page.goto('/login');
|
||||
// await page.fill('[name="username"]', 'test-user');
|
||||
// await page.fill('[name="password"]', 'test-password');
|
||||
// await page.click('button[type="submit"]');
|
||||
// await page.waitForURL('/purchaser');
|
||||
|
||||
// 保存登录状态
|
||||
// await page.context().storageState({ path: authFile });
|
||||
});
|
||||
182
e2e/collaboration-workflow.spec.ts
Normal file
182
e2e/collaboration-workflow.spec.ts
Normal file
@ -0,0 +1,182 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
/**
|
||||
* 协作流程测试
|
||||
* 核心路径:采购商创建计划 → 纺织厂确认 → 入库 → 采购商看到库存
|
||||
*
|
||||
* 注意:这些测试需要真实的数据库连接和测试账号
|
||||
* 在实际运行前需要配置测试环境
|
||||
*/
|
||||
|
||||
test.describe('协作流程 - 采购商视角', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// 登录采购商账号(需要配置测试账号)
|
||||
await page.goto('/login');
|
||||
// await loginAsPurchaser(page);
|
||||
});
|
||||
|
||||
test('采购商创建新计划', async ({ page }) => {
|
||||
// 导航到新建计划页面
|
||||
await page.goto('/purchaser/plans/new');
|
||||
|
||||
// 验证页面加载
|
||||
await expect(page.locator('h1')).toContainText('新建纺织计划');
|
||||
|
||||
// 填写计划表单
|
||||
await page.fill('[name="productName"]', '测试产品');
|
||||
await page.fill('[name="color"]', '红色');
|
||||
await page.fill('[name="targetQuantity"]', '1000');
|
||||
|
||||
// 添加纱线配比
|
||||
await page.click('text=添加纱线');
|
||||
await page.fill('[name="yarnName"]', '测试纱线');
|
||||
await page.fill('[name="ratio"]', '100');
|
||||
|
||||
// 提交表单
|
||||
// await page.click('button[type="submit"]');
|
||||
|
||||
// 验证创建成功
|
||||
// await expect(page).toHaveURL(/.*purchaser\/plans/);
|
||||
});
|
||||
|
||||
test('采购商查看计划列表', async ({ page }) => {
|
||||
await page.goto('/purchaser/plans');
|
||||
|
||||
// 验证页面加载
|
||||
await expect(page.locator('h1')).toContainText('计划总览');
|
||||
|
||||
// 验证计划列表存在
|
||||
await expect(page.locator('[data-testid="plan-list"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('采购商查看库存', async ({ page }) => {
|
||||
await page.goto('/purchaser/warehouse');
|
||||
|
||||
// 验证页面加载
|
||||
await expect(page.locator('h1')).toContainText('仓库管理');
|
||||
|
||||
// 验证库存列表
|
||||
await expect(page.locator('[data-testid="inventory-list"]')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('协作流程 - 纺织厂视角', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// 登录纺织厂账号
|
||||
await page.goto('/login');
|
||||
// await loginAsTextileFactory(page);
|
||||
});
|
||||
|
||||
test('纺织厂查看计划', async ({ page }) => {
|
||||
await page.goto('/textile/plans');
|
||||
|
||||
// 验证页面加载
|
||||
await expect(page.locator('h1')).toContainText('计划总览');
|
||||
|
||||
// 验证计划列表
|
||||
await expect(page.locator('[data-testid="plan-list"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('纺织厂确认流程节点', async ({ page }) => {
|
||||
await page.goto('/textile/plans');
|
||||
|
||||
// 找到待确认的计划
|
||||
const pendingPlan = page.locator('[data-testid="plan-card"]').first();
|
||||
await expect(pendingPlan).toBeVisible();
|
||||
|
||||
// 展开计划详情
|
||||
await pendingPlan.click();
|
||||
|
||||
// 点击确认按钮
|
||||
// await page.click('[data-testid="confirm-step-button"]');
|
||||
|
||||
// 验证确认成功
|
||||
// await expect(page.locator('[data-testid="step-completed"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('纺织厂坯布入库', async ({ page }) => {
|
||||
await page.goto('/textile/plans');
|
||||
|
||||
// 找到进行中的计划
|
||||
const activePlan = page.locator('[data-testid="plan-card"]').first();
|
||||
await expect(activePlan).toBeVisible();
|
||||
|
||||
// 展开计划
|
||||
await activePlan.click();
|
||||
|
||||
// 填写入库信息
|
||||
// await page.fill('[data-testid="inbound-quantity"]', '100');
|
||||
// await page.fill('[data-testid="inbound-rolls"]', '10');
|
||||
|
||||
// 提交入库
|
||||
// await page.click('[data-testid="submit-inbound"]');
|
||||
|
||||
// 验证入库成功
|
||||
// await expect(page.locator('[data-testid="inbound-success"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('纺织厂查看坯布仓库', async ({ page }) => {
|
||||
await page.goto('/textile/fabric-warehouse');
|
||||
|
||||
// 验证页面加载
|
||||
await expect(page.locator('h1')).toContainText('原坯布仓库');
|
||||
|
||||
// 验证库存列表
|
||||
await expect(page.locator('[data-testid="fabric-inventory"]')).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('数据同步验证', () => {
|
||||
test('入库后采购商实时看到库存更新', async ({ page, browser }) => {
|
||||
// 这个测试需要两个浏览器上下文模拟两个角色
|
||||
const purchaserContext = await browser.newContext();
|
||||
const textileContext = await browser.newContext();
|
||||
|
||||
const purchaserPage = await purchaserContext.newPage();
|
||||
const textilePage = await textileContext.newPage();
|
||||
|
||||
try {
|
||||
// 采购商查看初始库存
|
||||
await purchaserPage.goto('/purchaser/warehouse');
|
||||
// const initialInventory = await getInventoryCount(purchaserPage);
|
||||
|
||||
// 纺织厂执行入库
|
||||
await textilePage.goto('/textile/plans');
|
||||
// await textilePage.click('[data-testid="inbound-button"]');
|
||||
// await textilePage.fill('[data-testid="quantity"]', '100');
|
||||
// await textilePage.click('[data-testid="submit"]');
|
||||
|
||||
// 等待实时同步
|
||||
await purchaserPage.waitForTimeout(2000);
|
||||
|
||||
// 验证采购商看到更新后的库存
|
||||
// const updatedInventory = await getInventoryCount(purchaserPage);
|
||||
// expect(updatedInventory).toBe(initialInventory + 100);
|
||||
|
||||
} finally {
|
||||
await purchaserContext.close();
|
||||
await textileContext.close();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('分享链接流程', () => {
|
||||
test('通过分享链接导入计划', async ({ page }) => {
|
||||
// 访问分享链接
|
||||
const shareToken = 'test-token';
|
||||
await page.goto(`/import?token=${shareToken}`);
|
||||
|
||||
// 验证导入页面加载
|
||||
await expect(page.locator('h1')).toContainText('导入计划');
|
||||
|
||||
// 验证计划信息展示(不包含敏感信息)
|
||||
await expect(page.locator('[data-testid="plan-code"]')).toBeVisible();
|
||||
await expect(page.locator('[data-testid="fabric-code"]')).toBeVisible();
|
||||
|
||||
// 确认导入
|
||||
// await page.click('[data-testid="confirm-import"]');
|
||||
|
||||
// 验证导入成功
|
||||
// await expect(page).toHaveURL(/.*textile\/plans/);
|
||||
});
|
||||
});
|
||||
149
e2e/core-workflow.spec.ts
Normal file
149
e2e/core-workflow.spec.ts
Normal file
@ -0,0 +1,149 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('核心业务流程', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// 每个测试前导航到登录页
|
||||
await page.goto('/login');
|
||||
});
|
||||
|
||||
test('采购商登录并查看仪表盘', async ({ page }) => {
|
||||
// 验证登录页面加载
|
||||
await expect(page).toHaveURL(/.*login/);
|
||||
await expect(page.locator('h1')).toContainText('登录');
|
||||
|
||||
// 由于需要真实账号,这里只验证页面结构
|
||||
await expect(page.locator('input[name="username"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="password"]')).toBeVisible();
|
||||
await expect(page.locator('button[type="submit"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('角色选择页面', async ({ page }) => {
|
||||
await page.goto('/role-select');
|
||||
|
||||
// 验证角色选择页面
|
||||
await expect(page.locator('h1')).toContainText('选择角色');
|
||||
await expect(page.locator('text=采购商/布行')).toBeVisible();
|
||||
await expect(page.locator('text=纺织厂')).toBeVisible();
|
||||
await expect(page.locator('text=水洗厂')).toBeVisible();
|
||||
});
|
||||
|
||||
test('注册页面表单验证', async ({ page }) => {
|
||||
await page.goto('/register');
|
||||
|
||||
// 验证注册页面
|
||||
await expect(page.locator('h1')).toContainText('注册');
|
||||
|
||||
// 尝试提交空表单
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// 验证表单验证(假设有必填验证)
|
||||
await expect(page.locator('input[name="username"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="password"]')).toBeVisible();
|
||||
await expect(page.locator('input[name="confirmPassword"]')).toBeVisible();
|
||||
});
|
||||
|
||||
test('页面导航和路由', async ({ page }) => {
|
||||
// 测试路由导航
|
||||
await page.goto('/login');
|
||||
await expect(page).toHaveURL(/.*login/);
|
||||
|
||||
// 测试 404 回退
|
||||
await page.goto('/non-existent-page');
|
||||
// 应该显示登录页或 404
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
});
|
||||
|
||||
test('响应式布局 - 移动端适配', async ({ page }) => {
|
||||
// 设置移动端视口
|
||||
await page.setViewportSize({ width: 375, height: 667 });
|
||||
await page.goto('/login');
|
||||
|
||||
// 验证移动端布局
|
||||
await expect(page.locator('body')).toBeVisible();
|
||||
|
||||
// 检查是否有移动端特定的样式或元素
|
||||
const body = page.locator('body');
|
||||
await expect(body).toBeVisible();
|
||||
});
|
||||
|
||||
test('网络状态提示组件', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
// 模拟离线状态
|
||||
await page.context().setOffline(true);
|
||||
|
||||
// 等待离线提示出现
|
||||
await page.waitForTimeout(500);
|
||||
|
||||
// 恢复网络
|
||||
await page.context().setOffline(false);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('页面加载性能', () => {
|
||||
test('首页加载时间', async ({ page }) => {
|
||||
const startTime = Date.now();
|
||||
await page.goto('/login');
|
||||
const loadTime = Date.now() - startTime;
|
||||
|
||||
// 验证页面在合理时间内加载
|
||||
expect(loadTime).toBeLessThan(5000);
|
||||
|
||||
// 验证关键元素渲染
|
||||
await expect(page.locator('h1')).toBeVisible();
|
||||
});
|
||||
|
||||
test('资源加载无错误', async ({ page }) => {
|
||||
const errors: string[] = [];
|
||||
|
||||
page.on('console', (msg) => {
|
||||
if (msg.type() === 'error') {
|
||||
errors.push(msg.text());
|
||||
}
|
||||
});
|
||||
|
||||
page.on('pageerror', (error) => {
|
||||
errors.push(error.message);
|
||||
});
|
||||
|
||||
await page.goto('/login');
|
||||
await page.waitForLoadState('networkidle');
|
||||
|
||||
// 允许一些预期的错误(如 API 调用)
|
||||
const unexpectedErrors = errors.filter(e =>
|
||||
!e.includes('supabase') &&
|
||||
!e.includes('api') &&
|
||||
!e.includes('favicon')
|
||||
);
|
||||
|
||||
expect(unexpectedErrors).toHaveLength(0);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('无障碍测试', () => {
|
||||
test('登录页表单可访问性', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
// 检查表单元素是否有正确的标签
|
||||
const usernameInput = page.locator('input[name="username"]');
|
||||
const passwordInput = page.locator('input[name="password"]');
|
||||
|
||||
await expect(usernameInput).toHaveAttribute('placeholder');
|
||||
await expect(passwordInput).toHaveAttribute('placeholder');
|
||||
|
||||
// 检查按钮可点击
|
||||
const submitButton = page.locator('button[type="submit"]');
|
||||
await expect(submitButton).toBeEnabled();
|
||||
});
|
||||
|
||||
test('键盘导航', async ({ page }) => {
|
||||
await page.goto('/login');
|
||||
|
||||
// 使用 Tab 键导航
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(page.locator('input[name="username"]"]')).toBeFocused();
|
||||
|
||||
await page.keyboard.press('Tab');
|
||||
await expect(page.locator('input[name="password"]"]')).toBeFocused();
|
||||
});
|
||||
});
|
||||
176
functions/data-consistency-check/index.ts
Normal file
176
functions/data-consistency-check/index.ts
Normal file
@ -0,0 +1,176 @@
|
||||
// 数据一致性校验与修复 Edge Function
|
||||
// 定期检查并修复 completed_quantity 与 inventory_records 不一致的问题
|
||||
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
// CORS 预检
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response('ok', {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const corsHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
|
||||
try {
|
||||
const body = await req.json();
|
||||
const { action, planId } = body; // action: 'check' | 'fix' | 'check-all'
|
||||
|
||||
// 获取认证信息
|
||||
const authHeader = req.headers.get('Authorization') || '';
|
||||
|
||||
// 创建管理员客户端(绕过 RLS)
|
||||
const supabaseAdmin = createClient(
|
||||
Deno.env.get('SUPABASE_URL')!,
|
||||
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
|
||||
);
|
||||
|
||||
// 检查单个计划的数据一致性
|
||||
const checkPlanConsistency = async (pid: string) => {
|
||||
// 获取计划信息
|
||||
const { data: plan } = await supabaseAdmin
|
||||
.from('production_plans')
|
||||
.select('id, plan_code, completed_quantity, target_quantity')
|
||||
.eq('id', pid)
|
||||
.maybeSingle();
|
||||
|
||||
if (!plan) return null;
|
||||
|
||||
// 计算入库记录总和
|
||||
const { data: records } = await supabaseAdmin
|
||||
.from('inventory_records')
|
||||
.select('quantity')
|
||||
.eq('plan_id', pid);
|
||||
|
||||
const inventoryTotal = (records || []).reduce((sum, r) => sum + (r.quantity || 0), 0);
|
||||
const completedQuantity = plan.completed_quantity || 0;
|
||||
const diff = inventoryTotal - completedQuantity;
|
||||
|
||||
return {
|
||||
planId: pid,
|
||||
planCode: plan.plan_code,
|
||||
completedQuantity,
|
||||
inventoryTotal,
|
||||
diff,
|
||||
isConsistent: diff === 0,
|
||||
};
|
||||
};
|
||||
|
||||
// 检查所有计划的数据一致性
|
||||
const checkAllPlans = async () => {
|
||||
const { data: plans } = await supabaseAdmin
|
||||
.from('production_plans')
|
||||
.select('id');
|
||||
|
||||
const results = [];
|
||||
for (const plan of (plans || [])) {
|
||||
const result = await checkPlanConsistency(plan.id);
|
||||
if (result && !result.isConsistent) {
|
||||
results.push(result);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
};
|
||||
|
||||
// 修复不一致的数据
|
||||
const fixInconsistency = async (pid: string) => {
|
||||
const check = await checkPlanConsistency(pid);
|
||||
if (!check || check.isConsistent) {
|
||||
return { fixed: false, message: '数据已一致,无需修复' };
|
||||
}
|
||||
|
||||
// 以 inventory_records 为准修复 completed_quantity
|
||||
const { data: records } = await supabaseAdmin
|
||||
.from('inventory_records')
|
||||
.select('quantity')
|
||||
.eq('plan_id', pid);
|
||||
|
||||
const inventoryTotal = (records || []).reduce((sum, r) => sum + (r.quantity || 0), 0);
|
||||
|
||||
const { error } = await supabaseAdmin
|
||||
.from('production_plans')
|
||||
.update({ completed_quantity: inventoryTotal })
|
||||
.eq('id', pid);
|
||||
|
||||
if (error) {
|
||||
return { fixed: false, error: error.message };
|
||||
}
|
||||
|
||||
return {
|
||||
fixed: true,
|
||||
planId: pid,
|
||||
oldValue: check.completedQuantity,
|
||||
newValue: inventoryTotal,
|
||||
diff: check.diff,
|
||||
};
|
||||
};
|
||||
|
||||
let result;
|
||||
|
||||
switch (action) {
|
||||
case 'check':
|
||||
if (!planId) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: 'check 操作需要提供 planId' }),
|
||||
{ status: 400, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
result = await checkPlanConsistency(planId);
|
||||
break;
|
||||
|
||||
case 'check-all':
|
||||
result = await checkAllPlans();
|
||||
break;
|
||||
|
||||
case 'fix':
|
||||
if (!planId) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: 'fix 操作需要提供 planId' }),
|
||||
{ status: 400, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
result = await fixInconsistency(planId);
|
||||
break;
|
||||
|
||||
case 'fix-all':
|
||||
const inconsistentPlans = await checkAllPlans();
|
||||
const fixResults = [];
|
||||
for (const plan of inconsistentPlans) {
|
||||
const fixResult = await fixInconsistency(plan.planId);
|
||||
fixResults.push(fixResult);
|
||||
}
|
||||
result = {
|
||||
totalChecked: inconsistentPlans.length,
|
||||
fixed: fixResults.filter(r => r.fixed).length,
|
||||
details: fixResults,
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
return new Response(
|
||||
JSON.stringify({ error: '无效的操作类型,支持: check, check-all, fix, fix-all' }),
|
||||
{ status: 400, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({ success: true, data: result }),
|
||||
{ headers: corsHeaders }
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
return new Response(
|
||||
JSON.stringify({ error: '服务器错误: ' + message }),
|
||||
{ status: 500, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
});
|
||||
148
functions/fabric-warehouse-inbound/index.ts
Normal file
148
functions/fabric-warehouse-inbound/index.ts
Normal file
@ -0,0 +1,148 @@
|
||||
// 坯布入库事务处理 Edge Function
|
||||
// 确保 completed_quantity 和 inventory_records 数据一致性
|
||||
|
||||
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2';
|
||||
|
||||
Deno.serve(async (req) => {
|
||||
// CORS 预检
|
||||
if (req.method === 'OPTIONS') {
|
||||
return new Response('ok', {
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
'Access-Control-Allow-Methods': 'POST, OPTIONS',
|
||||
'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
const corsHeaders = {
|
||||
'Content-Type': 'application/json',
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
};
|
||||
|
||||
try {
|
||||
const body = await req.json();
|
||||
const {
|
||||
planId,
|
||||
quantity,
|
||||
rolls,
|
||||
warehouseId,
|
||||
warehouseLocation,
|
||||
operatorId,
|
||||
pricePerMeter,
|
||||
} = body;
|
||||
|
||||
// 参数验证
|
||||
if (!planId || !quantity || quantity <= 0) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: '缺少必要参数或数量无效' }),
|
||||
{ status: 400, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
// 获取认证信息
|
||||
const authHeader = req.headers.get('Authorization') || '';
|
||||
|
||||
// 创建管理员客户端(绕过 RLS)
|
||||
const supabaseAdmin = createClient(
|
||||
Deno.env.get('SUPABASE_URL')!,
|
||||
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!,
|
||||
);
|
||||
|
||||
// 开始事务处理
|
||||
// 1. 获取当前计划信息
|
||||
const { data: plan, error: planError } = await supabaseAdmin
|
||||
.from('production_plans')
|
||||
.select('completed_quantity, target_quantity, purchaser_id')
|
||||
.eq('id', planId)
|
||||
.maybeSingle();
|
||||
|
||||
if (planError || !plan) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: '获取计划信息失败: ' + (planError?.message || '计划不存在') }),
|
||||
{ status: 404, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
// 2. 计算新的已完成数量
|
||||
const newCompletedQuantity = (plan.completed_quantity || 0) + quantity;
|
||||
|
||||
// 3. 检查是否超过目标数量
|
||||
if (newCompletedQuantity > plan.target_quantity) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: `入库数量超过剩余数量 (${plan.target_quantity - (plan.completed_quantity || 0)}米)` }),
|
||||
{ status: 400, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
const now = new Date().toISOString();
|
||||
|
||||
// 4. 更新计划的 completed_quantity
|
||||
const { error: updateError } = await supabaseAdmin
|
||||
.from('production_plans')
|
||||
.update({ completed_quantity: newCompletedQuantity })
|
||||
.eq('id', planId);
|
||||
|
||||
if (updateError) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: '更新计划数量失败: ' + updateError.message }),
|
||||
{ status: 500, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
// 5. 创建入库记录
|
||||
const insertData: any = {
|
||||
plan_id: planId,
|
||||
quantity: quantity,
|
||||
rolls: rolls || 0,
|
||||
warehouse_location: warehouseLocation || '',
|
||||
operator_id: operatorId,
|
||||
price_per_meter: pricePerMeter || 0,
|
||||
created_at: now,
|
||||
};
|
||||
|
||||
if (warehouseId) {
|
||||
insertData.warehouse_id = warehouseId;
|
||||
}
|
||||
|
||||
const { data: inventoryRecord, error: insertError } = await supabaseAdmin
|
||||
.from('inventory_records')
|
||||
.insert(insertData)
|
||||
.select()
|
||||
.single();
|
||||
|
||||
if (insertError) {
|
||||
// 如果入库记录创建失败,需要回滚 completed_quantity
|
||||
// 注意:这里简化处理,实际生产环境应使用数据库事务
|
||||
await supabaseAdmin
|
||||
.from('production_plans')
|
||||
.update({ completed_quantity: plan.completed_quantity })
|
||||
.eq('id', planId);
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({ error: '创建入库记录失败: ' + insertError.message }),
|
||||
{ status: 500, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
|
||||
// 6. 返回成功结果
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
success: true,
|
||||
data: {
|
||||
inventoryRecord,
|
||||
completedQuantity: newCompletedQuantity,
|
||||
progress: Math.round((newCompletedQuantity / plan.target_quantity) * 100),
|
||||
},
|
||||
}),
|
||||
{ headers: corsHeaders }
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : 'Unknown error';
|
||||
return new Response(
|
||||
JSON.stringify({ error: '服务器错误: ' + message }),
|
||||
{ status: 500, headers: corsHeaders }
|
||||
);
|
||||
}
|
||||
});
|
||||
56
index.html
Normal file
56
index.html
Normal file
@ -0,0 +1,56 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>织机 - 以AI为梭,织天地经纬</title>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<style>
|
||||
/* 内联样式确保主题色立即生效,避免闪烁 */
|
||||
html, body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
html.light, html.light body {
|
||||
background-color: #ffffff !important;
|
||||
color: #000000;
|
||||
}
|
||||
html.dark, html.dark body {
|
||||
background-color: #1a1a1a !important;
|
||||
color: #ffffff;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
// 在 React 加载前立即设置主题,避免闪烁
|
||||
(function() {
|
||||
const isInIframe = window.self !== window.top;
|
||||
|
||||
function applyThemeToDOM(theme) {
|
||||
document.documentElement.classList.remove('light', 'dark');
|
||||
document.documentElement.classList.add(theme);
|
||||
document.documentElement.setAttribute('data-theme', theme);
|
||||
}
|
||||
|
||||
if (isInIframe) {
|
||||
// 监听父窗口主动推送的主题消息
|
||||
window.addEventListener('message', function(event) {
|
||||
if (event.data && typeof event.data.theme === 'string') {
|
||||
const theme = event.data.theme;
|
||||
if (theme === 'light' || theme === 'dark') {
|
||||
applyThemeToDOM(theme);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 非 iframe 环境,使用默认 light 主题
|
||||
applyThemeToDOM('light');
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
34
jest.config.js
Normal file
34
jest.config.js
Normal file
@ -0,0 +1,34 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'jsdom',
|
||||
roots: ['<rootDir>/src'],
|
||||
testMatch: ['**/__tests__/**/*.test.ts', '**/__tests__/**/*.test.tsx'],
|
||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json'],
|
||||
setupFilesAfterEnv: ['<rootDir>/src/__tests__/setup.ts'],
|
||||
moduleNameMapper: {
|
||||
'^@/(.*)$': '<rootDir>/src/$1',
|
||||
},
|
||||
collectCoverageFrom: [
|
||||
'src/**/*.{ts,tsx}',
|
||||
'!src/**/*.d.ts',
|
||||
'!src/__tests__/**',
|
||||
'!src/index.tsx',
|
||||
'!src/App.tsx',
|
||||
],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
branches: 30,
|
||||
functions: 30,
|
||||
lines: 30,
|
||||
statements: 30,
|
||||
},
|
||||
},
|
||||
transform: {
|
||||
'^.+\\.tsx?$': ['ts-jest', {
|
||||
tsconfig: {
|
||||
jsx: 'react-jsx',
|
||||
esModuleInterop: true,
|
||||
},
|
||||
}],
|
||||
},
|
||||
};
|
||||
46
migrations/20260523_052639_create_base_tables.sql
Normal file
46
migrations/20260523_052639_create_base_tables.sql
Normal file
@ -0,0 +1,46 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 自定义枚举类型
|
||||
CREATE TYPE public.app_role AS ENUM ('purchaser', 'textile', 'washing');
|
||||
CREATE TYPE public.factory_type AS ENUM ('textile', 'washing');
|
||||
CREATE TYPE public.plan_status AS ENUM ('pending', 'producing', 'completed');
|
||||
CREATE TYPE public.step_type AS ENUM ('confirm', 'yarn_purchase', 'dyeing', 'machine_start', 'fabric_warehouse');
|
||||
CREATE TYPE public.step_status AS ENUM ('pending', 'active', 'completed');
|
||||
CREATE TYPE public.warehouse_type AS ENUM ('raw_fabric', 'fabric', 'finished', 'yarn');
|
||||
CREATE TYPE public.payment_status AS ENUM ('pending', 'completed');
|
||||
|
||||
-- 公司表
|
||||
CREATE TABLE public.companies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
role public.app_role NOT NULL,
|
||||
address TEXT,
|
||||
contact_phone TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 用户配置表
|
||||
CREATE TABLE public.profiles (
|
||||
id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
phone TEXT,
|
||||
company_id UUID REFERENCES public.companies(id) ON DELETE SET NULL,
|
||||
is_master BOOLEAN NOT NULL DEFAULT true,
|
||||
master_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 公司成员表
|
||||
CREATE TABLE public.company_members (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
company_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE,
|
||||
role TEXT NOT NULL DEFAULT 'member',
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(company_id, user_id)
|
||||
);
|
||||
|
||||
48
migrations/20260523_052709_create_plan_tables.sql
Normal file
48
migrations/20260523_052709_create_plan_tables.sql
Normal file
@ -0,0 +1,48 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 生产计划表
|
||||
CREATE TABLE public.production_plans (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
plan_code TEXT UNIQUE NOT NULL,
|
||||
product_name TEXT NOT NULL,
|
||||
color TEXT NOT NULL,
|
||||
fabric_code TEXT NOT NULL,
|
||||
color_code TEXT NOT NULL DEFAULT '01',
|
||||
remark TEXT,
|
||||
purchaser_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
target_quantity INTEGER NOT NULL DEFAULT 0,
|
||||
completed_quantity INTEGER NOT NULL DEFAULT 0,
|
||||
yarn_usage_per_meter DECIMAL DEFAULT 0,
|
||||
production_price DECIMAL DEFAULT 0,
|
||||
status public.plan_status NOT NULL DEFAULT 'pending',
|
||||
start_time TIMESTAMPTZ,
|
||||
created_by UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 计划与工厂关联表
|
||||
CREATE TABLE public.plan_factories (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
plan_id UUID NOT NULL REFERENCES public.production_plans(id) ON DELETE CASCADE,
|
||||
factory_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
factory_type public.factory_type NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
||||
UNIQUE(plan_id, factory_id)
|
||||
);
|
||||
|
||||
-- 纱线配比表
|
||||
CREATE TABLE public.yarn_ratios (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
plan_id UUID NOT NULL REFERENCES public.production_plans(id) ON DELETE CASCADE,
|
||||
yarn_name TEXT NOT NULL,
|
||||
ratio DECIMAL NOT NULL DEFAULT 1,
|
||||
amount_per_meter DECIMAL NOT NULL DEFAULT 0,
|
||||
total_amount DECIMAL NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
40
migrations/20260523_052735_create_warehouse_tables.sql
Normal file
40
migrations/20260523_052735_create_warehouse_tables.sql
Normal file
@ -0,0 +1,40 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 仓库表
|
||||
CREATE TABLE public.warehouses (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
company_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
type public.warehouse_type NOT NULL,
|
||||
location TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 入库记录表
|
||||
CREATE TABLE public.inventory_records (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
plan_id UUID NOT NULL REFERENCES public.production_plans(id) ON DELETE CASCADE,
|
||||
warehouse_id UUID NOT NULL REFERENCES public.warehouses(id) ON DELETE CASCADE,
|
||||
quantity DECIMAL NOT NULL DEFAULT 0,
|
||||
warehouse_location TEXT,
|
||||
operator_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 纱线库存表
|
||||
CREATE TABLE public.yarn_stock (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
company_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
warehouse_id UUID REFERENCES public.warehouses(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
spec TEXT,
|
||||
quantity DECIMAL NOT NULL DEFAULT 0,
|
||||
min_stock DECIMAL NOT NULL DEFAULT 0,
|
||||
unit TEXT NOT NULL DEFAULT 'kg',
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 流程节点表
|
||||
CREATE TABLE public.plan_process_steps (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
plan_id UUID NOT NULL REFERENCES public.production_plans(id) ON DELETE CASCADE,
|
||||
step_type public.step_type NOT NULL,
|
||||
status public.step_status NOT NULL DEFAULT 'pending',
|
||||
timestamp TIMESTAMPTZ,
|
||||
operator_id UUID REFERENCES auth.users(id) ON DELETE SET NULL,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 结款记录表
|
||||
CREATE TABLE public.payments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
plan_id UUID NOT NULL REFERENCES public.production_plans(id) ON DELETE CASCADE,
|
||||
from_company_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
to_company_id UUID NOT NULL REFERENCES public.companies(id) ON DELETE CASCADE,
|
||||
amount DECIMAL NOT NULL DEFAULT 0,
|
||||
quantity DECIMAL NOT NULL DEFAULT 0,
|
||||
price_per_meter DECIMAL NOT NULL DEFAULT 0,
|
||||
status public.payment_status NOT NULL DEFAULT 'pending',
|
||||
paid_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
73
migrations/20260523_052842_enable_rls_all_tables.sql
Normal file
73
migrations/20260523_052842_enable_rls_all_tables.sql
Normal file
@ -0,0 +1,73 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 启用所有表的 RLS
|
||||
ALTER TABLE public.companies ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.company_members ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.production_plans ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.plan_factories ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.yarn_ratios ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.warehouses ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.inventory_records ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.yarn_stock ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.plan_process_steps ENABLE ROW LEVEL SECURITY;
|
||||
ALTER TABLE public.payments ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- companies: 所有人可查看,登录用户可创建/修改自己公司的
|
||||
CREATE POLICY anon_select_companies ON public.companies FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_companies ON public.companies FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_update_companies ON public.companies FOR UPDATE USING (true);
|
||||
|
||||
-- profiles: 登录用户可查看所有profile,只能修改自己的
|
||||
CREATE POLICY anon_select_profiles ON public.profiles FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_profiles ON public.profiles FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY users_update_own_profile ON public.profiles FOR UPDATE USING (auth.uid() = id);
|
||||
|
||||
-- company_members: 所有人可查看和创建
|
||||
CREATE POLICY anon_select_company_members ON public.company_members FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_company_members ON public.company_members FOR INSERT WITH CHECK (true);
|
||||
|
||||
-- production_plans: 所有人可查看,登录用户可创建/修改
|
||||
CREATE POLICY anon_select_plans ON public.production_plans FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_plans ON public.production_plans FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_update_plans ON public.production_plans FOR UPDATE USING (true);
|
||||
CREATE POLICY anon_delete_plans ON public.production_plans FOR DELETE USING (true);
|
||||
|
||||
-- plan_factories: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_plan_factories ON public.plan_factories FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_plan_factories ON public.plan_factories FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_delete_plan_factories ON public.plan_factories FOR DELETE USING (true);
|
||||
|
||||
-- yarn_ratios: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_yarn_ratios ON public.yarn_ratios FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_yarn_ratios ON public.yarn_ratios FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_delete_yarn_ratios ON public.yarn_ratios FOR DELETE USING (true);
|
||||
|
||||
-- warehouses: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_warehouses ON public.warehouses FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_warehouses ON public.warehouses FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_update_warehouses ON public.warehouses FOR UPDATE USING (true);
|
||||
|
||||
-- inventory_records: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_inventory ON public.inventory_records FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_inventory ON public.inventory_records FOR INSERT WITH CHECK (true);
|
||||
|
||||
-- yarn_stock: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_yarn_stock ON public.yarn_stock FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_yarn_stock ON public.yarn_stock FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_update_yarn_stock ON public.yarn_stock FOR UPDATE USING (true);
|
||||
|
||||
-- plan_process_steps: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_process_steps ON public.plan_process_steps FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_process_steps ON public.plan_process_steps FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_update_process_steps ON public.plan_process_steps FOR UPDATE USING (true);
|
||||
|
||||
-- payments: 所有人可查看和操作
|
||||
CREATE POLICY anon_select_payments ON public.payments FOR SELECT USING (true);
|
||||
CREATE POLICY anon_insert_payments ON public.payments FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY anon_update_payments ON public.payments FOR UPDATE USING (true);
|
||||
|
||||
66
migrations/20260523_052936_create_test_users.sql
Normal file
66
migrations/20260523_052936_create_test_users.sql
Normal file
@ -0,0 +1,66 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
INSERT INTO auth.users (
|
||||
instance_id, id, aud, role, email,
|
||||
encrypted_password, email_confirmed_at,
|
||||
created_at, updated_at,
|
||||
confirmation_token, recovery_token,
|
||||
email_change_token_new, email_change,
|
||||
raw_app_meta_data, raw_user_meta_data,
|
||||
is_super_admin
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000000',
|
||||
'a0000001-0000-0000-0000-000000000001'::uuid, 'authenticated', 'authenticated',
|
||||
'purchaser@meoo.local',
|
||||
crypt('123456', gen_salt('bf')),
|
||||
NOW(), NOW(), NOW(),
|
||||
'', '', '', '',
|
||||
'{"provider":"email","providers":["email"]}'::jsonb,
|
||||
'{"username":"purchaser"}'::jsonb,
|
||||
false
|
||||
);
|
||||
|
||||
INSERT INTO auth.users (
|
||||
instance_id, id, aud, role, email,
|
||||
encrypted_password, email_confirmed_at,
|
||||
created_at, updated_at,
|
||||
confirmation_token, recovery_token,
|
||||
email_change_token_new, email_change,
|
||||
raw_app_meta_data, raw_user_meta_data,
|
||||
is_super_admin
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000000',
|
||||
'a0000002-0000-0000-0000-000000000002'::uuid, 'authenticated', 'authenticated',
|
||||
'textile@meoo.local',
|
||||
crypt('123456', gen_salt('bf')),
|
||||
NOW(), NOW(), NOW(),
|
||||
'', '', '', '',
|
||||
'{"provider":"email","providers":["email"]}'::jsonb,
|
||||
'{"username":"textile"}'::jsonb,
|
||||
false
|
||||
);
|
||||
|
||||
INSERT INTO auth.users (
|
||||
instance_id, id, aud, role, email,
|
||||
encrypted_password, email_confirmed_at,
|
||||
created_at, updated_at,
|
||||
confirmation_token, recovery_token,
|
||||
email_change_token_new, email_change,
|
||||
raw_app_meta_data, raw_user_meta_data,
|
||||
is_super_admin
|
||||
) VALUES (
|
||||
'00000000-0000-0000-0000-000000000000',
|
||||
'a0000003-0000-0000-0000-000000000003'::uuid, 'authenticated', 'authenticated',
|
||||
'washing@meoo.local',
|
||||
crypt('123456', gen_salt('bf')),
|
||||
NOW(), NOW(), NOW(),
|
||||
'', '', '', '',
|
||||
'{"provider":"email","providers":["email"]}'::jsonb,
|
||||
'{"username":"washing"}'::jsonb,
|
||||
false
|
||||
);
|
||||
|
||||
37
migrations/20260523_053030_seed_companies_and_profiles.sql
Normal file
37
migrations/20260523_053030_seed_companies_and_profiles.sql
Normal file
@ -0,0 +1,37 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 创建公司
|
||||
INSERT INTO public.companies (id, name, role, address, contact_phone) VALUES
|
||||
('11111111-1111-1111-1111-111111111101', '示例布行', 'purchaser', '浙江省杭州市', '13800138000'),
|
||||
('11111111-1111-1111-1111-111111111102', '示例纺织厂', 'textile', '浙江省绍兴市', '13800138001'),
|
||||
('11111111-1111-1111-1111-111111111103', '示例水洗厂', 'washing', '广东省广州市', '13800138002');
|
||||
|
||||
-- 创建 profiles
|
||||
INSERT INTO public.profiles (id, username, phone, company_id, is_master) VALUES
|
||||
('a0000001-0000-0000-0000-000000000001', 'purchaser', '13800138000', '11111111-1111-1111-1111-111111111101', true),
|
||||
('a0000002-0000-0000-0000-000000000002', 'textile', '13800138001', '11111111-1111-1111-1111-111111111102', true),
|
||||
('a0000003-0000-0000-0000-000000000003', 'washing', '13800138002', '11111111-1111-1111-1111-111111111103', true);
|
||||
|
||||
-- 创建公司成员
|
||||
INSERT INTO public.company_members (company_id, user_id, role) VALUES
|
||||
('11111111-1111-1111-1111-111111111101', 'a0000001-0000-0000-0000-000000000001', 'master'),
|
||||
('11111111-1111-1111-1111-111111111102', 'a0000002-0000-0000-0000-000000000002', 'master'),
|
||||
('11111111-1111-1111-1111-111111111103', 'a0000003-0000-0000-0000-000000000003', 'master');
|
||||
|
||||
-- 创建仓库
|
||||
INSERT INTO public.warehouses (id, company_id, name, type, location) VALUES
|
||||
('22222222-2222-2222-2222-222222222201', '11111111-1111-1111-1111-111111111101', '原坯布仓库', 'raw_fabric', 'A区-01'),
|
||||
('22222222-2222-2222-2222-222222222202', '11111111-1111-1111-1111-111111111101', '坯布仓库', 'fabric', 'B区-01'),
|
||||
('22222222-2222-2222-2222-222222222203', '11111111-1111-1111-1111-111111111101', '成品仓库', 'finished', 'C区-01'),
|
||||
('22222222-2222-2222-2222-222222222204', '11111111-1111-1111-1111-111111111102', '原料纱仓库', 'yarn', '绍兴厂区');
|
||||
|
||||
-- 创建纱线库存
|
||||
INSERT INTO public.yarn_stock (company_id, warehouse_id, name, spec, quantity, min_stock, unit) VALUES
|
||||
('11111111-1111-1111-1111-111111111102', '22222222-2222-2222-2222-222222222204', '棉纱32S', '32支纯棉', 500, 100, 'kg'),
|
||||
('11111111-1111-1111-1111-111111111102', '22222222-2222-2222-2222-222222222204', '涤纶纱', '75D/36F', 30, 50, 'kg'),
|
||||
('11111111-1111-1111-1111-111111111102', '22222222-2222-2222-2222-222222222204', '氨纶', '40D', 200, 80, 'kg');
|
||||
|
||||
37
migrations/20260523_053110_seed_plans_and_related.sql
Normal file
37
migrations/20260523_053110_seed_plans_and_related.sql
Normal file
@ -0,0 +1,37 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 创建示例生产计划
|
||||
INSERT INTO public.production_plans (id, plan_code, product_name, color, fabric_code, color_code, remark, purchaser_id, target_quantity, completed_quantity, yarn_usage_per_meter, production_price, status, start_time, created_by) VALUES
|
||||
('33333333-3333-3333-3333-333333333301', 'PLAN-2026-001', '水洗棉花糖', '白色', 'SX', '01', '60*40', '11111111-1111-1111-1111-111111111101', 10000, 6500, 100, 10, 'producing', '2026-01-15T00:00:00Z', 'a0000001-0000-0000-0000-000000000001'),
|
||||
('33333333-3333-3333-3333-333333333302', 'PLAN-2026-002', '纯棉汗布', '黑色', 'CM', '02', '60双股', '11111111-1111-1111-1111-111111111101', 8000, 0, 120, 12, 'pending', NULL, 'a0000001-0000-0000-0000-000000000001'),
|
||||
('33333333-3333-3333-3333-333333333303', 'PLAN-2026-003', '磨毛布', '灰色', 'MM', '03', '40*40', '11111111-1111-1111-1111-111111111101', 5000, 5000, 80, 8, 'completed', '2026-01-01T00:00:00Z', 'a0000001-0000-0000-0000-000000000001');
|
||||
|
||||
-- 创建计划与工厂关联
|
||||
INSERT INTO public.plan_factories (plan_id, factory_id, factory_type) VALUES
|
||||
('33333333-3333-3333-3333-333333333301', '11111111-1111-1111-1111-111111111102', 'textile'),
|
||||
('33333333-3333-3333-3333-333333333302', '11111111-1111-1111-1111-111111111102', 'textile'),
|
||||
('33333333-3333-3333-3333-333333333303', '11111111-1111-1111-1111-111111111102', 'textile');
|
||||
|
||||
-- 创建纱线配比
|
||||
INSERT INTO public.yarn_ratios (plan_id, yarn_name, ratio, amount_per_meter, total_amount) VALUES
|
||||
('33333333-3333-3333-3333-333333333301', '棉纱32S', 1, 10, 100000),
|
||||
('33333333-3333-3333-3333-333333333301', '涤纶纱', 1, 10, 100000),
|
||||
('33333333-3333-3333-3333-333333333301', '氨纶', 8, 80, 800000);
|
||||
|
||||
-- 创建流程节点
|
||||
INSERT INTO public.plan_process_steps (plan_id, step_type, status, timestamp, operator_id) VALUES
|
||||
('33333333-3333-3333-3333-333333333301', 'confirm', 'completed', '2026-01-15T09:30:00Z', 'a0000001-0000-0000-0000-000000000001'),
|
||||
('33333333-3333-3333-3333-333333333301', 'yarn_purchase', 'completed', '2026-01-16T14:20:00Z', 'a0000002-0000-0000-0000-000000000002'),
|
||||
('33333333-3333-3333-3333-333333333301', 'dyeing', 'completed', '2026-01-18T10:00:00Z', 'a0000002-0000-0000-0000-000000000002'),
|
||||
('33333333-3333-3333-3333-333333333301', 'machine_start', 'active', '2026-01-20T08:00:00Z', 'a0000002-0000-0000-0000-000000000002'),
|
||||
('33333333-3333-3333-3333-333333333301', 'fabric_warehouse', 'pending', NULL, NULL);
|
||||
|
||||
-- 创建结款记录
|
||||
INSERT INTO public.payments (plan_id, from_company_id, to_company_id, amount, quantity, price_per_meter, status) VALUES
|
||||
('33333333-3333-3333-3333-333333333301', '11111111-1111-1111-1111-111111111101', '11111111-1111-1111-1111-111111111102', 65000, 6500, 10, 'pending'),
|
||||
('33333333-3333-3333-3333-333333333303', '11111111-1111-1111-1111-111111111101', '11111111-1111-1111-1111-111111111102', 50000, 5000, 10, 'pending');
|
||||
|
||||
14
migrations/20260523_124703_add_company_id_to_inventory.sql
Normal file
14
migrations/20260523_124703_add_company_id_to_inventory.sql
Normal file
@ -0,0 +1,14 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
ALTER TABLE product_inventory_records ADD COLUMN company_id UUID REFERENCES companies(id) ON DELETE CASCADE;
|
||||
|
||||
-- 更新RLS策略
|
||||
CREATE POLICY company_select_product_inventory_records ON product_inventory_records FOR SELECT USING (true);
|
||||
CREATE POLICY company_insert_product_inventory_records ON product_inventory_records FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY company_update_product_inventory_records ON product_inventory_records FOR UPDATE USING (true);
|
||||
CREATE POLICY company_delete_product_inventory_records ON product_inventory_records FOR DELETE USING (true);
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 创建产品纱线配比表
|
||||
CREATE TABLE IF NOT EXISTS product_yarn_ratios (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
product_id UUID NOT NULL REFERENCES products(id) ON DELETE CASCADE,
|
||||
yarn_name TEXT NOT NULL,
|
||||
ratio DECIMAL(5,2) NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- 启用RLS
|
||||
ALTER TABLE product_yarn_ratios ENABLE ROW LEVEL SECURITY;
|
||||
|
||||
-- RLS策略
|
||||
CREATE POLICY company_select_product_yarn_ratios ON product_yarn_ratios FOR SELECT USING (true);
|
||||
CREATE POLICY company_insert_product_yarn_ratios ON product_yarn_ratios FOR INSERT WITH CHECK (true);
|
||||
CREATE POLICY company_update_product_yarn_ratios ON product_yarn_ratios FOR UPDATE USING (true);
|
||||
CREATE POLICY company_delete_product_yarn_ratios ON product_yarn_ratios FOR DELETE USING (true);
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
ALTER TABLE products ADD COLUMN IF NOT EXISTS production_price DECIMAL(10,2) DEFAULT 0;
|
||||
@ -0,0 +1,6 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
ALTER TABLE inventory_records ADD COLUMN IF NOT EXISTS rolls INTEGER DEFAULT 0;
|
||||
40
migrations/20260523_162407_drop_old_rls_policies.sql
Normal file
40
migrations/20260523_162407_drop_old_rls_policies.sql
Normal file
@ -0,0 +1,40 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 删除现有宽松的 RLS 策略
|
||||
DROP POLICY IF EXISTS anon_select_companies ON public.companies;
|
||||
DROP POLICY IF EXISTS anon_insert_companies ON public.companies;
|
||||
DROP POLICY IF EXISTS anon_update_companies ON public.companies;
|
||||
DROP POLICY IF EXISTS anon_select_profiles ON public.profiles;
|
||||
DROP POLICY IF EXISTS anon_insert_profiles ON public.profiles;
|
||||
DROP POLICY IF EXISTS users_update_own_profile ON public.profiles;
|
||||
DROP POLICY IF EXISTS anon_select_company_members ON public.company_members;
|
||||
DROP POLICY IF EXISTS anon_insert_company_members ON public.company_members;
|
||||
DROP POLICY IF EXISTS anon_select_plans ON public.production_plans;
|
||||
DROP POLICY IF EXISTS anon_insert_plans ON public.production_plans;
|
||||
DROP POLICY IF EXISTS anon_update_plans ON public.production_plans;
|
||||
DROP POLICY IF EXISTS anon_delete_plans ON public.production_plans;
|
||||
DROP POLICY IF EXISTS anon_select_plan_factories ON public.plan_factories;
|
||||
DROP POLICY IF EXISTS anon_insert_plan_factories ON public.plan_factories;
|
||||
DROP POLICY IF EXISTS anon_delete_plan_factories ON public.plan_factories;
|
||||
DROP POLICY IF EXISTS anon_select_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS anon_insert_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS anon_delete_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS anon_select_warehouses ON public.warehouses;
|
||||
DROP POLICY IF EXISTS anon_insert_warehouses ON public.warehouses;
|
||||
DROP POLICY IF EXISTS anon_update_warehouses ON public.warehouses;
|
||||
DROP POLICY IF EXISTS anon_select_inventory ON public.inventory_records;
|
||||
DROP POLICY IF EXISTS anon_insert_inventory ON public.inventory_records;
|
||||
DROP POLICY IF EXISTS anon_select_yarn_stock ON public.yarn_stock;
|
||||
DROP POLICY IF EXISTS anon_insert_yarn_stock ON public.yarn_stock;
|
||||
DROP POLICY IF EXISTS anon_update_yarn_stock ON public.yarn_stock;
|
||||
DROP POLICY IF EXISTS anon_select_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS anon_insert_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS anon_update_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS anon_select_payments ON public.payments;
|
||||
DROP POLICY IF EXISTS anon_insert_payments ON public.payments;
|
||||
DROP POLICY IF EXISTS anon_update_payments ON public.payments;
|
||||
|
||||
23
migrations/20260523_162428_create_helper_function_1.sql
Normal file
23
migrations/20260523_162428_create_helper_function_1.sql
Normal file
@ -0,0 +1,23 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 创建辅助函数:获取当前用户的公司ID
|
||||
CREATE OR REPLACE FUNCTION public.get_current_user_company_id()
|
||||
RETURNS UUID
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = public
|
||||
AS $$
|
||||
DECLARE
|
||||
company_id UUID;
|
||||
BEGIN
|
||||
SELECT p.company_id INTO company_id
|
||||
FROM public.profiles p
|
||||
WHERE p.id = auth.uid();
|
||||
RETURN company_id;
|
||||
END;
|
||||
$$;
|
||||
|
||||
32
migrations/20260523_162436_create_helper_function_2.sql
Normal file
32
migrations/20260523_162436_create_helper_function_2.sql
Normal file
@ -0,0 +1,32 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 创建辅助函数:获取用户主账号公司ID(用于子账号)
|
||||
CREATE OR REPLACE FUNCTION public.get_user_master_company_id()
|
||||
RETURNS UUID
|
||||
LANGUAGE plpgsql
|
||||
SECURITY DEFINER
|
||||
SET search_path = public
|
||||
AS $$
|
||||
DECLARE
|
||||
user_company_id UUID;
|
||||
user_master_id UUID;
|
||||
BEGIN
|
||||
SELECT company_id, master_id INTO user_company_id, user_master_id
|
||||
FROM public.profiles
|
||||
WHERE id = auth.uid();
|
||||
|
||||
-- 如果是子账号,返回主账号的公司ID
|
||||
IF user_master_id IS NOT NULL THEN
|
||||
SELECT company_id INTO user_company_id
|
||||
FROM public.profiles
|
||||
WHERE id = user_master_id;
|
||||
END IF;
|
||||
|
||||
RETURN user_company_id;
|
||||
END;
|
||||
$$;
|
||||
|
||||
22
migrations/20260523_162443_create_companies_rls.sql
Normal file
22
migrations/20260523_162443_create_companies_rls.sql
Normal file
@ -0,0 +1,22 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- companies 表 RLS 策略
|
||||
-- 用户只能查看、修改自己公司的数据
|
||||
CREATE POLICY users_select_own_company ON public.companies
|
||||
FOR SELECT USING (
|
||||
id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_own_company ON public.companies
|
||||
FOR UPDATE USING (
|
||||
id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- 允许创建公司(注册时需要)
|
||||
CREATE POLICY users_insert_company ON public.companies
|
||||
FOR INSERT WITH CHECK (true);
|
||||
|
||||
24
migrations/20260523_162456_create_profiles_rls.sql
Normal file
24
migrations/20260523_162456_create_profiles_rls.sql
Normal file
@ -0,0 +1,24 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- profiles 表 RLS 策略
|
||||
-- 用户可以查看自己公司的所有成员资料
|
||||
CREATE POLICY users_select_company_profiles ON public.profiles
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
OR id = auth.uid()
|
||||
);
|
||||
|
||||
-- 用户可以修改自己的资料
|
||||
CREATE POLICY users_update_own_profile ON public.profiles
|
||||
FOR UPDATE USING (
|
||||
id = auth.uid()
|
||||
);
|
||||
|
||||
-- 允许创建 profile(注册时需要)
|
||||
CREATE POLICY users_insert_profile ON public.profiles
|
||||
FOR INSERT WITH CHECK (true);
|
||||
|
||||
31
migrations/20260523_162514_create_production_plans_rls.sql
Normal file
31
migrations/20260523_162514_create_production_plans_rls.sql
Normal file
@ -0,0 +1,31 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- production_plans 表 RLS 策略
|
||||
-- 采购商可以查看、修改、删除自己创建的计划
|
||||
CREATE POLICY purchaser_select_plans ON public.production_plans
|
||||
FOR SELECT USING (
|
||||
purchaser_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY purchaser_insert_plans ON public.production_plans
|
||||
FOR INSERT WITH CHECK (
|
||||
purchaser_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY purchaser_update_plans ON public.production_plans
|
||||
FOR UPDATE USING (
|
||||
purchaser_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY purchaser_delete_plans ON public.production_plans
|
||||
FOR DELETE USING (
|
||||
purchaser_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- 工厂可以查看关联的计划(通过 plan_factories 关联)
|
||||
-- 这个策略需要配合 plan_factories 的查询
|
||||
|
||||
39
migrations/20260523_162530_create_plan_factories_rls.sql
Normal file
39
migrations/20260523_162530_create_plan_factories_rls.sql
Normal file
@ -0,0 +1,39 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- plan_factories 表 RLS 策略
|
||||
-- 工厂可以查看和管理关联到自己的计划
|
||||
CREATE POLICY factory_select_plan_factories ON public.plan_factories
|
||||
FOR SELECT USING (
|
||||
factory_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- 采购商可以查看自己计划的工厂关联
|
||||
CREATE POLICY purchaser_select_plan_factories ON public.plan_factories
|
||||
FOR SELECT USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
-- 采购商可以创建和删除工厂关联
|
||||
CREATE POLICY purchaser_insert_plan_factories ON public.plan_factories
|
||||
FOR INSERT WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY purchaser_delete_plan_factories ON public.plan_factories
|
||||
FOR DELETE USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
@ -0,0 +1,45 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- warehouses 表 RLS 策略
|
||||
CREATE POLICY users_select_company_warehouses ON public.warehouses
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_company_warehouses ON public.warehouses
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_company_warehouses ON public.warehouses
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_company_warehouses ON public.warehouses
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- inventory_records 表 RLS 策略
|
||||
-- 通过 warehouse 关联到公司
|
||||
CREATE POLICY users_select_company_inventory ON public.inventory_records
|
||||
FOR SELECT USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.warehouses
|
||||
WHERE id = warehouse_id AND company_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_company_inventory ON public.inventory_records
|
||||
FOR INSERT WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.warehouses
|
||||
WHERE id = warehouse_id AND company_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
53
migrations/20260523_162604_create_yarn_rls.sql
Normal file
53
migrations/20260523_162604_create_yarn_rls.sql
Normal file
@ -0,0 +1,53 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- yarn_stock 表 RLS 策略
|
||||
CREATE POLICY users_select_company_yarn_stock ON public.yarn_stock
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_company_yarn_stock ON public.yarn_stock
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_company_yarn_stock ON public.yarn_stock
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_company_yarn_stock ON public.yarn_stock
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- yarn_ratios 表 RLS 策略
|
||||
-- 通过 plan 关联到采购商
|
||||
CREATE POLICY users_select_yarn_ratios ON public.yarn_ratios
|
||||
FOR SELECT USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_yarn_ratios ON public.yarn_ratios
|
||||
FOR INSERT WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_yarn_ratios ON public.yarn_ratios
|
||||
FOR DELETE USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
77
migrations/20260523_162626_create_payments_process_rls.sql
Normal file
77
migrations/20260523_162626_create_payments_process_rls.sql
Normal file
@ -0,0 +1,77 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- payments 表 RLS 策略
|
||||
-- 付款方或收款方可以查看相关结款记录
|
||||
CREATE POLICY users_select_payments ON public.payments
|
||||
FOR SELECT USING (
|
||||
from_company_id = public.get_user_master_company_id()
|
||||
OR to_company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_payments ON public.payments
|
||||
FOR INSERT WITH CHECK (
|
||||
from_company_id = public.get_user_master_company_id()
|
||||
OR to_company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_payments ON public.payments
|
||||
FOR UPDATE USING (
|
||||
from_company_id = public.get_user_master_company_id()
|
||||
OR to_company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- plan_process_steps 表 RLS 策略
|
||||
-- 关联计划的采购商或工厂可以查看流程步骤
|
||||
CREATE POLICY users_select_process_steps ON public.plan_process_steps
|
||||
FOR SELECT USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans p
|
||||
JOIN public.plan_factories pf ON p.id = pf.plan_id
|
||||
WHERE p.id = plan_id
|
||||
AND (p.purchaser_id = public.get_user_master_company_id()
|
||||
OR pf.factory_id = public.get_user_master_company_id())
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_process_steps ON public.plan_process_steps
|
||||
FOR INSERT WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans p
|
||||
JOIN public.plan_factories pf ON p.id = pf.plan_id
|
||||
WHERE p.id = plan_id
|
||||
AND (p.purchaser_id = public.get_user_master_company_id()
|
||||
OR pf.factory_id = public.get_user_master_company_id())
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_process_steps ON public.plan_process_steps
|
||||
FOR UPDATE USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans p
|
||||
JOIN public.plan_factories pf ON p.id = pf.plan_id
|
||||
WHERE p.id = plan_id
|
||||
AND (p.purchaser_id = public.get_user_master_company_id()
|
||||
OR pf.factory_id = public.get_user_master_company_id())
|
||||
)
|
||||
);
|
||||
|
||||
-- company_members 表 RLS 策略
|
||||
CREATE POLICY users_select_company_members ON public.company_members
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_company_members ON public.company_members
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_company_members ON public.company_members
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
28
migrations/20260523_162653_drop_remaining_old_policies.sql
Normal file
28
migrations/20260523_162653_drop_remaining_old_policies.sql
Normal file
@ -0,0 +1,28 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 删除 products 表上的旧宽松策略
|
||||
DROP POLICY IF EXISTS anon_select_products ON public.products;
|
||||
DROP POLICY IF EXISTS anon_insert_products ON public.products;
|
||||
DROP POLICY IF EXISTS anon_update_products ON public.products;
|
||||
DROP POLICY IF EXISTS anon_delete_products ON public.products;
|
||||
|
||||
-- 删除 product_inventory_records 表上的旧宽松策略
|
||||
DROP POLICY IF EXISTS anon_select_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS anon_insert_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS anon_update_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS anon_delete_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS company_select_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS company_insert_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS company_update_product_inventory_records ON public.product_inventory_records;
|
||||
DROP POLICY IF EXISTS company_delete_product_inventory_records ON public.product_inventory_records;
|
||||
|
||||
-- 删除 product_yarn_ratios 表上的旧宽松策略
|
||||
DROP POLICY IF EXISTS company_select_product_yarn_ratios ON public.product_yarn_ratios;
|
||||
DROP POLICY IF EXISTS company_insert_product_yarn_ratios ON public.product_yarn_ratios;
|
||||
DROP POLICY IF EXISTS company_update_product_yarn_ratios ON public.product_yarn_ratios;
|
||||
DROP POLICY IF EXISTS company_delete_product_yarn_ratios ON public.product_yarn_ratios;
|
||||
|
||||
22
migrations/20260523_162700_fix_profiles_rls.sql
Normal file
22
migrations/20260523_162700_fix_profiles_rls.sql
Normal file
@ -0,0 +1,22 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 修复 profiles 策略中的 uid() 为 auth.uid()
|
||||
DROP POLICY IF EXISTS users_select_company_profiles ON public.profiles;
|
||||
DROP POLICY IF EXISTS users_update_own_profile ON public.profiles;
|
||||
|
||||
-- 重新创建正确的策略
|
||||
CREATE POLICY users_select_company_profiles ON public.profiles
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
OR id = auth.uid()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_own_profile ON public.profiles
|
||||
FOR UPDATE USING (
|
||||
id = auth.uid()
|
||||
);
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 为 inventory_records 表添加 company_id 字段
|
||||
ALTER TABLE public.inventory_records ADD COLUMN IF NOT EXISTS company_id UUID REFERENCES public.companies(id) ON DELETE CASCADE;
|
||||
|
||||
-- 创建索引优化查询
|
||||
CREATE INDEX IF NOT EXISTS idx_inventory_records_company_id ON public.inventory_records(company_id);
|
||||
|
||||
12
migrations/20260523_162846_add_company_id_to_yarn_ratios.sql
Normal file
12
migrations/20260523_162846_add_company_id_to_yarn_ratios.sql
Normal file
@ -0,0 +1,12 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 为 yarn_ratios 表添加 company_id 字段
|
||||
ALTER TABLE public.yarn_ratios ADD COLUMN IF NOT EXISTS company_id UUID REFERENCES public.companies(id) ON DELETE CASCADE;
|
||||
|
||||
-- 创建索引优化查询
|
||||
CREATE INDEX IF NOT EXISTS idx_yarn_ratios_company_id ON public.yarn_ratios(company_id);
|
||||
|
||||
@ -0,0 +1,12 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 为 plan_process_steps 表添加 company_id 字段
|
||||
ALTER TABLE public.plan_process_steps ADD COLUMN IF NOT EXISTS company_id UUID REFERENCES public.companies(id) ON DELETE CASCADE;
|
||||
|
||||
-- 创建索引优化查询
|
||||
CREATE INDEX IF NOT EXISTS idx_plan_process_steps_company_id ON public.plan_process_steps(company_id);
|
||||
|
||||
31
migrations/20260523_162913_update_inventory_records_rls.sql
Normal file
31
migrations/20260523_162913_update_inventory_records_rls.sql
Normal file
@ -0,0 +1,31 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 删除旧的 RLS 策略
|
||||
DROP POLICY IF EXISTS users_select_company_inventory ON public.inventory_records;
|
||||
DROP POLICY IF EXISTS users_insert_company_inventory ON public.inventory_records;
|
||||
|
||||
-- 创建优化的 RLS 策略(直接使用 company_id)
|
||||
CREATE POLICY users_select_company_inventory ON public.inventory_records
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_company_inventory ON public.inventory_records
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_company_inventory ON public.inventory_records
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_company_inventory ON public.inventory_records
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
32
migrations/20260523_162926_update_yarn_ratios_rls.sql
Normal file
32
migrations/20260523_162926_update_yarn_ratios_rls.sql
Normal file
@ -0,0 +1,32 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 删除旧的 RLS 策略
|
||||
DROP POLICY IF EXISTS users_select_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS users_insert_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS users_delete_yarn_ratios ON public.yarn_ratios;
|
||||
|
||||
-- 创建优化的 RLS 策略(直接使用 company_id)
|
||||
CREATE POLICY users_select_yarn_ratios ON public.yarn_ratios
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_yarn_ratios ON public.yarn_ratios
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_yarn_ratios ON public.yarn_ratios
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_yarn_ratios ON public.yarn_ratios
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
32
migrations/20260523_162941_update_plan_process_steps_rls.sql
Normal file
32
migrations/20260523_162941_update_plan_process_steps_rls.sql
Normal file
@ -0,0 +1,32 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 删除旧的 RLS 策略
|
||||
DROP POLICY IF EXISTS users_select_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS users_insert_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS users_update_process_steps ON public.plan_process_steps;
|
||||
|
||||
-- 创建优化的 RLS 策略(直接使用 company_id)
|
||||
CREATE POLICY users_select_process_steps ON public.plan_process_steps
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_insert_process_steps ON public.plan_process_steps
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_process_steps ON public.plan_process_steps
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_process_steps ON public.plan_process_steps
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
27
migrations/20260523_163000_sync_company_id_data.sql
Normal file
27
migrations/20260523_163000_sync_company_id_data.sql
Normal file
@ -0,0 +1,27 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 更新 inventory_records 的 company_id(通过 warehouse 关联)
|
||||
UPDATE public.inventory_records ir
|
||||
SET company_id = w.company_id
|
||||
FROM public.warehouses w
|
||||
WHERE ir.warehouse_id = w.id
|
||||
AND ir.company_id IS NULL;
|
||||
|
||||
-- 更新 yarn_ratios 的 company_id(通过 production_plans 关联)
|
||||
UPDATE public.yarn_ratios yr
|
||||
SET company_id = pp.purchaser_id
|
||||
FROM public.production_plans pp
|
||||
WHERE yr.plan_id = pp.id
|
||||
AND yr.company_id IS NULL;
|
||||
|
||||
-- 更新 plan_process_steps 的 company_id(通过 production_plans 关联)
|
||||
UPDATE public.plan_process_steps pps
|
||||
SET company_id = pp.purchaser_id
|
||||
FROM public.production_plans pp
|
||||
WHERE pps.plan_id = pp.id
|
||||
AND pps.company_id IS NULL;
|
||||
|
||||
37
migrations/20260523_163054_add_share_link_rls_policies.sql
Normal file
37
migrations/20260523_163054_add_share_link_rls_policies.sql
Normal file
@ -0,0 +1,37 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 为分享链接场景添加特殊的 RLS 策略
|
||||
-- 允许工厂查看通过 plan_factories 关联的计划
|
||||
|
||||
-- production_plans:工厂可以查看关联的计划
|
||||
CREATE POLICY factory_select_plans_via_share ON public.production_plans
|
||||
FOR SELECT USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.plan_factories
|
||||
WHERE plan_id = production_plans.id
|
||||
AND factory_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
-- yarn_ratios:工厂可以查看关联计划的纱线配比
|
||||
CREATE POLICY factory_select_yarn_ratios_via_share ON public.yarn_ratios
|
||||
FOR SELECT USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.plan_factories
|
||||
WHERE plan_id = yarn_ratios.plan_id
|
||||
AND factory_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
-- companies:允许查看所有公司(用于显示采购商名称)
|
||||
-- 删除旧的限制策略,创建新的开放查询策略
|
||||
DROP POLICY IF EXISTS users_select_own_company ON public.companies;
|
||||
|
||||
-- 允许所有登录用户查看所有公司信息(用于分享链接显示采购商名称)
|
||||
CREATE POLICY users_select_companies ON public.companies
|
||||
FOR SELECT USING (true);
|
||||
|
||||
41
migrations/20260523_163116_fix_share_link_rls_v2.sql
Normal file
41
migrations/20260523_163116_fix_share_link_rls_v2.sql
Normal file
@ -0,0 +1,41 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 删除刚才创建的策略(有问题)
|
||||
DROP POLICY IF EXISTS factory_select_plans_via_share ON public.production_plans;
|
||||
DROP POLICY IF EXISTS factory_select_yarn_ratios_via_share ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS users_select_yarn_ratios ON public.yarn_ratios;
|
||||
|
||||
-- 重新创建策略:允许所有登录用户查看计划(但只能看到分享链接中展示的非敏感字段)
|
||||
-- 实际敏感信息控制由前端完成
|
||||
DROP POLICY IF EXISTS purchaser_select_plans ON public.production_plans;
|
||||
CREATE POLICY users_select_plans ON public.production_plans
|
||||
FOR SELECT USING (true);
|
||||
|
||||
-- yarn_ratios:允许查看(配合计划查看)
|
||||
DROP POLICY IF EXISTS users_select_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS users_insert_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS users_update_yarn_ratios ON public.yarn_ratios;
|
||||
DROP POLICY IF EXISTS users_delete_yarn_ratios ON public.yarn_ratios;
|
||||
|
||||
CREATE POLICY users_select_yarn_ratios ON public.yarn_ratios
|
||||
FOR SELECT USING (true);
|
||||
|
||||
CREATE POLICY users_insert_yarn_ratios ON public.yarn_ratios
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_yarn_ratios ON public.yarn_ratios
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_yarn_ratios ON public.yarn_ratios
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
52
migrations/20260523_163245_add_missing_rls_policies.sql
Normal file
52
migrations/20260523_163245_add_missing_rls_policies.sql
Normal file
@ -0,0 +1,52 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 为 products 表添加 RLS 策略
|
||||
-- 允许查看(用于仓库同步),但只允许公司自己管理
|
||||
CREATE POLICY users_select_products ON public.products
|
||||
FOR SELECT USING (true);
|
||||
|
||||
CREATE POLICY users_insert_products ON public.products
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_products ON public.products
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_products ON public.products
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- 为 product_inventory_records 表添加 RLS 策略
|
||||
CREATE POLICY users_select_product_inventory ON public.product_inventory_records
|
||||
FOR SELECT USING (true);
|
||||
|
||||
CREATE POLICY users_insert_product_inventory ON public.product_inventory_records
|
||||
FOR INSERT WITH CHECK (true);
|
||||
|
||||
CREATE POLICY users_update_product_inventory ON public.product_inventory_records
|
||||
FOR UPDATE USING (true);
|
||||
|
||||
CREATE POLICY users_delete_product_inventory ON public.product_inventory_records
|
||||
FOR DELETE USING (true);
|
||||
|
||||
-- 为 product_yarn_ratios 表添加 RLS 策略
|
||||
CREATE POLICY users_select_product_yarn_ratios ON public.product_yarn_ratios
|
||||
FOR SELECT USING (true);
|
||||
|
||||
CREATE POLICY users_insert_product_yarn_ratios ON public.product_yarn_ratios
|
||||
FOR INSERT WITH CHECK (true);
|
||||
|
||||
CREATE POLICY users_update_product_yarn_ratios ON public.product_yarn_ratios
|
||||
FOR UPDATE USING (true);
|
||||
|
||||
CREATE POLICY users_delete_product_yarn_ratios ON public.product_yarn_ratios
|
||||
FOR DELETE USING (true);
|
||||
|
||||
32
migrations/20260523_163255_fix_inventory_records_rls.sql
Normal file
32
migrations/20260523_163255_fix_inventory_records_rls.sql
Normal file
@ -0,0 +1,32 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 修复 inventory_records 的 RLS 策略
|
||||
-- 删除旧的策略
|
||||
DROP POLICY IF EXISTS users_select_company_inventory ON public.inventory_records;
|
||||
DROP POLICY IF EXISTS users_insert_company_inventory ON public.inventory_records;
|
||||
DROP POLICY IF EXISTS users_update_company_inventory ON public.inventory_records;
|
||||
DROP POLICY IF EXISTS users_delete_company_inventory ON public.inventory_records;
|
||||
|
||||
-- 创建新的策略:允许查看(用于仓库同步),但只允许公司自己管理
|
||||
CREATE POLICY users_select_inventory ON public.inventory_records
|
||||
FOR SELECT USING (true);
|
||||
|
||||
CREATE POLICY users_insert_inventory ON public.inventory_records
|
||||
FOR INSERT WITH CHECK (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_update_inventory ON public.inventory_records
|
||||
FOR UPDATE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_inventory ON public.inventory_records
|
||||
FOR DELETE USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
34
migrations/20260523_163429_fix_plan_factories_rls.sql
Normal file
34
migrations/20260523_163429_fix_plan_factories_rls.sql
Normal file
@ -0,0 +1,34 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 修复 plan_factories 的 RLS 策略
|
||||
-- 删除旧的策略
|
||||
DROP POLICY IF EXISTS factory_select_plan_factories ON public.plan_factories;
|
||||
DROP POLICY IF EXISTS purchaser_select_plan_factories ON public.plan_factories;
|
||||
DROP POLICY IF EXISTS purchaser_insert_plan_factories ON public.plan_factories;
|
||||
DROP POLICY IF EXISTS purchaser_delete_plan_factories ON public.plan_factories;
|
||||
|
||||
-- 创建新的策略:允许查看(用于仓库同步和分享链接)
|
||||
CREATE POLICY users_select_plan_factories ON public.plan_factories
|
||||
FOR SELECT USING (true);
|
||||
|
||||
-- 插入和删除保持严格限制
|
||||
CREATE POLICY users_insert_plan_factories ON public.plan_factories
|
||||
FOR INSERT WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
CREATE POLICY users_delete_plan_factories ON public.plan_factories
|
||||
FOR DELETE USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_id AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
51
migrations/20260523_163537_fix_plan_process_steps_rls.sql
Normal file
51
migrations/20260523_163537_fix_plan_process_steps_rls.sql
Normal file
@ -0,0 +1,51 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 修复 plan_process_steps 的 RLS 策略
|
||||
-- 删除旧的策略
|
||||
DROP POLICY IF EXISTS users_select_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS users_insert_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS users_update_process_steps ON public.plan_process_steps;
|
||||
DROP POLICY IF EXISTS users_delete_process_steps ON public.plan_process_steps;
|
||||
|
||||
-- 创建新的策略:允许查看(用于流程跟踪)
|
||||
CREATE POLICY users_select_process_steps ON public.plan_process_steps
|
||||
FOR SELECT USING (true);
|
||||
|
||||
-- 插入:允许关联计划的采购商或工厂
|
||||
CREATE POLICY users_insert_process_steps ON public.plan_process_steps
|
||||
FOR INSERT WITH CHECK (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans p
|
||||
LEFT JOIN public.plan_factories pf ON p.id = pf.plan_id
|
||||
WHERE p.id = plan_process_steps.plan_id
|
||||
AND (p.purchaser_id = public.get_user_master_company_id()
|
||||
OR pf.factory_id = public.get_user_master_company_id())
|
||||
)
|
||||
);
|
||||
|
||||
-- 更新:允许关联计划的采购商或工厂
|
||||
CREATE POLICY users_update_process_steps ON public.plan_process_steps
|
||||
FOR UPDATE USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans p
|
||||
LEFT JOIN public.plan_factories pf ON p.id = pf.plan_id
|
||||
WHERE p.id = plan_process_steps.plan_id
|
||||
AND (p.purchaser_id = public.get_user_master_company_id()
|
||||
OR pf.factory_id = public.get_user_master_company_id())
|
||||
)
|
||||
);
|
||||
|
||||
-- 删除:只允许采购商
|
||||
CREATE POLICY users_delete_process_steps ON public.plan_process_steps
|
||||
FOR DELETE USING (
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans
|
||||
WHERE id = plan_process_steps.plan_id
|
||||
AND purchaser_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
50
migrations/20260523_163644_fix_select_policies_security.sql
Normal file
50
migrations/20260523_163644_fix_select_policies_security.sql
Normal file
@ -0,0 +1,50 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 修复高风险表的 SELECT 策略
|
||||
|
||||
-- 1. production_plans: 只允许采购商查看自己的计划,工厂查看关联的计划
|
||||
DROP POLICY IF EXISTS users_select_plans ON public.production_plans;
|
||||
|
||||
CREATE POLICY users_select_plans ON public.production_plans
|
||||
FOR SELECT USING (
|
||||
-- 采购商可以查看自己的计划
|
||||
purchaser_id = public.get_user_master_company_id()
|
||||
OR
|
||||
-- 工厂可以查看关联的计划
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.plan_factories
|
||||
WHERE plan_id = production_plans.id
|
||||
AND factory_id = public.get_user_master_company_id()
|
||||
)
|
||||
);
|
||||
|
||||
-- 2. products: 只允许公司自己查看(产品管理)
|
||||
DROP POLICY IF EXISTS users_select_products ON public.products;
|
||||
|
||||
CREATE POLICY users_select_products ON public.products
|
||||
FOR SELECT USING (
|
||||
company_id = public.get_user_master_company_id()
|
||||
);
|
||||
|
||||
-- 3. inventory_records: 只允许相关方查看
|
||||
DROP POLICY IF EXISTS users_select_inventory ON public.inventory_records;
|
||||
|
||||
CREATE POLICY users_select_inventory ON public.inventory_records
|
||||
FOR SELECT USING (
|
||||
-- 公司可以查看自己的入库记录
|
||||
company_id = public.get_user_master_company_id()
|
||||
OR
|
||||
-- 采购商可以查看关联计划的入库记录
|
||||
EXISTS (
|
||||
SELECT 1 FROM public.production_plans p
|
||||
JOIN public.plan_factories pf ON p.id = pf.plan_id
|
||||
WHERE p.id = inventory_records.plan_id
|
||||
AND (p.purchaser_id = public.get_user_master_company_id()
|
||||
OR pf.factory_id = public.get_user_master_company_id())
|
||||
)
|
||||
);
|
||||
|
||||
@ -0,0 +1,17 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 1. 删除 PLAN-2026-820523 的重复工厂关联,只保留示例纺织厂
|
||||
DELETE FROM plan_factories
|
||||
WHERE plan_id = '7b0d76c2-0bf3-4a58-8607-4dfa850cf416'
|
||||
AND factory_id = '2da8c512-6076-44e1-8f37-def2298b5847';
|
||||
|
||||
-- 2. 检查是否还有其他重复关联
|
||||
SELECT plan_id, factory_type, COUNT(*)
|
||||
FROM plan_factories
|
||||
GROUP BY plan_id, factory_type
|
||||
HAVING COUNT(*) > 1;
|
||||
|
||||
@ -0,0 +1,15 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
|
||||
-- 添加唯一约束:一个计划的同类型工厂只能关联一个
|
||||
-- 先删除可能存在的旧约束
|
||||
ALTER TABLE plan_factories DROP CONSTRAINT IF EXISTS unique_plan_factory_type;
|
||||
|
||||
-- 添加新的唯一约束
|
||||
ALTER TABLE plan_factories
|
||||
ADD CONSTRAINT unique_plan_factory_type
|
||||
UNIQUE (plan_id, factory_type);
|
||||
|
||||
6
migrations/20260523_165555_create_audit_logs_table.sql
Normal file
6
migrations/20260523_165555_create_audit_logs_table.sql
Normal file
@ -0,0 +1,6 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS public.audit_logs (id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES auth.users(id) ON DELETE SET NULL, company_id UUID REFERENCES public.companies(id) ON DELETE SET NULL, action TEXT NOT NULL, resource_type TEXT NOT NULL, resource_id UUID, details JSONB, ip_address TEXT, user_agent TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()); CREATE INDEX idx_audit_logs_user_id ON public.audit_logs(user_id); CREATE INDEX idx_audit_logs_company_id ON public.audit_logs(company_id); CREATE INDEX idx_audit_logs_action ON public.audit_logs(action); CREATE INDEX idx_audit_logs_created_at ON public.audit_logs(created_at DESC); ALTER TABLE public.audit_logs ENABLE ROW LEVEL SECURITY; CREATE POLICY users_select_company_audit_logs ON public.audit_logs FOR SELECT USING (company_id = public.get_user_master_company_id()); CREATE POLICY users_insert_audit_logs ON public.audit_logs FOR INSERT WITH CHECK (true);
|
||||
6
migrations/20260523_165857_fix_inventory_insert_rls.sql
Normal file
6
migrations/20260523_165857_fix_inventory_insert_rls.sql
Normal file
@ -0,0 +1,6 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
DROP POLICY IF EXISTS users_insert_inventory ON public.inventory_records; CREATE POLICY users_insert_inventory ON public.inventory_records FOR INSERT WITH CHECK (EXISTS (SELECT 1 FROM public.warehouses WHERE id = warehouse_id AND company_id = public.get_user_master_company_id()));
|
||||
6
migrations/20260523_165900_fix_payments_insert_rls.sql
Normal file
6
migrations/20260523_165900_fix_payments_insert_rls.sql
Normal file
@ -0,0 +1,6 @@
|
||||
-- ============================================
|
||||
-- 此文件由 Meoo Cloud 自动生成,请勿修改
|
||||
-- This file is auto-generated by Meoo Cloud, DO NOT MODIFY
|
||||
-- ============================================
|
||||
|
||||
DROP POLICY IF EXISTS users_insert_payments ON public.payments; CREATE POLICY users_insert_payments ON public.payments FOR INSERT WITH CHECK (from_company_id = public.get_user_master_company_id() OR to_company_id = public.get_user_master_company_id());
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user