10 小时以前 db46314b9c56256a31c9114bd45d9bd63368cbd8
feat(crm): 实现CRM客户管理查看全部权限功能

- 新增场景类型枚举值"全部"(type=4),扩展客户查询功能
- 实现权限校验逻辑,支持crm:customer:view-all权限或crm_admin角色
- 添加权限降级机制,无权限用户自动切换为"我负责的"场景
- 更新数据库权限配置,新增view-all权限标识到客户公海菜单
- 完善前端文档说明,定义权限判断和Tab展示规则
- 修改MCP服务器端口配置,更新本地开发环境连接地址
已添加22个文件
已修改32个文件
1914 ■■■■■ 文件已修改
.mcp.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.mcp.json.tmp 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-40-35-404Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-42-11-724Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-42-36-804Z.yml 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-43-35-225Z.yml 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-47-24-223Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-47-38-983Z.yml 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-47-57-125Z.yml 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-51-00-932Z.yml 152 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-56-04-077Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T06-56-14-335Z.yml 122 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T07-10-45-745Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T07-12-31-548Z.yml 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T07-14-24-445Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T07-14-44-587Z.yml 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.playwright-mcp/page-2026-07-29T07-14-58-476Z.yml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/crm_customer_view_all.md 88 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/document_audit_project_filter_fix.md 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/machinery_new_fields_frontend.md 140 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/pro_archive_integration.md 154 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/pro_task_calculate_duration.md 81 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/mysql/mes_pd_menu_init.sql 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pd/documentaudit/vo/MesPdDocumentAuditPageReqVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryMapper.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pd/documentaudit/MesPdDocumentAuditMapper.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java 32 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pd/documentaudit/MesPdDocumentAuditServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/SrmBidAwardController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/SrmBidEvaluationController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/SrmTenderBidController.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/vo/SrmSupplierQuoteRespVO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/dal/mysql/SrmTenderBidMapper.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/supplier/SrmSupplierServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidEvaluationService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidEvaluationServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmTenderBidServiceImpl.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmTenderProjectServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.mcp.json
@@ -1,7 +1,7 @@
{
  "mcpServers": {
    "idea": {
      "url": "http://127.0.0.1:64342/stream",
      "url": "http://127.0.0.1:64417/stream",
      "type": "http"
    }
  }
.mcp.json.tmp
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,8 @@
{
  "mcpServers": {
    "idea": {
      "url": "http://127.0.0.1:64417/stream",
      "type": "http"
    }
  }
}
.playwright-mcp/page-2026-07-29T06-40-35-404Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
.playwright-mcp/page-2026-07-29T06-42-11-724Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
.playwright-mcp/page-2026-07-29T06-42-36-804Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,112 @@
- generic [ref=e7]:
  - complementary [ref=e8]:
    - generic [ref=e9]:
      - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=e15] [cursor=pointer]:
        - /url: javascript:void 0
        - img "工厂数字化MOM系统" [ref=e18]
        - generic [ref=e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
      - menu [ref=e22]:
        - listitem [ref=e23]:
          - generic [ref=e24] [cursor=pointer]: æ¦‚览
        - listitem [ref=e34]:
          - generic [ref=e35] [cursor=pointer]: åŸºç¡€æ•°æ®
        - listitem [ref=e43]:
          - generic [ref=e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
        - listitem [ref=e50]:
          - generic [ref=e51] [cursor=pointer]: è¥é”€ç®¡ç†
        - listitem [ref=e57]:
          - generic [ref=e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
        - listitem [ref=e65]:
          - generic [ref=e66] [cursor=pointer]: ä»“储物流
        - listitem [ref=e74]:
          - generic [ref=e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
        - listitem [ref=e82]:
          - generic [ref=e83] [cursor=pointer]: è´¨é‡ç®¡ç†
        - listitem [ref=e89]:
          - generic [ref=e90] [cursor=pointer]: ååŒåŠžå…¬
        - listitem [ref=e96]:
          - generic [ref=e97] [cursor=pointer]: äººåŠ›èµ„æº
        - listitem [ref=e103]:
          - generic [ref=e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
        - listitem [ref=e110]:
          - generic [ref=e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
        - listitem [ref=e117]:
          - generic [ref=e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
  - generic [ref=e131]:
    - generic [ref=e132]:
      - banner [ref=e133]:
        - button [ref=e134] [cursor=pointer]
        - button [ref=e137] [cursor=pointer]
        - navigation "breadcrumb" [ref=e142]:
          - list [ref=e143]:
            - listitem [ref=e144]:
              - link [ref=e145] [cursor=pointer]:
                - /url: javascript:void 0
              - listitem [ref=e152]
            - listitem [ref=e155]:
              - link "招标详情" [disabled] [ref=e156]
        - generic [ref=e159]:
          - generic [ref=e161] [cursor=pointer]:
            - generic [ref=e165]: æœç´¢
            - generic [ref=e166]: Ctrl K
          - button [ref=e168] [cursor=pointer]
          - button "dark" [ref=e173] [cursor=pointer]
          - button [ref=e182] [cursor=pointer]
          - button [ref=e188] [cursor=pointer]
          - button [ref=e191] [cursor=pointer]
          - button [ref=e197] [cursor=pointer]:
            - button [ref=e199]
          - button "工作台" [ref=e203] [cursor=pointer]
          - button "源码" [ref=e207] [cursor=pointer]
      - generic [ref=e214]:
        - generic [ref=e219]:
          - generic [ref=e220] [cursor=pointer]: åˆ†æžé¡µ
          - generic [ref=e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
        - button [ref=e254] [cursor=pointer]
    - main [ref=e272]:
      - generic [ref=e275]:
        - generic [ref=e276]:
          - button [ref=e277] [cursor=pointer]
          - generic [ref=e280]: æµ‹è¯•项目
          - generic [ref=e281]: æµ‹è¯•编号
          - generic [ref=e282]: è¯„标中
          - generic [ref=e283]: å…¬å¼€æ‹›æ ‡
          - button "刷新" [ref=e284] [cursor=pointer]
        - generic [ref=e290]:
          - generic:
            - generic "草稿"
            - generic "发布"
            - generic "投标中"
            - generic "评标中"
            - generic "已定标"
          - generic [ref=e291]:
            - generic [ref=e292]:
              - generic [ref=e293]: é¢„算金额
              - generic [ref=e294]: 15,000 å…ƒ
            - generic [ref=e295]:
              - generic [ref=e296]: è´Ÿè´£äºº
              - generic [ref=e297]: "-"
            - generic [ref=e298]:
              - generic [ref=e299]: é‡‡è´­ç»„织
              - generic [ref=e300]: "-"
            - generic [ref=e301]:
              - generic [ref=e302]: å¼€æ ‡æ—¶é—´
              - generic [ref=e303]: 2026-07-29 11:20:11
            - generic [ref=e304]:
              - generic [ref=e305]: å¼€å§‹æ—¶é—´
              - generic [ref=e306]: 2026-07-29 11:13:02
            - generic [ref=e307]:
              - generic [ref=e308]: æˆªæ­¢æ—¶é—´
              - generic [ref=e309]: 2026-07-29 19:13:06
        - generic [ref=e313]:
          - tablist [ref=e314]:
            - generic [ref=e316]:
              - tab [ref=e318] [cursor=pointer]
              - tab [ref=e323] [cursor=pointer]
              - tab [ref=e328] [cursor=pointer]
              - tab [ref=e333] [cursor=pointer]
              - tab [ref=e338] [cursor=pointer]
              - tab [active] [selected] [ref=e343] [cursor=pointer]
          - tabpanel "定标" [ref=e404]:
            - generic [ref=e405]:
              - generic "尚未定标"
.playwright-mcp/page-2026-07-29T06-43-35-225Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,112 @@
- generic [ref=e7]:
  - complementary [ref=e8]:
    - generic [ref=e9]:
      - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=e15] [cursor=pointer]:
        - /url: javascript:void 0
        - img "工厂数字化MOM系统" [ref=e18]
        - generic [ref=e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
      - menu [ref=e22]:
        - listitem [ref=e23]:
          - generic [ref=e24] [cursor=pointer]: æ¦‚览
        - listitem [ref=e34]:
          - generic [ref=e35] [cursor=pointer]: åŸºç¡€æ•°æ®
        - listitem [ref=e43]:
          - generic [ref=e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
        - listitem [ref=e50]:
          - generic [ref=e51] [cursor=pointer]: è¥é”€ç®¡ç†
        - listitem [ref=e57]:
          - generic [ref=e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
        - listitem [ref=e65]:
          - generic [ref=e66] [cursor=pointer]: ä»“储物流
        - listitem [ref=e74]:
          - generic [ref=e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
        - listitem [ref=e82]:
          - generic [ref=e83] [cursor=pointer]: è´¨é‡ç®¡ç†
        - listitem [ref=e89]:
          - generic [ref=e90] [cursor=pointer]: ååŒåŠžå…¬
        - listitem [ref=e96]:
          - generic [ref=e97] [cursor=pointer]: äººåŠ›èµ„æº
        - listitem [ref=e103]:
          - generic [ref=e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
        - listitem [ref=e110]:
          - generic [ref=e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
        - listitem [ref=e117]:
          - generic [ref=e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
  - generic [ref=e131]:
    - generic [ref=e132]:
      - banner [ref=e133]:
        - button [ref=e134] [cursor=pointer]
        - button [ref=e137] [cursor=pointer]
        - navigation "breadcrumb" [ref=e142]:
          - list [ref=e143]:
            - listitem [ref=e144]:
              - link [ref=e145] [cursor=pointer]:
                - /url: javascript:void 0
              - listitem [ref=e152]
            - listitem [ref=e155]:
              - link "招标详情" [disabled] [ref=e156]
        - generic [ref=e159]:
          - generic [ref=e161] [cursor=pointer]:
            - generic [ref=e165]: æœç´¢
            - generic [ref=e166]: Ctrl K
          - button [ref=e168] [cursor=pointer]
          - button "dark" [ref=e173] [cursor=pointer]
          - button [ref=e182] [cursor=pointer]
          - button [ref=e188] [cursor=pointer]
          - button [ref=e191] [cursor=pointer]
          - button [ref=e197] [cursor=pointer]:
            - button [ref=e199]
          - button "工作台" [ref=e203] [cursor=pointer]
          - button "源码" [ref=e207] [cursor=pointer]
      - generic [ref=e214]:
        - generic [ref=e219]:
          - generic [ref=e220] [cursor=pointer]: åˆ†æžé¡µ
          - generic [ref=e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
        - button [ref=e254] [cursor=pointer]
    - main [ref=e272]:
      - generic [ref=e275]:
        - generic [ref=e276]:
          - button [ref=e277] [cursor=pointer]
          - generic [ref=e280]: æµ‹è¯•项目
          - generic [ref=e281]: æµ‹è¯•编号
          - generic [ref=e282]: è¯„标中
          - generic [ref=e283]: å…¬å¼€æ‹›æ ‡
          - button "刷新" [ref=e284] [cursor=pointer]
        - generic [ref=e290]:
          - generic:
            - generic "草稿"
            - generic "发布"
            - generic "投标中"
            - generic "评标中"
            - generic "已定标"
          - generic [ref=e291]:
            - generic [ref=e292]:
              - generic [ref=e293]: é¢„算金额
              - generic [ref=e294]: 15,000 å…ƒ
            - generic [ref=e295]:
              - generic [ref=e296]: è´Ÿè´£äºº
              - generic [ref=e297]: "-"
            - generic [ref=e298]:
              - generic [ref=e299]: é‡‡è´­ç»„织
              - generic [ref=e300]: "-"
            - generic [ref=e301]:
              - generic [ref=e302]: å¼€æ ‡æ—¶é—´
              - generic [ref=e303]: 2026-07-29 11:20:11
            - generic [ref=e304]:
              - generic [ref=e305]: å¼€å§‹æ—¶é—´
              - generic [ref=e306]: 2026-07-29 11:13:02
            - generic [ref=e307]:
              - generic [ref=e308]: æˆªæ­¢æ—¶é—´
              - generic [ref=e309]: 2026-07-29 19:13:06
        - generic [ref=e313]:
          - tablist [ref=e314]:
            - generic [ref=e316]:
              - tab [ref=e318] [cursor=pointer]
              - tab [ref=e323] [cursor=pointer]
              - tab [ref=e328] [cursor=pointer]
              - tab [active] [selected] [ref=e333] [cursor=pointer]
              - tab [ref=e338] [cursor=pointer]
              - tab [ref=e343] [cursor=pointer]
          - tabpanel "开标" [ref=e406]:
            - generic [ref=e407]:
              - generic "尚未开标"
.playwright-mcp/page-2026-07-29T06-47-24-223Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
.playwright-mcp/page-2026-07-29T06-47-38-983Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,113 @@
- generic [ref=f1e7]:
  - complementary [ref=f1e8]:
    - generic [ref=f1e9]:
      - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=f1e15] [cursor=pointer]:
        - /url: javascript:void 0
        - img "工厂数字化MOM系统" [ref=f1e18]
        - generic [ref=f1e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
      - menu [ref=f1e22]:
        - listitem [ref=f1e23]:
          - generic [ref=f1e24] [cursor=pointer]: æ¦‚览
        - listitem [ref=f1e34]:
          - generic [ref=f1e35] [cursor=pointer]: åŸºç¡€æ•°æ®
        - listitem [ref=f1e43]:
          - generic [ref=f1e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
        - listitem [ref=f1e50]:
          - generic [ref=f1e51] [cursor=pointer]: è¥é”€ç®¡ç†
        - listitem [ref=f1e57]:
          - generic [ref=f1e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
        - listitem [ref=f1e65]:
          - generic [ref=f1e66] [cursor=pointer]: ä»“储物流
        - listitem [ref=f1e74]:
          - generic [ref=f1e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
        - listitem [ref=f1e82]:
          - generic [ref=f1e83] [cursor=pointer]: è´¨é‡ç®¡ç†
        - listitem [ref=f1e89]:
          - generic [ref=f1e90] [cursor=pointer]: ååŒåŠžå…¬
        - listitem [ref=f1e96]:
          - generic [ref=f1e97] [cursor=pointer]: äººåŠ›èµ„æº
        - listitem [ref=f1e103]:
          - generic [ref=f1e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
        - listitem [ref=f1e110]:
          - generic [ref=f1e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
        - listitem [ref=f1e117]:
          - generic [ref=f1e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
  - generic [ref=f1e131]:
    - generic [ref=f1e132]:
      - banner [ref=f1e133]:
        - button [ref=f1e134] [cursor=pointer]
        - button [ref=f1e137] [cursor=pointer]
        - navigation "breadcrumb" [ref=f1e142]:
          - list [ref=f1e143]:
            - listitem [ref=f1e144]:
              - link [ref=f1e145] [cursor=pointer]:
                - /url: javascript:void 0
              - listitem [ref=f1e152]
            - listitem [ref=f1e155]:
              - link "招标详情" [disabled] [ref=f1e156]
        - generic [ref=f1e159]:
          - generic [ref=f1e161] [cursor=pointer]:
            - generic [ref=f1e165]: æœç´¢
            - generic [ref=f1e166]: Ctrl K
          - button [ref=f1e168] [cursor=pointer]
          - button "dark" [ref=f1e173] [cursor=pointer]
          - button [ref=f1e182] [cursor=pointer]
          - button [ref=f1e188] [cursor=pointer]
          - button [ref=f1e191] [cursor=pointer]
          - button [ref=f1e197] [cursor=pointer]:
            - button [ref=f1e199]
          - button "工作台" [ref=f1e203] [cursor=pointer]
          - button "源码" [ref=f1e207] [cursor=pointer]
      - generic [ref=f1e214]:
        - generic [ref=f1e219]:
          - generic [ref=f1e220] [cursor=pointer]: åˆ†æžé¡µ
          - generic [ref=f1e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
        - button [ref=f1e254] [cursor=pointer]
    - main [ref=f1e272]:
      - generic [ref=f1e275]:
        - generic [ref=f1e276]:
          - button [ref=f1e277] [cursor=pointer]
          - generic [ref=f1e280]: æµ‹è¯•项目
          - generic [ref=f1e281]: æµ‹è¯•编号
          - generic [ref=f1e282]: è¯„标中
          - generic [ref=f1e283]: å…¬å¼€æ‹›æ ‡
          - button "刷新" [ref=f1e284] [cursor=pointer]
        - generic [ref=f1e290]:
          - generic:
            - generic "草稿"
            - generic "发布"
            - generic "投标中"
            - generic "评标中"
            - generic "已定标"
          - generic [ref=f1e291]:
            - generic [ref=f1e292]:
              - generic [ref=f1e293]: é¢„算金额
              - generic [ref=f1e294]: 15,000 å…ƒ
            - generic [ref=f1e295]:
              - generic [ref=f1e296]: è´Ÿè´£äºº
              - generic [ref=f1e297]: "-"
            - generic [ref=f1e298]:
              - generic [ref=f1e299]: é‡‡è´­ç»„织
              - generic [ref=f1e300]: "-"
            - generic [ref=f1e301]:
              - generic [ref=f1e302]: å¼€æ ‡æ—¶é—´
              - generic [ref=f1e303]: 2026-07-29 11:20:11
            - generic [ref=f1e304]:
              - generic [ref=f1e305]: å¼€å§‹æ—¶é—´
              - generic [ref=f1e306]: 2026-07-29 11:13:02
            - generic [ref=f1e307]:
              - generic [ref=f1e308]: æˆªæ­¢æ—¶é—´
              - generic [ref=f1e309]: 2026-07-29 19:13:06
        - generic [ref=f1e313]:
          - tablist [ref=f1e314]:
            - generic [ref=f1e316]:
              - tab [ref=f1e318] [cursor=pointer]
              - tab [ref=f1e323] [cursor=pointer]
              - tab [ref=f1e328] [cursor=pointer]
              - tab [ref=f1e333] [cursor=pointer]
              - tab [ref=f1e338] [cursor=pointer]
              - tab [active] [selected] [ref=f1e343] [cursor=pointer]
          - tabpanel "定标" [ref=f1e404]:
            - generic [ref=f1e405]:
              - generic "尚未定标"
              - button "创建定标" [ref=f1e406] [cursor=pointer]
.playwright-mcp/page-2026-07-29T06-47-57-125Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
- generic [ref=f1e4]:
  - generic [ref=f1e7]:
    - complementary [ref=f1e8]:
      - generic [ref=f1e9]:
        - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=f1e15] [cursor=pointer]:
          - /url: javascript:void 0
          - img "工厂数字化MOM系统" [ref=f1e18]
          - generic [ref=f1e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
        - menu [ref=f1e22]:
          - listitem [ref=f1e23]:
            - generic [ref=f1e24] [cursor=pointer]: æ¦‚览
          - listitem [ref=f1e34]:
            - generic [ref=f1e35] [cursor=pointer]: åŸºç¡€æ•°æ®
          - listitem [ref=f1e43]:
            - generic [ref=f1e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
          - listitem [ref=f1e50]:
            - generic [ref=f1e51] [cursor=pointer]: è¥é”€ç®¡ç†
          - listitem [ref=f1e57]:
            - generic [ref=f1e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
          - listitem [ref=f1e65]:
            - generic [ref=f1e66] [cursor=pointer]: ä»“储物流
          - listitem [ref=f1e74]:
            - generic [ref=f1e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
          - listitem [ref=f1e82]:
            - generic [ref=f1e83] [cursor=pointer]: è´¨é‡ç®¡ç†
          - listitem [ref=f1e89]:
            - generic [ref=f1e90] [cursor=pointer]: ååŒåŠžå…¬
          - listitem [ref=f1e96]:
            - generic [ref=f1e97] [cursor=pointer]: äººåŠ›èµ„æº
          - listitem [ref=f1e103]:
            - generic [ref=f1e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
          - listitem [ref=f1e110]:
            - generic [ref=f1e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
          - listitem [ref=f1e117]:
            - generic [ref=f1e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
    - generic [ref=f1e131]:
      - generic [ref=f1e132]:
        - banner [ref=f1e133]:
          - button [ref=f1e134] [cursor=pointer]
          - button [ref=f1e137] [cursor=pointer]
          - navigation "breadcrumb" [ref=f1e142]:
            - list [ref=f1e143]:
              - listitem [ref=f1e144]:
                - link [ref=f1e145] [cursor=pointer]:
                  - /url: javascript:void 0
                - listitem [ref=f1e152]
              - listitem [ref=f1e155]:
                - link "招标详情" [disabled] [ref=f1e156]
          - generic [ref=f1e159]:
            - generic [ref=f1e161] [cursor=pointer]:
              - generic [ref=f1e165]: æœç´¢
              - generic [ref=f1e166]: Ctrl K
            - button [ref=f1e168] [cursor=pointer]
            - button "dark" [ref=f1e173] [cursor=pointer]
            - button [ref=f1e182] [cursor=pointer]
            - button [ref=f1e188] [cursor=pointer]
            - button [ref=f1e191] [cursor=pointer]
            - button [ref=f1e197] [cursor=pointer]:
              - button [ref=f1e199]
            - button "工作台" [ref=f1e203] [cursor=pointer]
            - button "源码" [ref=f1e207] [cursor=pointer]
        - generic [ref=f1e214]:
          - generic [ref=f1e219]:
            - generic [ref=f1e220] [cursor=pointer]: åˆ†æžé¡µ
            - generic [ref=f1e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
          - button [ref=f1e254] [cursor=pointer]
      - main [ref=f1e272]:
        - generic [ref=f1e275]:
          - generic [ref=f1e276]:
            - button [ref=f1e277] [cursor=pointer]
            - generic [ref=f1e280]: æµ‹è¯•项目
            - generic [ref=f1e281]: æµ‹è¯•编号
            - generic [ref=f1e282]: è¯„标中
            - generic [ref=f1e283]: å…¬å¼€æ‹›æ ‡
            - button "刷新" [ref=f1e284] [cursor=pointer]
          - generic [ref=f1e290]:
            - generic:
              - generic "草稿"
              - generic "发布"
              - generic "投标中"
              - generic "评标中"
              - generic "已定标"
            - generic [ref=f1e291]:
              - generic [ref=f1e292]:
                - generic [ref=f1e293]: é¢„算金额
                - generic [ref=f1e294]: 15,000 å…ƒ
              - generic [ref=f1e295]:
                - generic [ref=f1e296]: è´Ÿè´£äºº
                - generic [ref=f1e297]: "-"
              - generic [ref=f1e298]:
                - generic [ref=f1e299]: é‡‡è´­ç»„织
                - generic [ref=f1e300]: "-"
              - generic [ref=f1e301]:
                - generic [ref=f1e302]: å¼€æ ‡æ—¶é—´
                - generic [ref=f1e303]: 2026-07-29 11:20:11
              - generic [ref=f1e304]:
                - generic [ref=f1e305]: å¼€å§‹æ—¶é—´
                - generic [ref=f1e306]: 2026-07-29 11:13:02
              - generic [ref=f1e307]:
                - generic [ref=f1e308]: æˆªæ­¢æ—¶é—´
                - generic [ref=f1e309]: 2026-07-29 19:13:06
          - generic [ref=f1e313]:
            - tablist [ref=f1e314]:
              - generic [ref=f1e316]:
                - tab [ref=f1e318] [cursor=pointer]
                - tab [ref=f1e323] [cursor=pointer]
                - tab [ref=f1e328] [cursor=pointer]
                - tab [ref=f1e333] [cursor=pointer]
                - tab [ref=f1e338] [cursor=pointer]
                - tab [selected] [ref=f1e343] [cursor=pointer]
            - tabpanel "定标" [ref=f1e404]:
              - generic [ref=f1e405]:
                - generic "尚未定标"
                - button "创建定标" [active] [ref=f1e406] [cursor=pointer]
  - dialog "创建定标" [ref=f1e412]:
    - document:
      - generic [ref=f1e413]:
        - button "Close" [ref=f1e414] [cursor=pointer]:
          - img "close" [ref=f1e416]
        - generic [ref=f1e419]: åˆ›å»ºå®šæ ‡
        - generic [ref=f1e422]:
          - generic [ref=f1e424]:
            - generic "定标编号" [ref=f1e426]: "* å®šæ ‡ç¼–号"
            - textbox "如 AWARD2024010001" [ref=f1e430]
          - generic [ref=f1e431]:
            - generic [ref=f1e434]:
              - generic "供应商" [ref=f1e436]: "* ä¾›åº”商"
              - generic [ref=f1e441]:
                - combobox [ref=f1e443]
                - generic "0" [ref=f1e444]
            - generic [ref=f1e447]:
              - generic "投标" [ref=f1e449]: "* æŠ•æ ‡"
              - generic [ref=f1e454]:
                - combobox [ref=f1e456]
                - generic "0" [ref=f1e457]
          - generic [ref=f1e459]:
            - generic "定标金额" [ref=f1e461]: "* å®šæ ‡é‡‘额"
            - generic [ref=f1e466]:
              - generic [ref=f1e467]:
                - generic [ref=f1e468]:
                  - button "Increase Value" [ref=f1e469] [cursor=pointer]:
                    - img "up" [ref=f1e470]
                  - button "Decrease Value" [ref=f1e473] [cursor=pointer]:
                    - img "down" [ref=f1e474]
                - spinbutton "定标金额" [ref=f1e478]
              - generic [ref=f1e479]: å…ƒ
          - generic [ref=f1e481]:
            - generic "备注" [ref=f1e483]
            - textbox "如:综合评标第一名" [ref=f1e487]
        - generic [ref=f1e488]:
          - button "取 æ¶ˆ" [ref=f1e489] [cursor=pointer]
          - button "ç¡® å®š" [ref=f1e491] [cursor=pointer]
.playwright-mcp/page-2026-07-29T06-51-00-932Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,152 @@
- generic [ref=f1e4]:
  - generic [ref=f1e7]:
    - complementary [ref=f1e8]:
      - generic [ref=f1e9]:
        - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=f1e15] [cursor=pointer]:
          - /url: javascript:void 0
          - img "工厂数字化MOM系统" [ref=f1e18]
          - generic [ref=f1e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
        - menu [ref=f1e22]:
          - listitem [ref=f1e23]:
            - generic [ref=f1e24] [cursor=pointer]: æ¦‚览
          - listitem [ref=f1e34]:
            - generic [ref=f1e35] [cursor=pointer]: åŸºç¡€æ•°æ®
          - listitem [ref=f1e43]:
            - generic [ref=f1e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
          - listitem [ref=f1e50]:
            - generic [ref=f1e51] [cursor=pointer]: è¥é”€ç®¡ç†
          - listitem [ref=f1e57]:
            - generic [ref=f1e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
          - listitem [ref=f1e65]:
            - generic [ref=f1e66] [cursor=pointer]: ä»“储物流
          - listitem [ref=f1e74]:
            - generic [ref=f1e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
          - listitem [ref=f1e82]:
            - generic [ref=f1e83] [cursor=pointer]: è´¨é‡ç®¡ç†
          - listitem [ref=f1e89]:
            - generic [ref=f1e90] [cursor=pointer]: ååŒåŠžå…¬
          - listitem [ref=f1e96]:
            - generic [ref=f1e97] [cursor=pointer]: äººåŠ›èµ„æº
          - listitem [ref=f1e103]:
            - generic [ref=f1e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
          - listitem [ref=f1e110]:
            - generic [ref=f1e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
          - listitem [ref=f1e117]:
            - generic [ref=f1e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
    - generic [ref=f1e131]:
      - generic [ref=f1e132]:
        - banner [ref=f1e133]:
          - button [ref=f1e134] [cursor=pointer]
          - button [ref=f1e137] [cursor=pointer]
          - navigation "breadcrumb" [ref=f1e142]:
            - list [ref=f1e143]:
              - listitem [ref=f1e144]:
                - link [ref=f1e145] [cursor=pointer]:
                  - /url: javascript:void 0
                - listitem [ref=f1e152]
              - listitem [ref=f1e155]:
                - link "招标详情" [disabled] [ref=f1e156]
          - generic [ref=f1e159]:
            - generic [ref=f1e161] [cursor=pointer]:
              - generic [ref=f1e165]: æœç´¢
              - generic [ref=f1e166]: Ctrl K
            - button [ref=f1e168] [cursor=pointer]
            - button "dark" [ref=f1e173] [cursor=pointer]
            - button [ref=f1e182] [cursor=pointer]
            - button [ref=f1e188] [cursor=pointer]
            - button [ref=f1e191] [cursor=pointer]
            - button [ref=f1e197] [cursor=pointer]:
              - button [ref=f1e199]
            - button "工作台" [ref=f1e203] [cursor=pointer]
            - button "源码" [ref=f1e207] [cursor=pointer]
        - generic [ref=f1e214]:
          - generic [ref=f1e219]:
            - generic [ref=f1e220] [cursor=pointer]: åˆ†æžé¡µ
            - generic [ref=f1e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
          - button [ref=f1e254] [cursor=pointer]
      - main [ref=f1e272]:
        - generic [ref=f1e275]:
          - generic [ref=f1e276]:
            - button [ref=f1e277] [cursor=pointer]
            - generic [ref=f1e280]: æµ‹è¯•项目
            - generic [ref=f1e281]: æµ‹è¯•编号
            - generic [ref=f1e282]: è¯„标中
            - generic [ref=f1e283]: å…¬å¼€æ‹›æ ‡
            - button "刷新" [ref=f1e284] [cursor=pointer]
          - generic [ref=f1e290]:
            - generic:
              - generic "草稿"
              - generic "发布"
              - generic "投标中"
              - generic "评标中"
              - generic "已定标"
            - generic [ref=f1e291]:
              - generic [ref=f1e292]:
                - generic [ref=f1e293]: é¢„算金额
                - generic [ref=f1e294]: 15,000 å…ƒ
              - generic [ref=f1e295]:
                - generic [ref=f1e296]: è´Ÿè´£äºº
                - generic [ref=f1e297]: "-"
              - generic [ref=f1e298]:
                - generic [ref=f1e299]: é‡‡è´­ç»„织
                - generic [ref=f1e300]: "-"
              - generic [ref=f1e301]:
                - generic [ref=f1e302]: å¼€æ ‡æ—¶é—´
                - generic [ref=f1e303]: 2026-07-29 11:20:11
              - generic [ref=f1e304]:
                - generic [ref=f1e305]: å¼€å§‹æ—¶é—´
                - generic [ref=f1e306]: 2026-07-29 11:13:02
              - generic [ref=f1e307]:
                - generic [ref=f1e308]: æˆªæ­¢æ—¶é—´
                - generic [ref=f1e309]: 2026-07-29 19:13:06
          - generic [ref=f1e313]:
            - tablist [ref=f1e314]:
              - generic [ref=f1e316]:
                - tab [ref=f1e318] [cursor=pointer]
                - tab [ref=f1e323] [cursor=pointer]
                - tab [ref=f1e328] [cursor=pointer]
                - tab [ref=f1e333] [cursor=pointer]
                - tab [ref=f1e338] [cursor=pointer]
                - tab [selected] [ref=f1e343] [cursor=pointer]
            - tabpanel "定标" [ref=f1e404]:
              - generic [ref=f1e405]:
                - generic "尚未定标"
                - button "创建定标" [ref=f1e406] [cursor=pointer]
  - dialog "创建定标" [ref=f1e412]:
    - document:
      - generic [ref=f1e413]:
        - button "Close" [ref=f1e414] [cursor=pointer]:
          - img "close" [ref=f1e416]
        - generic [ref=f1e419]: åˆ›å»ºå®šæ ‡
        - generic [ref=f1e422]:
          - generic [ref=f1e424]:
            - generic "定标编号" [ref=f1e426]: "* å®šæ ‡ç¼–号"
            - textbox "如 AWARD2024010001" [ref=f1e430]
          - generic [ref=f1e431]:
            - generic [ref=f1e434]:
              - generic "供应商" [ref=f1e436]: "* ä¾›åº”商"
              - generic [ref=f1e441]:
                - combobox [ref=f1e443]
                - generic "0" [ref=f1e444]
            - generic [ref=f1e447]:
              - generic "投标" [ref=f1e449]: "* æŠ•æ ‡"
              - generic [ref=f1e454]:
                - combobox [ref=f1e456]
                - generic "0" [ref=f1e457]
          - generic [ref=f1e459]:
            - generic "定标金额" [ref=f1e461]: "* å®šæ ‡é‡‘额"
            - generic [ref=f1e466]:
              - generic [ref=f1e467]:
                - generic [ref=f1e468]:
                  - button "Increase Value" [ref=f1e469] [cursor=pointer]:
                    - img "up" [ref=f1e470]
                  - button "Decrease Value" [ref=f1e473] [cursor=pointer]:
                    - img "down" [ref=f1e474]
                - spinbutton "定标金额" [ref=f1e478]
              - generic [ref=f1e479]: å…ƒ
          - generic [ref=f1e481]:
            - generic "备注" [ref=f1e483]
            - textbox "如:综合评标第一名" [ref=f1e487]
        - generic [ref=f1e488]:
          - button "取 æ¶ˆ" [ref=f1e489] [cursor=pointer]
          - button "ç¡® å®š" [ref=f1e491] [cursor=pointer]
.playwright-mcp/page-2026-07-29T06-56-04-077Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
.playwright-mcp/page-2026-07-29T06-56-14-335Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,122 @@
- generic [ref=f2e7]:
  - complementary [ref=f2e8]:
    - generic [ref=f2e9]:
      - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=f2e15] [cursor=pointer]:
        - /url: javascript:void 0
        - img "工厂数字化MOM系统" [ref=f2e18]
        - generic [ref=f2e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
      - menu [ref=f2e22]:
        - listitem [ref=f2e23]:
          - generic [ref=f2e24] [cursor=pointer]: æ¦‚览
        - listitem [ref=f2e34]:
          - generic [ref=f2e35] [cursor=pointer]: åŸºç¡€æ•°æ®
        - listitem [ref=f2e43]:
          - generic [ref=f2e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
        - listitem [ref=f2e50]:
          - generic [ref=f2e51] [cursor=pointer]: è¥é”€ç®¡ç†
        - listitem [ref=f2e57]:
          - generic [ref=f2e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
        - listitem [ref=f2e65]:
          - generic [ref=f2e66] [cursor=pointer]: ä»“储物流
        - listitem [ref=f2e74]:
          - generic [ref=f2e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
        - listitem [ref=f2e82]:
          - generic [ref=f2e83] [cursor=pointer]: è´¨é‡ç®¡ç†
        - listitem [ref=f2e89]:
          - generic [ref=f2e90] [cursor=pointer]: ååŒåŠžå…¬
        - listitem [ref=f2e96]:
          - generic [ref=f2e97] [cursor=pointer]: äººåŠ›èµ„æº
        - listitem [ref=f2e103]:
          - generic [ref=f2e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
        - listitem [ref=f2e110]:
          - generic [ref=f2e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
        - listitem [ref=f2e117]:
          - generic [ref=f2e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
  - generic [ref=f2e131]:
    - generic [ref=f2e132]:
      - banner [ref=f2e133]:
        - button [ref=f2e134] [cursor=pointer]
        - button [ref=f2e137] [cursor=pointer]
        - navigation "breadcrumb" [ref=f2e142]:
          - list [ref=f2e143]:
            - listitem [ref=f2e144]:
              - link [ref=f2e145] [cursor=pointer]:
                - /url: javascript:void 0
              - listitem [ref=f2e152]
            - listitem [ref=f2e155]:
              - link "招标详情" [disabled] [ref=f2e156]
        - generic [ref=f2e159]:
          - generic [ref=f2e161] [cursor=pointer]:
            - generic [ref=f2e165]: æœç´¢
            - generic [ref=f2e166]: Ctrl K
          - button [ref=f2e168] [cursor=pointer]
          - button "dark" [ref=f2e173] [cursor=pointer]
          - button [ref=f2e182] [cursor=pointer]
          - button [ref=f2e188] [cursor=pointer]
          - button [ref=f2e191] [cursor=pointer]
          - button [ref=f2e197] [cursor=pointer]:
            - button [ref=f2e199]
          - button "工作台" [ref=f2e203] [cursor=pointer]
          - button "源码" [ref=f2e207] [cursor=pointer]
      - generic [ref=f2e214]:
        - generic [ref=f2e219]:
          - generic [ref=f2e220] [cursor=pointer]: åˆ†æžé¡µ
          - generic [ref=f2e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
        - button [ref=f2e254] [cursor=pointer]
    - main [ref=f2e272]:
      - generic [ref=f2e275]:
        - generic [ref=f2e276]:
          - button [ref=f2e277] [cursor=pointer]
          - generic [ref=f2e280]: æµ‹è¯•项目
          - generic [ref=f2e281]: æµ‹è¯•编号
          - generic [ref=f2e282]: å·²å®šæ ‡
          - generic [ref=f2e283]: å…¬å¼€æ‹›æ ‡
          - button "刷新" [ref=f2e284] [cursor=pointer]
        - generic [ref=f2e290]:
          - generic:
            - generic "草稿"
            - generic "发布"
            - generic "投标中"
            - generic "评标中"
            - generic "已定标"
          - generic [ref=f2e291]:
            - generic [ref=f2e292]:
              - generic [ref=f2e293]: é¢„算金额
              - generic [ref=f2e294]: 15,000 å…ƒ
            - generic [ref=f2e295]:
              - generic [ref=f2e296]: è´Ÿè´£äºº
              - generic [ref=f2e297]: "-"
            - generic [ref=f2e298]:
              - generic [ref=f2e299]: é‡‡è´­ç»„织
              - generic [ref=f2e300]: "-"
            - generic [ref=f2e301]:
              - generic [ref=f2e302]: å¼€æ ‡æ—¶é—´
              - generic [ref=f2e303]: 2026-07-29 11:20:11
            - generic [ref=f2e304]:
              - generic [ref=f2e305]: å¼€å§‹æ—¶é—´
              - generic [ref=f2e306]: 2026-07-29 11:13:02
            - generic [ref=f2e307]:
              - generic [ref=f2e308]: æˆªæ­¢æ—¶é—´
              - generic [ref=f2e309]: 2026-07-29 19:13:06
        - generic [ref=f2e313]:
          - tablist [ref=f2e314]:
            - generic [ref=f2e316]:
              - tab [ref=f2e318] [cursor=pointer]
              - tab [ref=f2e323] [cursor=pointer]
              - tab [ref=f2e328] [cursor=pointer]
              - tab [ref=f2e333] [cursor=pointer]
              - tab [ref=f2e338] [cursor=pointer]
              - tab [active] [selected] [ref=f2e343] [cursor=pointer]
          - tabpanel "定标" [ref=f2e350]:
            - generic [ref=f2e351]:
              - generic [ref=f2e353]:
                - generic [ref=f2e354]: å·²å®šè¡¨
                - generic [ref=f2e355]: "12"
                - generic [ref=f2e357]: 10,000 å…ƒ
                - text: 2026-07-29 14:52:43
                - generic [ref=f2e358]: å·²å®šæ ‡
                - text: å¾…生成综合评定
              - generic [ref=f2e361]:
                - generic "定标完成"
                - button "生成采购订单" [ref=f2e362] [cursor=pointer]
                - button "删除定标" [ref=f2e366] [cursor=pointer]
.playwright-mcp/page-2026-07-29T07-10-45-745Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
.playwright-mcp/page-2026-07-29T07-12-31-548Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
- generic [ref=f3e7]:
  - complementary [ref=f3e8]:
    - generic [ref=f3e9]:
      - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=f3e15] [cursor=pointer]:
        - /url: javascript:void 0
        - img "工厂数字化MOM系统" [ref=f3e18]
        - generic [ref=f3e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
      - menu [ref=f3e22]:
        - listitem [ref=f3e23]:
          - generic [ref=f3e24] [cursor=pointer]: æ¦‚览
        - listitem [ref=f3e34]:
          - generic [ref=f3e35] [cursor=pointer]: åŸºç¡€æ•°æ®
        - listitem [ref=f3e43]:
          - generic [ref=f3e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
        - listitem [ref=f3e50]:
          - generic [ref=f3e51] [cursor=pointer]: è¥é”€ç®¡ç†
        - listitem [ref=f3e57]:
          - generic [ref=f3e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
        - listitem [ref=f3e65]:
          - generic [ref=f3e66] [cursor=pointer]: ä»“储物流
        - listitem [ref=f3e74]:
          - generic [ref=f3e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
        - listitem [ref=f3e82]:
          - generic [ref=f3e83] [cursor=pointer]: è´¨é‡ç®¡ç†
        - listitem [ref=f3e89]:
          - generic [ref=f3e90] [cursor=pointer]: ååŒåŠžå…¬
        - listitem [ref=f3e96]:
          - generic [ref=f3e97] [cursor=pointer]: äººåŠ›èµ„æº
        - listitem [ref=f3e103]:
          - generic [ref=f3e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
        - listitem [ref=f3e110]:
          - generic [ref=f3e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
        - listitem [ref=f3e117]:
          - generic [ref=f3e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
  - generic [ref=f3e131]:
    - generic [ref=f3e132]:
      - banner [ref=f3e133]:
        - button [ref=f3e134] [cursor=pointer]
        - button [ref=f3e137] [cursor=pointer]
        - navigation "breadcrumb" [ref=f3e142]:
          - list [ref=f3e143]:
            - listitem [ref=f3e144]:
              - link [ref=f3e145] [cursor=pointer]:
                - /url: javascript:void 0
              - listitem [ref=f3e152]
            - listitem [ref=f3e155]:
              - link "招标详情" [disabled] [ref=f3e156]
        - generic [ref=f3e159]:
          - generic [ref=f3e161] [cursor=pointer]:
            - generic [ref=f3e165]: æœç´¢
            - generic [ref=f3e166]: Ctrl K
          - button [ref=f3e168] [cursor=pointer]
          - button "dark" [ref=f3e173] [cursor=pointer]
          - button [ref=f3e182] [cursor=pointer]
          - button [ref=f3e188] [cursor=pointer]
          - button [ref=f3e191] [cursor=pointer]
          - button [ref=f3e197] [cursor=pointer]:
            - button [ref=f3e199]
          - button "工作台" [ref=f3e203] [cursor=pointer]
          - button "源码" [ref=f3e207] [cursor=pointer]
      - generic [ref=f3e214]:
        - generic [ref=f3e219]:
          - generic [ref=f3e220] [cursor=pointer]: åˆ†æžé¡µ
          - generic [ref=f3e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
        - button [ref=f3e254] [cursor=pointer]
    - main [ref=f3e272]:
      - generic [ref=f3e275]:
        - generic [ref=f3e276]:
          - button [ref=f3e277] [cursor=pointer]
          - generic [ref=f3e280]: æµ‹è¯•项目
          - generic [ref=f3e281]: æµ‹è¯•编号
          - generic [ref=f3e282]: å·²å®šæ ‡
          - generic [ref=f3e283]: å…¬å¼€æ‹›æ ‡
          - button "刷新" [ref=f3e284] [cursor=pointer]
        - generic [ref=f3e290]:
          - generic:
            - generic "草稿"
            - generic "发布"
            - generic "投标中"
            - generic "评标中"
            - generic "已定标"
          - generic [ref=f3e291]:
            - generic [ref=f3e292]:
              - generic [ref=f3e293]: é¢„算金额
              - generic [ref=f3e294]: 15,000 å…ƒ
            - generic [ref=f3e295]:
              - generic [ref=f3e296]: è´Ÿè´£äºº
              - generic [ref=f3e297]: "-"
            - generic [ref=f3e298]:
              - generic [ref=f3e299]: é‡‡è´­ç»„织
              - generic [ref=f3e300]: "-"
            - generic [ref=f3e301]:
              - generic [ref=f3e302]: å¼€æ ‡æ—¶é—´
              - generic [ref=f3e303]: 2026-07-29 11:20:11
            - generic [ref=f3e304]:
              - generic [ref=f3e305]: å¼€å§‹æ—¶é—´
              - generic [ref=f3e306]: 2026-07-29 11:13:02
            - generic [ref=f3e307]:
              - generic [ref=f3e308]: æˆªæ­¢æ—¶é—´
              - generic [ref=f3e309]: 2026-07-29 19:13:06
        - generic [ref=f3e313]:
          - tablist [ref=f3e314]:
            - generic [ref=f3e316]:
              - tab [ref=f3e318] [cursor=pointer]
              - tab [ref=f3e323] [cursor=pointer]
              - tab [ref=f3e328] [cursor=pointer]
              - tab [ref=f3e333] [cursor=pointer]
              - tab [ref=f3e338] [cursor=pointer]
              - tab [active] [selected] [ref=f3e343] [cursor=pointer]
          - tabpanel "定标" [ref=f3e404]:
            - generic [ref=f3e405]:
              - generic [ref=f3e407]:
                - generic [ref=f3e408]: å·²å®šè¡¨
                - generic [ref=f3e409]: "12"
                - generic [ref=f3e411]: 10,000 å…ƒ
                - text: 2026-07-29 14:52:43
                - generic [ref=f3e412]: å·²ç”Ÿæˆè®¢å•
                - text: 18综合评定
              - generic [ref=f3e415]:
                - generic "订单已生成"
                - button "删除定标" [ref=f3e416] [cursor=pointer]
.playwright-mcp/page-2026-07-29T07-14-24-445Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
.playwright-mcp/page-2026-07-29T07-14-44-587Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,121 @@
- generic [ref=f4e7]:
  - complementary [ref=f4e8]:
    - generic [ref=f4e9]:
      - link "工厂数字化MOM系统 å·¥åŽ‚æ•°å­—åŒ–MOM系统" [ref=f4e15] [cursor=pointer]:
        - /url: javascript:void 0
        - img "工厂数字化MOM系统" [ref=f4e18]
        - generic [ref=f4e19]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
      - menu [ref=f4e22]:
        - listitem [ref=f4e23]:
          - generic [ref=f4e24] [cursor=pointer]: æ¦‚览
        - listitem [ref=f4e34]:
          - generic [ref=f4e35] [cursor=pointer]: åŸºç¡€æ•°æ®
        - listitem [ref=f4e43]:
          - generic [ref=f4e44] [cursor=pointer]: é‡‡è´­ç®¡ç†
        - listitem [ref=f4e50]:
          - generic [ref=f4e51] [cursor=pointer]: è¥é”€ç®¡ç†
        - listitem [ref=f4e57]:
          - generic [ref=f4e58] [cursor=pointer]: è®¾å¤‡ç®¡ç†
        - listitem [ref=f4e65]:
          - generic [ref=f4e66] [cursor=pointer]: ä»“储物流
        - listitem [ref=f4e74]:
          - generic [ref=f4e75] [cursor=pointer]: ç”Ÿäº§ç®¡æŽ§
        - listitem [ref=f4e82]:
          - generic [ref=f4e83] [cursor=pointer]: è´¨é‡ç®¡ç†
        - listitem [ref=f4e89]:
          - generic [ref=f4e90] [cursor=pointer]: ååŒåŠžå…¬
        - listitem [ref=f4e96]:
          - generic [ref=f4e97] [cursor=pointer]: äººåŠ›èµ„æº
        - listitem [ref=f4e103]:
          - generic [ref=f4e104] [cursor=pointer]: åŸºç¡€è®¾æ–½
        - listitem [ref=f4e110]:
          - generic [ref=f4e111] [cursor=pointer]: ç³»ç»Ÿç®¡ç†
        - listitem [ref=f4e117]:
          - generic [ref=f4e118] [cursor=pointer]: IM å³æ—¶é€šè®¯
  - generic [ref=f4e131]:
    - generic [ref=f4e132]:
      - banner [ref=f4e133]:
        - button [ref=f4e134] [cursor=pointer]
        - button [ref=f4e137] [cursor=pointer]
        - navigation "breadcrumb" [ref=f4e142]:
          - list [ref=f4e143]:
            - listitem [ref=f4e144]:
              - link [ref=f4e145] [cursor=pointer]:
                - /url: javascript:void 0
              - listitem [ref=f4e152]
            - listitem [ref=f4e155]:
              - link "招标详情" [disabled] [ref=f4e156]
        - generic [ref=f4e159]:
          - generic [ref=f4e161] [cursor=pointer]:
            - generic [ref=f4e165]: æœç´¢
            - generic [ref=f4e166]: Ctrl K
          - button [ref=f4e168] [cursor=pointer]
          - button "dark" [ref=f4e173] [cursor=pointer]
          - button [ref=f4e182] [cursor=pointer]
          - button [ref=f4e188] [cursor=pointer]
          - button [ref=f4e191] [cursor=pointer]
          - button [ref=f4e197] [cursor=pointer]:
            - button [ref=f4e199]
          - button "工作台" [ref=f4e203] [cursor=pointer]
          - button "源码" [ref=f4e207] [cursor=pointer]
      - generic [ref=f4e214]:
        - generic [ref=f4e219]:
          - generic [ref=f4e220] [cursor=pointer]: åˆ†æžé¡µ
          - generic [ref=f4e238] [cursor=pointer]: æ‹›æ ‡è¯¦æƒ…
        - button [ref=f4e254] [cursor=pointer]
    - main [ref=f4e272]:
      - generic [ref=f4e275]:
        - generic [ref=f4e276]:
          - button [ref=f4e277] [cursor=pointer]
          - generic [ref=f4e280]: æµ‹è¯•项目
          - generic [ref=f4e281]: æµ‹è¯•编号
          - generic [ref=f4e282]: å·²å®šæ ‡
          - generic [ref=f4e283]: å…¬å¼€æ‹›æ ‡
          - button "刷新" [ref=f4e284] [cursor=pointer]
        - generic [ref=f4e290]:
          - generic:
            - generic "草稿"
            - generic "发布"
            - generic "投标中"
            - generic "评标中"
            - generic "已定标"
          - generic [ref=f4e291]:
            - generic [ref=f4e292]:
              - generic [ref=f4e293]: é¢„算金额
              - generic [ref=f4e294]: 15,000 å…ƒ
            - generic [ref=f4e295]:
              - generic [ref=f4e296]: è´Ÿè´£äºº
              - generic [ref=f4e297]: "-"
            - generic [ref=f4e298]:
              - generic [ref=f4e299]: é‡‡è´­ç»„织
              - generic [ref=f4e300]: "-"
            - generic [ref=f4e301]:
              - generic [ref=f4e302]: å¼€æ ‡æ—¶é—´
              - generic [ref=f4e303]: 2026-07-29 11:20:11
            - generic [ref=f4e304]:
              - generic [ref=f4e305]: å¼€å§‹æ—¶é—´
              - generic [ref=f4e306]: 2026-07-29 11:13:02
            - generic [ref=f4e307]:
              - generic [ref=f4e308]: æˆªæ­¢æ—¶é—´
              - generic [ref=f4e309]: 2026-07-29 19:13:06
        - generic [ref=f4e313]:
          - tablist [ref=f4e314]:
            - generic [ref=f4e316]:
              - tab [ref=f4e318] [cursor=pointer]
              - tab [ref=f4e323] [cursor=pointer]
              - tab [ref=f4e328] [cursor=pointer]
              - tab [ref=f4e333] [cursor=pointer]
              - tab [ref=f4e338] [cursor=pointer]
              - tab [selected] [ref=f4e343] [cursor=pointer]
          - tabpanel "定标" [active] [ref=f4e404]:
            - generic [ref=f4e405]:
              - generic [ref=f4e407]:
                - generic [ref=f4e408]: AWARD2024070001
                - generic [ref=f4e409]: "12"
                - generic [ref=f4e411]: 10,000 å…ƒ
                - text: 2026-07-29 14:52:43
                - generic [ref=f4e412]: å·²ç”Ÿæˆè®¢å•
                - text: 18综合评定
              - generic [ref=f4e415]:
                - generic "订单已生成"
                - button "删除定标" [ref=f4e416] [cursor=pointer]
.playwright-mcp/page-2026-07-29T07-14-58-476Z.yml
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1 @@
- generic [active]: å·¥åŽ‚æ•°å­—åŒ–MOM系统
docs/crm_customer_view_all.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,88 @@
# æŸ¥çœ‹å…¨éƒ¨å®¢æˆ·æƒé™ - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
| é¡µé¢ | è·¯ç”±è·¯å¾„ | è¯´æ˜Ž |
|------|----------|------|
| å®¢æˆ·ç®¡ç†åˆ—表 | `/crm/customer` | å®¢æˆ·åˆ—表页,新增"全部"Tab |
---
## API
### å·²æœ‰æŽ¥å£ï¼šå®¢æˆ·åˆ†é¡µæŸ¥è¯¢ï¼ˆæ— éœ€æ–°å¢žæŽ¥å£ï¼‰
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/crm/customer/page` | å®¢æˆ·åˆ†é¡µæŸ¥è¯¢ |
**已有请求参数(`CrmCustomerPageReqVO`):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| sceneType | Integer | å¦ | åœºæ™¯ç±»åž‹ï¼š1-我负责的 / 2-我参与的 / 3-下属负责的 / **4-全部(新增)** |
| name | String | å¦ | å®¢æˆ·åç§°ï¼ˆæ¨¡ç³Šï¼‰ |
| mobile | String | å¦ | æ‰‹æœº |
| industryId | Integer | å¦ | æ‰€å±žè¡Œä¸š |
| level | Integer | å¦ | å®¢æˆ·ç­‰çº§ |
| source | Integer | å¦ | å®¢æˆ·æ¥æº |
| pool | Boolean | å¦ | æ˜¯å¦ä¸ºå…¬æµ·æ•°æ® |
| followUpStatus | Boolean | å¦ | è·Ÿè¿›çŠ¶æ€ |
**响应无变化**,`CrmCustomerRespVO` å·²åŒ…含:
- `ownerUserName` â€” é”€å”®äººå‘˜åç§°
- `ownerUserDeptName` â€” é”€å”®äººå‘˜éƒ¨é—¨åç§°
---
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
### åœºæ™¯ç±»åž‹æ‰©å±•
| sceneType å€¼ | åœºæ™¯åç§° | æ•°æ®èŒƒå›´ | æƒé™è¦æ±‚ |
|--------------|----------|----------|----------|
| 1 | æˆ‘负责的 | `owner_user_id = å½“前用户` | `crm:customer:query` |
| 2 | æˆ‘参与的 | å›¢é˜Ÿæˆå‘˜ï¼ˆéžè´Ÿè´£äººï¼‰ | `crm:customer:query` |
| 3 | ä¸‹å±žè´Ÿè´£çš„ | ä¸‹å±žä¸ºè´Ÿè´£äºº | `crm:customer:query` |
| **4(新增)** | **全部** | **所有客户(无过滤)** | **`crm:customer:view-all` æˆ– `crm_admin` è§’色** |
### æƒé™é™çº§è§„则
当用户以 `sceneType=4` è¯·æ±‚数据时:
- ç”¨æˆ·æ‹¥æœ‰ `crm:customer:view-all` æƒé™ **或** `crm_admin` è§’色 â†’ è¿”回全部客户
- ç”¨æˆ·**没有**该权限 â†’ è‡ªåŠ¨é™çº§ä¸º"我负责的"(`sceneType=1`),仅返回自己的客户
### æƒé™æ ‡è¯†
| æƒé™æ ‡è¯† | è¯´æ˜Ž | æ‰€å±žèœå• |
|----------|------|----------|
| `crm:customer:view-all` | æŸ¥çœ‹å…¨éƒ¨å®¢æˆ· | CRM å®¢æˆ·å…¬æµ· |
该权限已添加到数据库 `system_menu` è¡¨ï¼Œä½äºŽã€Œå®¢æˆ·å…¬æµ·ã€èœå•下(id=602583),角色分配后即可生效。
---
## å‰ç«¯ä¿®æ”¹ç‚¹
### 1. å®¢æˆ·åˆ—表页 Tab åˆ‡æ¢
在现有的场景类型 Tab(我负责的/我参与的/下属负责的)后面,新增"全部"Tab(`sceneType=4`)。
**展示规则**:
- ä»…当用户拥有 `crm:customer:view-all` æƒé™æˆ– `crm_admin` è§’色时,才显示"全部"Tab
- åˆ¤æ–­æ–¹å¼ï¼šè°ƒç”¨æƒé™åˆ¤æ–­æŽ¥å£æˆ–从用户权限列表中检查
### 2. æƒé™åˆ¤æ–­
前端需要判断当前用户是否有 `crm:customer:view-all` æƒé™ï¼š
- æ–¹å¼ä¸€ï¼šé€šè¿‡ Vue æŒ‡ä»¤ `v-hasPermi="['crm:customer:view-all']"` æŽ§åˆ¶ Tab æ˜¾éš
- æ–¹å¼äºŒï¼šé€šè¿‡èŽ·å–ç”¨æˆ·æƒé™åˆ—è¡¨åˆ¤æ–­
---
## æ³¨æ„äº‹é¡¹
- "全部"Tab ä»…控制数据可见范围,不改变其他功能权限(如编辑、删除仍需对应权限)
- å¯¼å‡º Excel æ—¶åŒæ ·æ”¯æŒ `sceneType=4`,拥有权限的用户可导出全部客户数据
- æƒé™æ•°æ®å·²æ’入数据库(`system_menu` id=602583),无需前端额外处理权限注册
- è¯¥æƒé™ä¸Ž `crm_admin` è§’色的区别:`crm_admin` æ‹¥æœ‰æ‰€æœ‰ CRM ç®¡ç†æƒé™ï¼Œè€Œ `view-all` ä»…控制客户列表的查看范围
docs/document_audit_project_filter_fix.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,59 @@
# é¡¹ç›®è¯¦æƒ… - èµ„料审核查询修复(前端联调方案)
## é—®é¢˜
项目详情页"资料审核" Tab æŸ¥è¯¢ `/mes/pd/document-audit/page` æ—¶æœªä¼ å…¥ `projectId`,导致返回了所有项目的审核记录,而非当前项目的。
## æ¶‰åŠé¡µé¢
| é¡µé¢ | è·¯ç”± | è¯´æ˜Ž |
|------|------|------|
| é¡¹ç›®è¯¦æƒ… - èµ„料审核 Tab | `/mes/pd/project/detail/{id}` | å¾…修复 |
---
## API å˜æ›´
`GET /mes/pd/document-audit/page` â€” æ–°å¢žè¯·æ±‚参数:
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| projectId | Long | å¦ | é¡¹ç›® ID,传入后仅返回该项目下资料的审核记录 |
**响应结构不变。**
---
## å‰ç«¯ä¿®æ”¹ç‚¹
**文件**: `src/views/mes/pd/project/modules/document-audit-list.vue`
该组件已通过 `props.projectId` æŽ¥æ”¶äº†é¡¹ç›® ID,但未传给接口。在 `proxyConfig.ajax.query` ä¸­åŠ ä¸Šå³å¯ï¼š
```typescript
// ç¬¬ 62-67 è¡Œï¼ŒåŽŸæ¥çš„ï¼š
query: async ({ page }, formValues) => {
  return await getPdDocumentAuditPage({
    pageNo: page.currentPage,
    pageSize: page.pageSize,
    ...formValues,
  });
},
// æ”¹ä¸ºï¼š
query: async ({ page }, formValues) => {
  return await getPdDocumentAuditPage({
    pageNo: page.currentPage,
    pageSize: page.pageSize,
    projectId: props.projectId,
    ...formValues,
  });
},
```
---
## æ³¨æ„äº‹é¡¹
- è¯¥ç»„件在项目状态为 `PENDING_AUDIT`(待审核)时展示,通过 props æŽ¥æ”¶ `projectId`
- æ”¹åŠ¨ä»…éœ€ä¸€è¡Œï¼Œæ— éœ€ä¿®æ”¹ API å°è£…函数或类型定义
docs/machinery_new_fields_frontend.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,140 @@
# è®¾å¤‡å°è´¦æ–°å¢žå­—段 - å‰ç«¯è”调方案
## æ¶‰åŠé¡µé¢
| é¡µé¢ | è·¯ç”±è·¯å¾„ | è¯´æ˜Ž |
|------|----------|------|
| è®¾å¤‡å°è´¦åˆ—表 | `/mes/dv-machinery` | åˆ—表新增筛选条件、表格列 |
| è®¾å¤‡å°è´¦è¡¨å• | `/mes/dv-machinery` (弹窗) | æ–°å¢ž/编辑表单中增加 3 ä¸ªå­—段 |
| è®¾å¤‡å°è´¦å¯¼å…¥ | åŒä¸Šï¼ˆå¯¼å…¥å¼¹çª—) | Excel æ¨¡æ¿æ–°å¢ž 3 åˆ— |
---
## æ–°å¢žå­—段说明
| å­—段 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| `productionEfficiency` | BigDecimal | å¦ | ç”Ÿäº§æ•ˆçŽ‡ï¼Œå•ä½ï¼šæ¯å°æ—¶ç”Ÿäº§æ•°é‡ï¼Œç”¨äºŽä¸‹æŽ’äº§è‡ªåŠ¨è®¡ç®—ç”Ÿäº§æ—¶é—´ |
| `conveyorBelt` | Integer | å¦ | ä¼ é€å±¥å¸¦æ•°é‡ï¼Œä¾‹ï¼š2 ä»£è¡¨åŒå€æ•ˆçއ |
| `workstationId` | Long | å¦ | å·¥ä½œç«™ç¼–号,用于将设备绑定到指定工作站 |
---
## API
### å·²æœ‰æŽ¥å£ï¼ˆæ— éœ€æ–°å¢žï¼‰
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| POST | `/mes/dv/machinery/create` | åˆ›å»ºè®¾å¤‡ |
| PUT | `/mes/dv/machinery/update` | æ›´æ–°è®¾å¤‡ |
| GET | `/mes/dv/machinery/get?id={id}` | èŽ·å–è¯¦æƒ… |
| GET | `/mes/dv/machinery/page` | åˆ†é¡µæŸ¥è¯¢ |
| GET | `/mes/dv/machinery/simple-list` | ç²¾ç®€åˆ—表(下拉选项) |
| POST | `/mes/dv/machinery/import` | å¯¼å…¥è®¾å¤‡ |
| GET | `/mes/dv/machinery/get-import-template` | ä¸‹è½½å¯¼å…¥æ¨¡æ¿ |
### è¯·æ±‚参数 - åˆ›å»º/更新(`MesDvMachinerySaveReqVO`)
**新增字段:**
| å­—段 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| productionEfficiency | BigDecimal | å¦ | ç”Ÿäº§æ•ˆçŽ‡ï¼ˆæ¯åˆ†é’Ÿï¼‰ |
| conveyorBelt | Integer | å¦ | ä¼ é€å±¥å¸¦æ•°é‡ |
| workstationId | Long | å¦ | å·¥ä½œç«™ç¼–号 |
### åˆ†é¡µæŸ¥è¯¢å‚数(`MesDvMachineryPageReqVO`)
**新增筛选字段:**
| å­—段 | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| workstationId | Long | å¦ | æŒ‰å·¥ä½œç«™ç­›é€‰ |
### å“åº”(`MesDvMachineryRespVO`)
**新增字段:**
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| productionEfficiency | BigDecimal | ç”Ÿäº§æ•ˆçއ |
| conveyorBelt | Integer | ä¼ é€å±¥å¸¦ |
| workstationId | Long | å·¥ä½œç«™ç¼–号 |
| workstationName | String | å·¥ä½œç«™åç§° |
**响应示例:**
```json
{
  "code": 0,
  "data": {
    "id": 1,
    "name": "CNC åŠ å·¥ä¸­å¿ƒ",
    "code": "EQ-001",
    "productionEfficiency": 10.5,
    "conveyorBelt": 2,
    "workstationId": 300,
    "workstationName": "一号工作站",
    ...
  }
}
```
---
## å‰ç«¯ä¿®æ”¹ç‚¹
### 1. åˆ—表页 - ç­›é€‰é¡¹
在列表搜索栏新增"工作站"下拉筛选框,调用 `/mes/md-workstation/simple-list` èŽ·å–é€‰é¡¹ã€‚
### 2. åˆ—表页 - è¡¨æ ¼åˆ—
| æ–°å¢žåˆ— | ç»‘定字段 | è¯´æ˜Ž |
|--------|----------|------|
| ç”Ÿäº§æ•ˆçއ | `productionEfficiency` | æ˜¾ç¤ºæ•°å€¼ |
| ä¼ é€å±¥å¸¦ | `conveyorBelt` | æ˜¾ç¤ºæ•°å€¼ |
| å·¥ä½œç«™ | `workstationName` | æ˜¾ç¤ºå·¥ä½œç«™åç§° |
### 3. è¡¨å•页 - æ–°å¢ž/编辑
在表单中新增 3 ä¸ªå­—段:
| å­—段 | ç»„ä»¶ | è¯´æ˜Ž |
|------|------|------|
| ç”Ÿäº§æ•ˆçއ | `<el-input-number>` | æ”¯æŒå°æ•°ï¼Œå•位提示"每小时" |
| ä¼ é€å±¥å¸¦ | `<el-input-number>` | æ­£æ•´æ•°ï¼Œæç¤º"2=双倍效率" |
| å·¥ä½œç«™ | `<el-select>` | ä¸‹æ‹‰é€‰æ‹©ï¼Œè°ƒç”¨å·¥ä½œç«™ç²¾ç®€åˆ—表接口 |
### 4. å¯¼å…¥æ¨¡æ¿
导入 Excel æ¨¡æ¿æ–°å¢ž 3 åˆ—(可选列):
| åˆ—名 | è¯´æ˜Ž |
|------|------|
| ç”Ÿäº§æ•ˆçއ(每小时) | æ•°å­—,可选 |
| ä¼ é€å±¥å¸¦ | æ•´æ•°ï¼Œå¯é€‰ |
| å·¥ä½œç«™ç¼–码 | å·¥ä½œç«™ç¼–码,可选,填了则校验是否存在 |
---
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| è§„则 | è¯´æ˜Ž |
|------|------|
| ç”Ÿäº§æ•ˆçŽ‡å•ä½ | å›ºå®šä¸º"每小时生产数量",前端直接展示"每小时" |
| ä¼ é€å±¥å¸¦å«ä¹‰ | æ•°å€¼ 2 ä»£è¡¨åŒå€æ•ˆçŽ‡ï¼ŒæŽ’äº§æ—¶ `conveyorBelt Ã— productionEfficiency` å¾—到最终产能 |
| å·¥ä½œç«™ç»‘定 | ä¸€å°è®¾å¤‡å¯ç»‘定一个工作站(非强制),下拉数据源为 `/mes/md-workstation/simple-list` |
| å¯¼å…¥æ—¶å·¥ä½œç«™ | å¡«å…¥å·¥ä½œç«™ç¼–码(非 ID),系统自动转换,编码不存在则导入失败 |
---
## æ³¨æ„äº‹é¡¹
- 3 ä¸ªæ–°å­—段均为可选,不影响现有数据
- ç”Ÿäº§æ•ˆçŽ‡è¾“å…¥å»ºè®®é™åˆ¶æœ€å°å€¼ 0,保留 2 ä½å°æ•°
- ä¼ é€å±¥å¸¦ä»…允许正整数
- å·¥ä½œç«™ä¸‹æ‹‰ä½¿ç”¨å·²æœ‰æŽ¥å£ `/mes/md-workstation/simple-list`,无需新增
- Excel å¯¼å…¥æ—¶å·¥ä½œç«™åˆ—填编码而非 ID
- å¯¼å…¥æ¨¡æ¿åŽç«¯æŽ¥å£ `/mes/dv/machinery/get-import-template` ä¹Ÿä¼šè¿”回新列
docs/pro_archive_integration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,154 @@
# ç”Ÿäº§æµç¨‹ - æŸ¥çœ‹äº§å“è®¾è®¡å½’档及附件(前端联调方案)
## æ¶‰åŠé¡µé¢
| é¡µé¢ | è·¯ç”±è·¯å¾„ | è¯´æ˜Ž |
|------|----------|------|
| ç”Ÿäº§å·¥å•列表/详情 | `/mes/pro-workorder` | æ–°å¢ž"查看归档"按钮 |
| ç”Ÿäº§å·¥å•中心 | `/mes/workorder-center` | æ–°å¢ž"查看归档"按钮 |
| ç”Ÿäº§ä»»åŠ¡åˆ—è¡¨/详情 | `/mes/pro-task` | æ–°å¢ž"查看归档"按钮 |
| å¾…报工台账 | `/mes/pro-task` (pending-feedback) | æ–°å¢ž"查看归档"按钮 |
| ç”Ÿäº§æŠ¥å·¥åˆ—表/详情 | `/mes/pro-feedback` | æ–°å¢ž"查看归档"按钮 |
---
## API(已有接口,无需新增)
### å½’档分页列表
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/mes/pd/archive/page` | æŒ‰äº§å“ç¼–码筛选归档列表 |
**请求参数(关键):**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| productCode | String | æ˜¯ | äº§å“ç¼–码,从当前记录的 `itemCode` æˆ– `productCode` ä¼ å…¥ |
| pageNo | Integer | å¦ | é¡µç  |
| pageSize | Integer | å¦ | æ¯é¡µæ¡æ•° |
### å½’档详情(含附件)
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/mes/pd/archive/detail-by-product` | æŒ‰äº§å“ç¼–码获取归档详情和附件 |
**请求参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| productCode | String | æ˜¯ | äº§å“ç¼–码 |
**响应结构:**
```json
{
  "code": 0,
  "data": [
    {
      "project": {
        "id": 1,
        "taskCode": "PD2024001",
        "taskName": "新产品设计任务",
        "productCode": "P001",
        "productName": "注塑产品A",
        "version": "V1.0",
        "status": 4,
        "chiefDesigner": 1,
        "chiefDesignerNickname": "张三"
      },
      "archives": [
        {
          "id": 1,
          "archiveCode": "ARC2024001",
          "archiver": 1,
          "archiverNickname": "王五",
          "archiveStatus": 1,
          "archiveTime": "2024-01-15T10:30:00"
        }
      ],
      "documents": [
        {
          "id": 1,
          "documentType": "1",
          "documentName": "产品设计图",
          "documentVersion": "V1.0",
          "fileName": "design.pdf",
          "attachmentList": [
            {
              "id": "blob-id-xxx",
              "name": "设计图纸.pdf",
              "url": "/system/storage-blob/preview/xxx"
            }
          ],
          "uploadUserId": 1,
          "uploadUserNickname": "赵六",
          "uploadTime": "2024-01-10T09:00:00"
        }
      ]
    }
  ]
}
```
---
## æ•°æ®ä¼ é€’
生产流程各环节的记录中已包含产品编码,直接传给归档接口:
| æ¥æºé¡µé¢ | å­—段名 | ä¼ ç»™å½’档接口 |
|----------|--------|-------------|
| ç”Ÿäº§å·¥å• | `productCode` | `?productCode={productCode}` |
| ç”Ÿäº§ä»»åŠ¡ | `itemCode` | `?productCode={itemCode}` |
| ç”Ÿäº§æŠ¥å·¥ | `itemCode` | `?productCode={itemCode}` |
| å¾…报工台账 | `itemCode` | `?productCode={itemCode}` |
---
## å‰ç«¯ä¿®æ”¹ç‚¹
### 1. æŸ¥çœ‹å½’档按钮
在生产工单、任务、报工列表的操作列,以及详情页,新增"设计归档"按钮。
点击后弹出抽屉或弹窗,调用 `/mes/pd/archive/detail-by-product?productCode={code}` èŽ·å–å½’æ¡£è¯¦æƒ…ã€‚
### 2. å¼¹çª—内容展示
以 Tab æˆ–分区展示三部分内容:
| åŒºåŸŸ | å†…容 | æ•°æ®æ¥æº |
|------|------|----------|
| é¡¹ç›®ä¿¡æ¯ | ä»»åŠ¡ç¼–ç ã€ä»»åŠ¡åç§°ã€äº§å“ç¼–ç /名称、版本、主设计师、状态 | `response[].project` |
| å½’档记录 | è¡¨æ ¼ï¼šå½’档编号、归档人、归档状态、归档时间 | `response[].archives` |
| è®¾è®¡èµ„æ–™ | è¡¨æ ¼ï¼šèµ„料类型、名称、版本、文件名,附件可点击下载/预览 | `response[].documents` |
### 3. é™„件处理
设计资料中的 `attachmentList` ä¸ºé™„件列表,其中 `url` å¯ç›´æŽ¥ç”¨äºŽæ–‡ä»¶é¢„览/下载。
文件预览 URL æ ¼å¼ï¼š
- é¢„览:`/system/storage-blob/preview/{fileName}`
- ä¸‹è½½ï¼š`/system/storage-blob/download/{fileName}`
---
## ä¸šåŠ¡è§„åˆ™è¯´æ˜Ž
| è§„则 | è¯´æ˜Ž |
|------|------|
| äº§å“æœªå½’æ¡£ | æŽ¥å£è¿”回空数组,弹窗提示"该产品暂无设计归档" |
| å¤šä¸ªé¡¹ç›® | åŒä¸€äº§å“å¯èƒ½æœ‰å¤šä¸ªè®¾è®¡é¡¹ç›®ï¼ŒæŒ‰é¡¹ç›®åˆ†ç»„展示 |
| é™„件权限 | é™„件预览/下载走 system æ¨¡å— Storage API,无需额外鉴权 |
| ç©ºé™„ä»¶ | `attachmentList` å¯èƒ½ä¸ºç©ºæ•°ç»„,前端判断后不显示下载链接 |
---
## æ³¨æ„äº‹é¡¹
- åˆ—表页操作列宽度有限,建议按钮文字简写为"归档"
- `detail-by-product` æŽ¥å£è¿”回数组,一个产品可能对应多个设计项目
- é™„件预览使用 `window.open()` æ‰“开预览 URL
- æŽ¥å£å·²å­˜åœ¨ï¼Œå‰ç«¯ç›´æŽ¥è°ƒç”¨ `src/api/mes/pd/archive/index.ts` ä¸­çš„封装方法
docs/pro_task_calculate_duration.md
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,81 @@
# ç”Ÿäº§ä»»åŠ¡ - é€‰å·¥ä½œç«™è‡ªåŠ¨è®¡ç®—ç”Ÿäº§æ—¶é•¿ï¼ˆå‰ç«¯è”è°ƒæ–¹æ¡ˆï¼‰
## æ¶‰åŠé¡µé¢
| é¡µé¢ | è·¯ç”±è·¯å¾„ | è¯´æ˜Ž |
|------|----------|------|
| ç”Ÿäº§ä»»åŠ¡è¡¨å• | `/mes/pro-task` (新增/编辑弹窗) | é€‰æ‹©å·¥ä½œç«™åŽè‡ªåŠ¨è°ƒç”¨æŽ¥å£è®¡ç®—ç”Ÿäº§æ—¶é•¿ |
---
## API
### æ–°å¢žæŽ¥å£ï¼šè®¡ç®—生产时长
| æ–¹æ³• | è·¯å¾„ | è¯´æ˜Ž |
|------|------|------|
| GET | `/mes/pro/task/calculate-duration` | æ ¹æ®å·¥ä½œç«™å’Œæ•°é‡è®¡ç®—生产时长 |
**请求参数:**
| å‚æ•° | ç±»åž‹ | å¿…å¡« | è¯´æ˜Ž |
|------|------|------|------|
| workstationId | Long | æ˜¯ | å·¥ä½œç«™ç¼–号 |
| quantity | BigDecimal | æ˜¯ | æŽ’产数量 |
**响应示例:**
```json
{
  "code": 0,
  "data": {
    "duration": 3
  },
  "msg": ""
}
```
| å­—段 | ç±»åž‹ | è¯´æ˜Ž |
|------|------|------|
| duration | Integer | ç”Ÿäº§æ—¶é•¿ï¼ˆå°æ—¶ï¼‰ï¼Œæ— ç»‘定设备时返回 0 |
---
## å‰ç«¯ä¿®æ”¹ç‚¹
### 1. è§¦å‘时机
在新增/编辑生产任务的表单中,当用户**选择工作站**或**修改排产数量**后,自动调用计算接口。
### 2. å­—段回填
接口返回的 `duration` å€¼è‡ªåŠ¨å¡«å…¥è¡¨å•çš„"生产时长"字段,无需用户手动计算。
### 3. è¾¹ç•Œæƒ…况
| åœºæ™¯ | è¡¨çް |
|------|------|
| æœªé€‰å·¥ä½œç«™ | ä¸è°ƒç”¨æŽ¥å£ |
| æœªå¡«æ•°é‡ | ä¸è°ƒç”¨æŽ¥å£ |
| å·¥ä½œç«™æœªç»‘定设备 | è¿”回 `duration=0`,前端可提示"该工作站未绑定设备" |
| è®¾å¤‡æœªé…ç½®ç”Ÿäº§æ•ˆçއ | è¿”回 `duration=0`,前端可提示"绑定设备未配置生产效率" |
---
## è®¡ç®—逻辑说明
| æ­¥éª¤ | è¯´æ˜Ž |
|------|------|
| 1 | æŸ¥è¯¢å·¥ä½œç«™ç»‘定的所有设备 |
| 2 | æ€»æ•ˆçއ = Î£(每台设备的 `productionEfficiency` Ã— `conveyorBelt`) |
| 3 | ä¼ é€å±¥å¸¦ä¸º 0 æˆ–空时默认取 1 |
| 4 | ç”Ÿäº§æ—¶é•¿ï¼ˆå°æ—¶ï¼‰= å‘上取整(排产数量 / æ€»æ•ˆçއ) |
---
## æ³¨æ„äº‹é¡¹
- è°ƒç”¨æŽ¥å£å‰éœ€ç¡®ä¿ `workstationId` å’Œ `quantity` å‡æœ‰å€¼ï¼Œé¿å…æ— æ•ˆè¯·æ±‚
- æŽ¥å£è¿”回 0 æ—¶ï¼Œå»ºè®®ç»™å‡ºå‹å¥½æç¤ºï¼Œè€Œéžé™é»˜
- ç”¨æˆ·ä»å¯æ‰‹åŠ¨ä¿®æ”¹è®¡ç®—åŽçš„ç”Ÿäº§æ—¶é•¿
- è¯¥æŽ¥å£ä»…用于前端辅助计算,不影响后端创建/更新任务的业务逻辑
sql/mysql/mes_pd_menu_init.sql
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
-- =============================================
-- MES PD äº§å“è®¾è®¡æ¨¡å—菜单初始化
-- åœ¨ MES ç³»ç»Ÿ(5100) ä¸‹æ–°å¢ž"产品设计"二级目录
-- è®¾è®¡é¡¹ç›®ã€è®¾è®¡å½’档两个页面
-- =============================================
-- ä¿®æ­£åŽŸæœ‰"产品设计"(6809) å‘½åä¸º"工艺设计",避免冲突(其内容为工艺设计:工序设置、工艺流程等)
UPDATE `system_menu` SET `name` = '工艺设计', `updater` = '1', `update_time` = NOW() WHERE `id` = 6809 AND `name` = '产品设计';
-- äº§å“è®¾è®¡ï¼ˆäºŒçº§ç›®å½•,放在 MES ç³»ç»Ÿä¸‹ï¼Œsort=25 ä½äºŽå·¥è‰ºè®¾è®¡ä¹‹åŽï¼‰
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES (602571, '产品设计', '', 1, 25, 5100, 'pd', 'ep:design', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
-- è®¾è®¡é¡¹ç›®ï¼ˆä¸‰çº§èœå•)
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES (602572, '设计项目', '', 2, 1, 602571, 'project', 'ep:document', 'mes/pd/project/index', 'MesPdProject', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
-- è®¾è®¡é¡¹ç›® - æŒ‰é’®æƒé™
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES
(602573, '设计项目查询', 'mes:pd-project:query', 3, 1, 602572, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602574, '设计项目创建', 'mes:pd-project:create', 3, 2, 602572, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602575, '设计项目更新', 'mes:pd-project:update', 3, 3, 602572, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602576, '设计项目删除', 'mes:pd-project:delete', 3, 4, 602572, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602577, '设计项目导出', 'mes:pd-project:export', 3, 5, 602572, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
-- è®¾è®¡å½’档(三级菜单)
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES (602578, '设计归档', '', 2, 2, 602571, 'archive', 'ep:folder', 'mes/pd/archive/index', 'MesPdArchive', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
-- è®¾è®¡å½’æ¡£ - æŒ‰é’®æƒé™
INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`)
VALUES
(602579, '设计归档查询', 'mes:pd-archive:query', 3, 1, 602578, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602580, '设计归档更新', 'mes:pd-archive:update', 3, 2, 602578, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602581, '设计归档删除', 'mes:pd-archive:delete', 3, 3, 602578, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0'),
(602582, '设计归档导出', 'mes:pd-archive:export', 3, 4, 602578, '', '', '', '', 0, b'1', b'1', b'1', '1', NOW(), '1', NOW(), b'0');
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java
@@ -51,7 +51,11 @@
    default PageResult<CrmCustomerDO> selectPage(CrmCustomerPageReqVO pageReqVO, Long ownerUserId) {
        MPJLambdaWrapperX<CrmCustomerDO> query = new MPJLambdaWrapperX<>();
        // æ‹¼æŽ¥æ•°æ®æƒé™çš„æŸ¥è¯¢æ¡ä»¶
        if (Boolean.TRUE.equals(pageReqVO.getPool())) {
        if (CrmSceneTypeEnum.isAll(pageReqVO.getSceneType())) {
            // åœºæ™¯å››ï¼šå…¨éƒ¨æ•°æ®ï¼Œä¸åŒºåˆ†å…¬æµ·/非公海,由 appendPermissionCondition ç»Ÿä¸€å¤„理
            CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
                    CrmCustomerDO::getId, ownerUserId, pageReqVO.getSceneType());
        } else if (Boolean.TRUE.equals(pageReqVO.getPool())) {
            query.isNull(CrmCustomerDO::getOwnerUserId);
        } else {
            CrmPermissionUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(),
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/enums/common/CrmSceneTypeEnum.java
@@ -18,7 +18,8 @@
    OWNER(1, "我负责的"),
    INVOLVED(2, "我参与的"),
    SUBORDINATE(3, "下属负责的");
    SUBORDINATE(3, "下属负责的"),
    ALL(4, "全部");
    public static final Integer[] ARRAYS = Arrays.stream(values()).map(CrmSceneTypeEnum::getType).toArray(Integer[]::new);
@@ -43,6 +44,10 @@
        return ObjUtil.equal(SUBORDINATE.getType(), type);
    }
    public static boolean isAll(Integer type) {
        return ObjUtil.equal(ALL.getType(), type);
    }
    @Override
    public Integer[] array() {
        return ARRAYS;
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java
@@ -37,6 +37,16 @@
    }
    /**
     * æ ¡éªŒç”¨æˆ·æ˜¯å¦æœ‰æŸ¥çœ‹å…¨éƒ¨å®¢æˆ·çš„æƒé™
     *
     * @return æ˜¯/否
     */
    private static boolean hasCustomerViewAllPermission() {
        PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class);
        return permissionApi.hasAnyPermissions(getLoginUserId(), "crm:customer:view-all");
    }
    /**
     * æž„造 CRM æ•°æ®ç±»åž‹æ•°æ®ã€åˆ†é¡µã€‘查询条件
     *
     * @param query     è¿žè¡¨æŸ¥è¯¢å¯¹è±¡
@@ -79,6 +89,14 @@
                query.in(ownerUserIdField, convertSet(subordinateUsers, AdminUserRespDTO::getId));
            }
        }
        // åœºæ™¯å››ï¼šå…¨éƒ¨æ•°æ®ï¼ˆéœ€è¦æœ‰ view-all æƒé™æˆ– CRM ç®¡ç†å‘˜ï¼‰
        if (CrmSceneTypeEnum.isAll(sceneType)) {
            if (isCrmAdmin() || hasCustomerViewAllPermission()) {
                return; // è·³è¿‡è¿‡æ»¤ï¼ŒæŸ¥çœ‹å…¨éƒ¨
            }
            // æ— æƒé™åˆ™é™çº§ä¸º"我负责的"
            query.eq(ownerUserIdField, userId);
        }
    }
    /**
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/MesDvMachineryController.java
@@ -52,6 +52,8 @@
    private MesDvMachineryTypeService machineryTypeService;
    @Resource
    private MesMdWorkshopService workshopService;
    @Resource
    private cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService workstationService;
    @PostMapping("/create")
    @Operation(summary = "创建设备")
@@ -151,17 +153,21 @@
        if (CollUtil.isEmpty(list)) {
            return Collections.emptyList();
        }
        // 1. æ‰¹é‡èŽ·å–è®¾å¤‡ç±»åž‹å’Œè½¦é—´ä¿¡æ¯
        // 1. æ‰¹é‡èŽ·å–è®¾å¤‡ç±»åž‹ã€è½¦é—´å’Œå·¥ä½œç«™ä¿¡æ¯
        Map<Long, MesDvMachineryTypeDO> machineryTypeMap = machineryTypeService.getMachineryTypeMap(
                convertSet(list, MesDvMachineryDO::getMachineryTypeId));
        Map<Long, MesMdWorkshopDO> workshopMap = workshopService.getWorkshopMap(
                convertSet(list, MesDvMachineryDO::getWorkshopId));
        Map<Long, cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO> workstationMap =
                workstationService.getWorkstationMap(convertSet(list, MesDvMachineryDO::getWorkstationId));
        // 2. æ‹¼æŽ¥ VO
        return BeanUtils.toBean(list, MesDvMachineryRespVO.class, vo -> {
            MapUtils.findAndThen(machineryTypeMap, vo.getMachineryTypeId(),
                    machineryType -> vo.setMachineryTypeName(machineryType.getName()));
            MapUtils.findAndThen(workshopMap, vo.getWorkshopId(),
                    workshop -> vo.setWorkshopName(workshop.getName()));
            MapUtils.findAndThen(workstationMap, vo.getWorkstationId(),
                    workstation -> vo.setWorkstationName(workstation.getName()));
        });
    }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java
@@ -43,4 +43,13 @@
    @ExcelProperty("备注")
    private String remark;
    @ExcelProperty("生产效率(每小时)")
    private java.math.BigDecimal productionEfficiency;
    @ExcelProperty("传送履带")
    private Integer conveyorBelt;
    @ExcelProperty("工作站编码")
    private String workstationCode;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryPageReqVO.java
@@ -35,4 +35,7 @@
    @Schema(description = "设备状态", example = "1")
    private Integer status;
    @Schema(description = "工作站编号", example = "300")
    private Long workstationId;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java
@@ -66,6 +66,21 @@
    @ExcelProperty("备注")
    private String remark;
    @Schema(description = "生产效率(每小时)", example = "10.5")
    @ExcelProperty("生产效率(每小时)")
    private java.math.BigDecimal productionEfficiency;
    @Schema(description = "传送履带(2=双倍效率)", example = "2")
    @ExcelProperty("传送履带")
    private Integer conveyorBelt;
    @Schema(description = "工作站编号", example = "300")
    private Long workstationId;
    @Schema(description = "工作站名称", example = "一号工作站")
    @ExcelProperty("工作站")
    private String workstationName;
    @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
    @ExcelProperty("创建时间")
    private LocalDateTime createTime;
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachinerySaveReqVO.java
@@ -49,4 +49,13 @@
    @Schema(description = "备注", example = "备注")
    private String remark;
    @Schema(description = "生产效率(每小时)", example = "10.5")
    private java.math.BigDecimal productionEfficiency;
    @Schema(description = "传送履带(2=双倍效率)", example = "2")
    private Integer conveyorBelt;
    @Schema(description = "工作站编号", example = "300")
    private Long workstationId;
    }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pd/documentaudit/vo/MesPdDocumentAuditPageReqVO.java
@@ -21,4 +21,7 @@
    @Schema(description = "审核状态", example = "0")
    private Integer auditStatus;
    @Schema(description = "项目ID", example = "1")
    private Long projectId;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/task/MesProTaskController.java
@@ -34,6 +34,7 @@
import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Parameters;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
@@ -98,6 +99,20 @@
        return success(true);
    }
    @GetMapping("/calculate-duration")
    @Operation(summary = "计算生产时长", description = "根据工作站绑定设备的生产效率和传送履带,自动计算生产时长(小时)")
    @Parameters({
            @Parameter(name = "workstationId", description = "工作站编号", required = true),
            @Parameter(name = "quantity", description = "排产数量", required = true)
    })
    @PreAuthorize("@ss.hasPermission('mes:pro-task:query')")
    public CommonResult<java.util.Map<String, Object>> calculateDuration(
            @RequestParam("workstationId") Long workstationId,
            @RequestParam("quantity") BigDecimal quantity) {
        Integer duration = taskService.calculateDuration(workstationId, quantity);
        return success(java.util.Map.of("duration", duration));
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除生产任务")
    @Parameter(name = "id", description = "编号", required = true)
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/dataobject/dv/machinery/MesDvMachineryDO.java
@@ -76,5 +76,19 @@
     * å¤‡æ³¨
     */
    private String remark;
    /**
     * ç”Ÿäº§æ•ˆçŽ‡ï¼ˆæ¯å°æ—¶ï¼‰
     */
    private java.math.BigDecimal productionEfficiency;
    /**
     * ä¼ é€å±¥å¸¦ï¼ˆ2=双倍效率)
     */
    private Integer conveyorBelt;
    /**
     * å·¥ä½œç«™ç¼–号
     *
     * å…³è” {@link cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO#getId()}
     */
    private Long workstationId;
}
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/dv/machinery/MesDvMachineryMapper.java
@@ -24,6 +24,7 @@
                .eqIfPresent(MesDvMachineryDO::getMachineryTypeId, reqVO.getMachineryTypeId())
                .inIfPresent(MesDvMachineryDO::getMachineryTypeId, reqVO.getMachineryTypeIds())
                .eqIfPresent(MesDvMachineryDO::getWorkshopId, reqVO.getWorkshopId())
                .eqIfPresent(MesDvMachineryDO::getWorkstationId, reqVO.getWorkstationId())
                .eqIfPresent(MesDvMachineryDO::getStatus, reqVO.getStatus())
                .orderByDesc(MesDvMachineryDO::getId));
    }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/pd/documentaudit/MesPdDocumentAuditMapper.java
@@ -21,6 +21,16 @@
                .orderByDesc(MesPdDocumentAuditDO::getId));
    }
    default PageResult<MesPdDocumentAuditDO> selectPage(MesPdDocumentAuditPageReqVO reqVO,
                                                         Collection<Long> documentIds) {
        return selectPage(reqVO, new LambdaQueryWrapperX<MesPdDocumentAuditDO>()
                .eqIfPresent(MesPdDocumentAuditDO::getDocumentId, reqVO.getDocumentId())
                .likeIfPresent(MesPdDocumentAuditDO::getAuditNo, reqVO.getAuditNo())
                .eqIfPresent(MesPdDocumentAuditDO::getAuditStatus, reqVO.getAuditStatus())
                .inIfPresent(MesPdDocumentAuditDO::getDocumentId, documentIds)
                .orderByDesc(MesPdDocumentAuditDO::getId));
    }
    default List<MesPdDocumentAuditDO> selectListByDocumentId(Long documentId) {
        return selectList(MesPdDocumentAuditDO::getDocumentId, documentId);
    }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java
@@ -169,6 +169,7 @@
    ErrorCode DV_MACHINERY_HAS_CHECK_RECORD = new ErrorCode(1_040_301_004, "设备已关联点检记录,无法删除");
    ErrorCode DV_MACHINERY_HAS_MAINTEN_RECORD = new ErrorCode(1_040_301_005, "设备已关联保养记录,无法删除");
    ErrorCode DV_MACHINERY_HAS_REPAIR = new ErrorCode(1_040_301_006, "设备已关联维修工单,无法删除");
    ErrorCode DV_MACHINERY_WORKSTATION_NOT_EXISTS = new ErrorCode(1_040_301_008, "工作站编码不存在");
    // ========== MES è®¾å¤‡ç®¡ç†-点检保养项目(1-040-304-000) ==========
    ErrorCode DV_SUBJECT_NOT_EXISTS = new ErrorCode(1_040_304_000, "点检保养项目不存在");
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/dv/machinery/MesDvMachineryServiceImpl.java
@@ -54,6 +54,9 @@
    @Lazy
    private MesMdWorkshopService workshopService;
    @Resource
    @Lazy
    private cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService workstationService;
    @Resource
    private MesWmBarcodeService barcodeService;
    @Resource
    @Lazy
@@ -201,7 +204,7 @@
            throw exception(DV_MACHINERY_IMPORT_LIST_IS_EMPTY);
        }
        // 2. æ‰¹é‡åŠ è½½è®¾å¤‡ç±»åž‹å’Œè½¦é—´ï¼Œæž„å»ºç¼–ç åˆ°å®žä½“çš„æ˜ å°„
        // 2. æ‰¹é‡åŠ è½½è®¾å¤‡ç±»åž‹ã€è½¦é—´å’Œå·¥ä½œç«™ï¼Œæž„å»ºç¼–ç åˆ°å®žä½“çš„æ˜ å°„
        List<MesDvMachineryTypeDO> allTypes = machineryTypeService.getMachineryTypeList(
                new cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type.MesDvMachineryTypeListReqVO());
        Map<String, MesDvMachineryTypeDO> typeCodeMap = allTypes.stream()
@@ -210,6 +213,13 @@
                cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus());
        Map<String, MesMdWorkshopDO> workshopCodeMap = allWorkshops.stream()
                .collect(Collectors.toMap(MesMdWorkshopDO::getCode, w -> w, (a, b) -> a));
        List<cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO> allWorkstations =
                workstationService.getWorkstationListByStatus(
                        cn.iocoder.yudao.framework.common.enums.CommonStatusEnum.ENABLE.getStatus());
        Map<String, cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO> workstationCodeMap =
                allWorkstations.stream().collect(Collectors.toMap(
                        cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO::getCode,
                        w -> w, (a, b) -> a));
        // 3. éåŽ†ï¼Œé€ä¸ªåˆ›å»º or æ›´æ–°
        MesDvMachineryImportRespVO respVO = MesDvMachineryImportRespVO.builder()
@@ -249,24 +259,38 @@
                return;
            }
            // 3.4 åˆ¤æ–­ï¼šåˆ›å»º or æ›´æ–°
            // 3.4 æ ¡éªŒå·¥ä½œç«™ç¼–码(可选)
            Long workstationId = null;
            if (StrUtil.isNotBlank(importItem.getWorkstationCode())) {
                cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationDO workstation =
                        workstationCodeMap.get(importItem.getWorkstationCode());
                if (workstation == null) {
                    respVO.getFailureCodes().put(key, "工作站编码[" + importItem.getWorkstationCode() + "]不存在");
                    return;
                }
                workstationId = workstation.getId();
            }
            // 3.5 åˆ¤æ–­ï¼šåˆ›å»º or æ›´æ–°
            MesDvMachineryDO existMachinery = machineryMapper.selectByCode(importItem.getCode());
            if (existMachinery == null) {
                // 3.4.1 åˆ›å»º
                // 3.5.1 åˆ›å»º
                MesDvMachineryDO machinery = BeanUtils.toBean(importItem, MesDvMachineryDO.class);
                machinery.setMachineryTypeId(machineryType.getId());
                machinery.setWorkshopId(workshop.getId());
                machinery.setWorkstationId(workstationId);
                machineryMapper.insert(machinery);
                // è‡ªåŠ¨ç”Ÿæˆæ¡ç 
                barcodeService.autoGenerateBarcode(BarcodeBizTypeEnum.MACHINERY.getValue(),
                        machinery.getId(), machinery.getCode(), machinery.getName());
                respVO.getCreateCodes().add(importItem.getCode());
            } else if (updateSupport) {
                // 3.4.2 æ›´æ–°
                // 3.5.2 æ›´æ–°
                MesDvMachineryDO updateObj = BeanUtils.toBean(importItem, MesDvMachineryDO.class);
                updateObj.setId(existMachinery.getId());
                updateObj.setMachineryTypeId(machineryType.getId());
                updateObj.setWorkshopId(workshop.getId());
                updateObj.setWorkstationId(workstationId);
                machineryMapper.updateById(updateObj);
                respVO.getUpdateCodes().add(importItem.getCode());
            } else {
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pd/documentaudit/MesPdDocumentAuditServiceImpl.java
@@ -4,7 +4,9 @@
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.mes.controller.admin.pd.documentaudit.vo.MesPdDocumentAuditPageReqVO;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.mes.controller.admin.pd.documentaudit.vo.MesPdDocumentAuditSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pd.document.MesPdDocumentDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pd.documentaudit.MesPdDocumentAuditDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pd.documentaudit.MesPdDocumentAuditMapper;
import cn.iocoder.yudao.module.mes.service.pd.document.MesPdDocumentService;
@@ -14,7 +16,9 @@
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PD_DOCUMENT_AUDIT_NOT_EXISTS;
@@ -72,6 +76,17 @@
    @Override
    public PageResult<MesPdDocumentAuditDO> getDocumentAuditPage(MesPdDocumentAuditPageReqVO pageReqVO) {
        // æŒ‰é¡¹ç›®ç­›é€‰ï¼šå…ˆæŸ¥å‡ºé¡¹ç›®ä¸‹æ‰€æœ‰èµ„料,再按资料 ID è¿‡æ»¤å®¡æ ¸è®°å½•
        if (pageReqVO.getProjectId() != null) {
            List<MesPdDocumentDO> documents = documentService.getDocumentListByProjectId(
                    pageReqVO.getProjectId());
            if (CollUtil.isEmpty(documents)) {
                return PageResult.empty();
            }
            List<Long> documentIds = documents.stream()
                    .map(MesPdDocumentDO::getId).collect(Collectors.toList());
            return documentAuditMapper.selectPage(pageReqVO, documentIds);
        }
        return documentAuditMapper.selectPage(pageReqVO);
    }
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskService.java
@@ -123,6 +123,15 @@
    void cancelTaskByOrderId(Long workOrderId);
    /**
     * æ ¹æ®å·¥ä½œç«™ç»‘定设备的生产效率和传送履带,计算生产时长(单位:小时)
     *
     * @param workstationId å·¥ä½œç«™ç¼–号
     * @param quantity      æŽ’产数量
     * @return ç”Ÿäº§æ—¶é•¿ï¼ˆå°æ—¶ï¼‰ï¼Œæ— è®¾å¤‡åˆ™è¿”回 0
     */
    Integer calculateDuration(Long workstationId, BigDecimal quantity);
    /**
     * ç´¯åŠ ä»»åŠ¡çš„å·²ç”Ÿäº§ã€åˆæ ¼ã€ä¸åˆæ ¼æ•°é‡
     *
     * @param id                    ä»»åŠ¡ç¼–å·
yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/pro/task/MesProTaskServiceImpl.java
@@ -7,17 +7,21 @@
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskAutoGenerateReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskPageReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.pro.task.vo.MesProTaskSaveReqVO;
import cn.iocoder.yudao.module.mes.dal.dataobject.dv.machinery.MesDvMachineryDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.unitmeasure.MesMdUnitMeasureDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.md.workstation.MesMdWorkstationMachineDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.task.MesProTaskDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.task.MesProTaskMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper;
import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum;
import cn.iocoder.yudao.module.mes.enums.pro.MesProTaskStatusEnum;
import cn.iocoder.yudao.module.mes.service.dv.machinery.MesDvMachineryService;
import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService;
import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService;
import cn.iocoder.yudao.module.mes.service.md.unitmeasure.MesMdUnitMeasureService;
import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationMachineService;
import cn.iocoder.yudao.module.mes.service.md.workstation.MesMdWorkstationService;
import cn.iocoder.yudao.module.mes.service.pro.process.MesProProcessService;
import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO;
@@ -40,9 +44,11 @@
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_ALREADY_FINISHED;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_HAS_FEEDBACK;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.PRO_TASK_NOT_EXISTS;
@@ -86,6 +92,11 @@
    private MesProWorkOrderProcessService workOrderProcessService;
    @Resource
    private MesMdAutoCodeRecordService autoCodeRecordService;
    @Resource
    private MesMdWorkstationMachineService workstationMachineService;
    @Resource
    @Lazy
    private MesDvMachineryService machineryService;
    @Override
    public Long createTask(MesProTaskSaveReqVO createReqVO) {
@@ -318,6 +329,33 @@
    }
    @Override
    public Integer calculateDuration(Long workstationId, BigDecimal quantity) {
        if (quantity == null || quantity.compareTo(BigDecimal.ZERO) <= 0) {
            return 0;
        }
        // 1. æŸ¥è¯¢å·¥ä½œç«™ç»‘定的设备
        List<MesMdWorkstationMachineDO> machines = workstationMachineService
                .getWorkstationMachineListByWorkstationId(workstationId);
        if (CollUtil.isEmpty(machines)) {
            return 0;
        }
        // 2. èŽ·å–è®¾å¤‡è¯¦æƒ…ï¼Œè®¡ç®—æ€»æ•ˆçŽ‡
        Set<Long> machineryIds = convertSet(machines, MesMdWorkstationMachineDO::getMachineryId);
        List<MesDvMachineryDO> machineryList = machineryService.getMachineryList(machineryIds);
        BigDecimal totalEfficiency = BigDecimal.ZERO;
        for (MesDvMachineryDO m : machineryList) {
            BigDecimal efficiency = m.getProductionEfficiency() != null ? m.getProductionEfficiency() : BigDecimal.ZERO;
            Integer belt = m.getConveyorBelt() != null && m.getConveyorBelt() > 0 ? m.getConveyorBelt() : 1;
            totalEfficiency = totalEfficiency.add(efficiency.multiply(BigDecimal.valueOf(belt)));
        }
        if (totalEfficiency.compareTo(BigDecimal.ZERO) <= 0) {
            return 0;
        }
        // 3. ç”Ÿäº§æ—¶é•¿ï¼ˆå°æ—¶ï¼‰ = ceil(排产数量 / æ€»æ•ˆçއ),效率单位为每小时产量
        return quantity.divide(totalEfficiency, 0, java.math.RoundingMode.CEILING).intValue();
    }
    @Override
    public MesProTaskAutoGeneratePreviewRespVO previewAutoGenerate(MesProTaskAutoGenerateReqVO reqVO) {
        // 1. æ ¡éªŒå·¥å•已确认
        MesProWorkOrderDO workOrder = workOrderService.validateWorkOrderConfirmed(reqVO.getWorkOrderId());
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/SrmBidAwardController.java
@@ -3,6 +3,7 @@
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.srm.controller.admin.tender.vo.*;
import cn.iocoder.yudao.module.srm.dal.dataobject.SrmBidAwardDO;
import cn.iocoder.yudao.module.srm.service.tender.SrmBidAwardService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
@@ -42,7 +43,20 @@
    @Operation(summary = "根据招标项目ID获取定标详情")
    @PreAuthorize("@ss.hasPermission('srm:bid-award:query')")
    public CommonResult<SrmBidAwardRespVO> getAwardByProject(@RequestParam("tenderProjectId") Long tenderProjectId) {
        return success(BeanUtils.toBean(bidAwardService.getAwardByProjectId(tenderProjectId), SrmBidAwardRespVO.class));
        SrmBidAwardDO award = bidAwardService.getAwardByProjectId(tenderProjectId);
        if (award == null) {
            return success((SrmBidAwardRespVO) null);
        }
        return success(BeanUtils.toBean(award, SrmBidAwardRespVO.class));
    }
    @DeleteMapping("/delete")
    @Operation(summary = "删除定标")
    @Parameter(name = "id", description = "定标ID", required = true)
    @PreAuthorize("@ss.hasPermission('srm:bid-award:update')")
    public CommonResult<Boolean> deleteAward(@RequestParam("id") Long id) {
        bidAwardService.deleteAward(id);
        return success(true);
    }
    @PutMapping("/approve")
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/SrmBidEvaluationController.java
@@ -40,6 +40,14 @@
        return success(bidEvaluationService.createEvaluation(createReqVO));
    }
    @PutMapping("/update")
    @Operation(summary = "更新评标记录")
    @PreAuthorize("@ss.hasPermission('srm:bid-evaluation:update')")
    public CommonResult<Boolean> updateEvaluation(@Valid @RequestBody SrmBidEvaluationSaveReqVO updateReqVO) {
        bidEvaluationService.updateEvaluation(updateReqVO);
        return success(true);
    }
    @GetMapping("/list-by-project")
    @Operation(summary = "按招标项目获取评标列表")
    @PreAuthorize("@ss.hasPermission('srm:bid-evaluation:query')")
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/SrmTenderBidController.java
@@ -111,6 +111,7 @@
            if (material != null) {
                vo.setTenderMaterialCode(material.getProductCode());
                vo.setTenderMaterialName(material.getProductName());
                vo.setMaterialName(material.getProductName());
                vo.setTenderMaterialSpec(material.getProductSpec());
                vo.setTenderMaterialUnit(material.getUnit());
            }
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/controller/admin/tender/vo/SrmSupplierQuoteRespVO.java
@@ -31,6 +31,9 @@
    @Schema(description = "物料名称")
    private String tenderMaterialName;
    @Schema(description = "物料名称(与前端 materialName å¯¹åº”)")
    private String materialName;
    @Schema(description = "物料规格")
    private String tenderMaterialSpec;
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/dal/mysql/SrmTenderBidMapper.java
@@ -21,4 +21,9 @@
                .eq(SrmTenderBidDO::getSupplierId, supplierId));
    }
    default boolean existsByBidNo(String bidNo) {
        return exists(new LambdaQueryWrapperX<SrmTenderBidDO>()
                .eq(SrmTenderBidDO::getBidNo, bidNo));
    }
}
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/enums/ErrorCodeConstants.java
@@ -37,6 +37,7 @@
    ErrorCode TENDER_STATUS_ALREADY_CLOSED = new ErrorCode(1_040_500_010, "已关闭的项目不允许操作");
    ErrorCode BID_NOT_EXISTS = new ErrorCode(1_040_500_003, "投标记录不存在");
    ErrorCode BID_SUPPLIER_EXISTS = new ErrorCode(1_040_500_004, "供应商已参与投标");
    ErrorCode BID_NO_EXISTS = new ErrorCode(1_040_500_016, "投标编号已存在");
    ErrorCode BID_PAST_END_TIME = new ErrorCode(1_040_500_005, "投标已截止");
    ErrorCode BID_SUPPLIER_NOT_APPROVED = new ErrorCode(1_040_500_011, "供应商未通过准入审批,无法参与投标");
    ErrorCode BID_WITHDRAWN_CANNOT_QUOTE = new ErrorCode(1_040_500_012, "投标已撤标,不允许报价");
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/supplier/SrmSupplierServiceImpl.java
@@ -14,7 +14,9 @@
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import cn.hutool.core.collection.CollUtil;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@Service
@@ -79,6 +81,9 @@
    @Override
    public List<SrmSupplierDO> getSupplierList(Collection<Long> ids) {
        if (CollUtil.isEmpty(ids)) {
            return Collections.emptyList();
        }
        return supplierMapper.selectBatchIds(ids);
    }
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardService.java
@@ -25,6 +25,11 @@
    SrmBidAwardDO getAwardByProjectId(Long tenderProjectId);
    /**
     * åˆ é™¤å®šæ ‡
     */
    void deleteAward(Long id);
    /**
     * å®¡æ‰¹å®šæ ‡
     */
    void approveAward(Long id);
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidAwardServiceImpl.java
@@ -15,10 +15,12 @@
import cn.iocoder.yudao.module.srm.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.srm.enums.TenderStatusEnum;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
@@ -29,6 +31,7 @@
 */
@Service
@Validated
@Slf4j
public class SrmBidAwardServiceImpl implements SrmBidAwardService {
    @Resource
@@ -86,6 +89,13 @@
    @Override
    public SrmBidAwardDO getAwardByProjectId(Long tenderProjectId) {
        return bidAwardMapper.selectByTenderProjectId(tenderProjectId);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAward(Long id) {
        SrmBidAwardDO award = validateAwardExists(id);
        bidAwardMapper.deleteById(id);
    }
    @Override
@@ -169,15 +179,33 @@
        ErpPurchaseOrderCreateReqDTO createReq = new ErpPurchaseOrderCreateReqDTO();
        createReq.setSupplierId(srmSupplier.getId());
        createReq.setOrderTime(LocalDateTime.now());
        createReq.setDepositPrice(BigDecimal.ZERO);
        createReq.setItems(orderItems);
        createReq.setRemark("SRM å®šæ ‡è‡ªåŠ¨ç”Ÿæˆ, å®šæ ‡ç¼–号: " + award.getAwardNo());
        Long purchaseOrderId = erpPurchaseOrderApi.createPurchaseOrder(createReq).getCheckedData();
        // èŽ·å–é‡‡è´­è®¢å•å·
        String purchaseOrderNo = null;
        try {
            purchaseOrderNo = erpPurchaseOrderApi.getPurchaseOrder(purchaseOrderId)
                    .getCheckedData().getNo();
        } catch (Exception e) {
            log.warn("[generatePurchaseOrder] èŽ·å–é‡‡è´­è®¢å•å·å¤±è´¥ï¼ŒpurchaseOrderId={}", purchaseOrderId, e);
        }
        // 8. æ›´æ–°å®šæ ‡è®°å½•
        award.setPurchaseOrderId(purchaseOrderId);
        award.setPurchaseOrderNo(purchaseOrderNo);
        award.setAwardStatus(AwardStatusEnum.ORDER_GENERATED.getCode());
        bidAwardMapper.updateById(award);
        // 9. æ›´æ–°æ‹›æ ‡é¡¹ç›®çŠ¶æ€
        SrmTenderProjectDO project = tenderProjectMapper.selectById(award.getTenderProjectId());
        if (project != null) {
            project.setTenderStatus(TenderStatusEnum.CLOSED.getCode());
            tenderProjectMapper.updateById(project);
        }
    }
    private SrmBidAwardDO validateAwardExists(Long id) {
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidEvaluationService.java
@@ -20,6 +20,11 @@
    Long createEvaluation(@Valid SrmBidEvaluationSaveReqVO createReqVO);
    /**
     * æ›´æ–°è¯„标记录
     */
    void updateEvaluation(@Valid SrmBidEvaluationSaveReqVO updateReqVO);
    /**
     * èŽ·å–è¯„æ ‡åˆ—è¡¨ï¼ˆæŒ‰æ‹›æ ‡é¡¹ç›®ï¼‰
     */
    List<SrmBidEvaluationDO> getEvaluationList(Long tenderProjectId);
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmBidEvaluationServiceImpl.java
@@ -44,6 +44,8 @@
    @Transactional(rollbackFor = Exception.class)
    public Long createEvaluation(SrmBidEvaluationSaveReqVO createReqVO) {
        SrmBidEvaluationDO evaluation = BeanUtils.toBean(createReqVO, SrmBidEvaluationDO.class);
        // å¼ºåˆ¶ç½®ç©º id,避免前端传入已有 id å¯¼è‡´ä¸»é”®å†²çªï¼Œç”±æ•°æ®åº“序列自动生成
        evaluation.setId(null);
        // è®¡ç®—综合评分: ä»·æ ¼*0.4 + æŠ€æœ¯*0.3 + äº¤ä»˜*0.2 + æœåŠ¡*0.1
        BigDecimal price = nvl(evaluation.getPriceScore());
        BigDecimal tech = nvl(evaluation.getTechScore());
@@ -67,6 +69,28 @@
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateEvaluation(SrmBidEvaluationSaveReqVO updateReqVO) {
        SrmBidEvaluationDO existing = bidEvaluationMapper.selectById(updateReqVO.getId());
        if (existing == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.EVALUATION_NOT_EXISTS_TENDER);
        }
        SrmBidEvaluationDO evaluation = BeanUtils.toBean(updateReqVO, SrmBidEvaluationDO.class);
        BigDecimal price = nvl(evaluation.getPriceScore());
        BigDecimal tech = nvl(evaluation.getTechScore());
        BigDecimal delivery = nvl(evaluation.getDeliveryScore());
        BigDecimal service = nvl(evaluation.getServiceScore());
        BigDecimal composite = price.multiply(new BigDecimal("0.4"))
                .add(tech.multiply(new BigDecimal("0.3")))
                .add(delivery.multiply(new BigDecimal("0.2")))
                .add(service.multiply(new BigDecimal("0.1")))
                .setScale(2, RoundingMode.HALF_UP);
        evaluation.setCompositeScore(composite);
        evaluation.setEvaluationTime(LocalDateTime.now());
        bidEvaluationMapper.updateById(evaluation);
    }
    @Override
    public List<SrmBidEvaluationDO> getEvaluationList(Long tenderProjectId) {
        return bidEvaluationMapper.selectListByTenderProjectId(tenderProjectId);
    }
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmTenderBidServiceImpl.java
@@ -51,6 +51,10 @@
        if (!supplierApplyMapper.existsApprovedBySupplierId(createReqVO.getSupplierId())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_SUPPLIER_NOT_APPROVED);
        }
        // æ ¡éªŒæŠ•标编号是否重复
        if (tenderBidMapper.existsByBidNo(createReqVO.getBidNo())) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.BID_NO_EXISTS);
        }
        // æ ¡éªŒä¾›åº”商是否已参与投标
        SrmTenderBidDO existing = tenderBidMapper.selectByTenderAndSupplier(createReqVO.getTenderProjectId(), createReqVO.getSupplierId());
        if (existing != null) {
yudao-module-srm/src/main/java/cn/iocoder/yudao/module/srm/service/tender/SrmTenderProjectServiceImpl.java
@@ -11,6 +11,7 @@
import cn.iocoder.yudao.module.srm.dal.mysql.SrmBidAwardMapper;
import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderMaterialMapper;
import cn.iocoder.yudao.module.srm.dal.mysql.SrmTenderProjectMapper;
import cn.iocoder.yudao.module.srm.enums.AwardStatusEnum;
import cn.iocoder.yudao.module.srm.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.srm.enums.TenderStatusEnum;
import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
@@ -64,7 +65,15 @@
    @Override
    public SrmTenderProjectDO getTenderProject(Long id) {
        return tenderProjectMapper.selectById(id);
        SrmTenderProjectDO project = tenderProjectMapper.selectById(id);
        if (project != null) {
            SrmBidAwardDO award = bidAwardMapper.selectByTenderProjectId(id);
            if (award != null) {
                project.setAwardId(award.getId());
                project.setPurchaseOrderNo(award.getPurchaseOrderNo());
            }
        }
        return project;
    }
    @Override
@@ -82,6 +91,10 @@
                if (award != null) {
                    project.setAwardId(award.getId());
                    project.setPurchaseOrderNo(award.getPurchaseOrderNo());
                    // é˜²å¾¡ï¼šå¦‚果定标已生成订单但项目状态未更新,同步状态
                    if (AwardStatusEnum.ORDER_GENERATED.getCode().equals(award.getAwardStatus())) {
                        project.setTenderStatus(TenderStatusEnum.CLOSED.getCode());
                    }
                }
            });
        }