岗位菜单权限与日报审核
This commit is contained in:
@@ -0,0 +1,75 @@
|
|||||||
|
# AGENTS.md
|
||||||
|
|
||||||
|
本文件面向 AI 编码代理,介绍本项目的架构、约定与开发方式。
|
||||||
|
|
||||||
|
## 项目概述
|
||||||
|
|
||||||
|
**SHJ_APP**(施工管理 App)是一个基于 **uni-app + Vue 3** 的跨端移动应用,服务于管道施工 / 焊接管理业务(点口管理、试压管理、包装管理、发货管理、预制组件管理、下料抽检、组对抽查、焊接日报、防腐处理等)。主要运行目标是**微信小程序**(`manifest.json` 中已配置 `mp-weixin` appid),同时兼容 H5 和 App(5+App)。
|
||||||
|
|
||||||
|
后端接口地址(见 `utils/request.js`):
|
||||||
|
|
||||||
|
- API:`https://lygcgs.com.cn:8078/shjapi/api/`
|
||||||
|
- 附件/文件:`https://lygcgs.com.cn:8078/shj/`
|
||||||
|
|
||||||
|
## 技术栈
|
||||||
|
|
||||||
|
- **框架**:uni-app(Vue 3,`manifest.json` 中 `vueVersion: "3"`)+ Vite
|
||||||
|
- **状态管理**:Pinia + `pinia-plugin-persist-uni`(状态持久化到本地存储)
|
||||||
|
- **UI 组件库**:uview-pro(`u-*` 组件通过 easycom 自动引入)。组件用法/props 参考本地文档副本 `docs/uview-pro-llms-full.txt`(原始地址 <https://uviewpro.cn/llms-full.txt>,可按 `url:` 分节检索,共 147 个组件/主题文档)
|
||||||
|
- **样式**:SCSS(全局样式在 `App.vue` 中引入;公共变量在 `uni.scss`,如 `$app-primary: #2979ff`)
|
||||||
|
- **条码**:bwip-js(`assets/js/js_sdk/`,微信小程序需要 `main.js` 顶部的 `atob` polyfill)
|
||||||
|
|
||||||
|
## 构建与运行
|
||||||
|
|
||||||
|
`package.json` 中**没有定义任何 scripts**,也没有 `vite.config.*`。本项目通常通过 **HBuilderX** 开发调试(运行 → 运行到小程序模拟器 → 微信开发者工具),构建产物输出到 `unpackage/`(已 gitignore)。
|
||||||
|
|
||||||
|
依赖安装:`pnpm install`(仓库同时存在 `pnpm-lock.yaml` 与 `package-lock.json`,以 pnpm 为主)。
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
|
```
|
||||||
|
pages/ 主包页面:login(登录)、index(首页)、mine(我的)、todo(待办)
|
||||||
|
pipe/ 分包(root: pipe):diankou 点口、pressure 试压、packaging 包装、
|
||||||
|
deliver 发货、precast 预制组件
|
||||||
|
scanpages/ 分包(root: scanpages):hj/ 扫码与焊接相关页面(材料详情、下料抽检、
|
||||||
|
组对抽查、焊接日报、防腐处理、日报审核)、components/nbd-print-prop.vue
|
||||||
|
components/ 全局公共组件,均为 nbd-* 前缀(easycom 自动注册)
|
||||||
|
api/ 接口层:auth.js / user.js / base.js / hj.js,按业务模块划分
|
||||||
|
store/ Pinia:index.js 入口,modules/ 下 user.js(登录态/项目)、
|
||||||
|
menu.js(菜单权限/快捷应用)、large.js(焊接首页数据)
|
||||||
|
utils/ request.js(请求封装)、scanUtils.js(扫码解析)、constant.js
|
||||||
|
(常量/默认应用配置)、formatTime.js、bwipjs-polyfill.js
|
||||||
|
assets/ css/(page.scss、components.scss 全局样式)、icon/(nbd-icon 图标)、js/
|
||||||
|
docs/ 参考文档(uview-pro-llms-full.txt 组件库文档副本)
|
||||||
|
static/ 图片与 tabBar 图标
|
||||||
|
pages.json 页面路由、分包、tabBar、easycom 配置(修改路由必须改这里)
|
||||||
|
manifest.json 应用配置(appid、微信小程序 appid、Android 权限等)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码约定
|
||||||
|
|
||||||
|
- 页面与组件统一使用 **Vue 3 `<script setup>` 组合式 API**;页面生命周期从 `@dcloudio/uni-app` 导入(`onLoad`、`onShow` 等),不要直接用 `onMounted` 代替页面级生命周期。
|
||||||
|
- **easycom 自动注册**(见 `pages.json`):
|
||||||
|
- `u-*` → uview-pro 组件
|
||||||
|
- `nbd-*` → `@/components/nbd-*.vue`(新增公共组件放到 `components/` 并遵循 `nbd-` 命名,无需手动 import)
|
||||||
|
- `nbd-print-prop` → `@/scanpages/components/nbd-print-prop.vue`
|
||||||
|
- 新页面必须在 `pages.json` 的 `pages` 或对应 `subPackages` 中登记;`pipe/`、`scanpages/` 是分包,页面路径引用时以 `/pipe/...`、`/scanpages/...` 开头。
|
||||||
|
- **接口层约定**:所有请求函数定义在 `api/*.js` 中,命名前缀 `req`(如 `reqHJIndexData`),基于 `utils/request.js` 导出的 `get` / `post`:
|
||||||
|
- 后端约定 `body.code === 1` 为成功;非 1 自动 toast 报错并 reject;`code === 401` 自动登出并跳转登录页。
|
||||||
|
- 请求自动携带 `token` 请求头(取自 user store);默认显示 loading,可通过 `request(url, { loading: false, toast: false })` 控制。
|
||||||
|
- GET 参数用对象传入(`get(url, { key: val })`),会自动编码中文;也兼容旧的 URL 拼接风格。
|
||||||
|
- 附件上传用 `api/base.js` 的 `uploadAttach`;服务器返回的逗号分隔附件路径用 `parseAttachUrls` 解析为可展示列表。
|
||||||
|
- **状态管理**:store 使用组合式写法(`defineStore('user', () => {...})`),通过 `persist` 选项持久化(如 user store 持久化 `loginForm/userInfo/token/currentProject`)。切换当前项目(`currentProject`)会自动触发菜单权限与焊接首页数据的重新拉取(`store/modules/user.js` 中的 watch)。
|
||||||
|
- **菜单权限**:双重过滤(`store/modules/menu.js` 的 `appVisible`)——后端 `getMenuPowerList`(按 menuId GUID 匹配)+ 小程序端硬编码岗位权限。岗位权限规则(来源 `requests/权限.xlsx`,固定在 `utils/constant.js` 的 `postMenuPermissions`):仅对登录返回 `UserType === '3'` 的现场人员按 `WorkPostName` 限制扫码类功能(`sampling` 下料抽检 / `makeRight` 组对抽查 / `antiRust` 防腐处理 / `dailyPaper` 焊接日报 / `dailyAudit` 日报审核,其中 `dailyAudit` 仅管理/技术岗位有),pipe 管理类应用(无 `funcKey`)对现场人员一律隐藏;其余用户不限制。扫码跳转页面前需用 menu store 的 `canAccessPath` 校验(首页扫一扫已接入)。
|
||||||
|
- **扫码**:首页入口带 `isScan: true` 的应用走扫码流程,扫码结果统一由 `utils/scanUtils.js` 的 `parseScanResult` 解析(焊接接头二维码跳焊接日报;非 URL 视为材料编码)。
|
||||||
|
- 代码风格:缩进用 **Tab**,中文注释,单文件组件结构为 template / script / style(scoped scss)。列表页普遍采用「filter-header + scroll-view 下拉刷新/上拉加载 + card 列表」的模式,新列表页请参照 `pipe/packaging/list.vue`。
|
||||||
|
|
||||||
|
## 测试
|
||||||
|
|
||||||
|
项目**没有测试框架、没有 lint/format 配置**,无任何自动化测试。验证方式是在微信开发者工具 / HBuilderX 中手动运行页面确认。
|
||||||
|
|
||||||
|
## 安全注意事项
|
||||||
|
|
||||||
|
- 登录 token(即 `PersonId`)通过 Pinia 持久化存储在本地,并在每个请求的 `token` 请求头中携带;不要在日志中打印 token 或提交包含凭据的代码。
|
||||||
|
- `manifest.json` 中包含微信小程序 appid 等发布配置,修改前请确认影响。
|
||||||
|
- 生产后端地址硬编码在 `utils/request.js`(`baseUrl` / `baseFileUrl`),修改会直接影响线上请求。
|
||||||
@@ -195,4 +195,29 @@ export const reqGetAntiCorrosionCheck = (params = {}) => {
|
|||||||
return get('/AntiCorrosionCheck/GetRecordsByMaterialCode', params)
|
return get('/AntiCorrosionCheck/GetRecordsByMaterialCode', params)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ========================= 日报审核 ====================================
|
||||||
|
/**
|
||||||
|
* 获取焊接日报待审核列表
|
||||||
|
* @param {Object} params - { projectId, unitWorkId?, weldingDate?, pipelineCode?, welderCode?, pageIndex? }
|
||||||
|
* pageIndex 从 1 开始,小于等于 0 时返回全部记录
|
||||||
|
*/
|
||||||
|
export const reqPendingWeldingDailyList = (params = {}) => get('/PreWeldingDaily/GetPendingWeldingDailyTempDetailList', params)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查看单条焊接日报待审核明细
|
||||||
|
* @param {String} tempDetailId 待审核明细ID
|
||||||
|
*/
|
||||||
|
export const reqPendingWeldingDailyDetail = (tempDetailId) => get(`/PreWeldingDaily/GetPendingWeldingDailyTempDetail?tempDetailId=${tempDetailId}`)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量审核通过焊接日报待审核明细
|
||||||
|
* @param {Object} data - { TempDetailIds: string[], AuditMan: string }
|
||||||
|
*/
|
||||||
|
export const reqAuditWeldingDaily = (data = {}) => post(`/PreWeldingDaily/AuditPendingWeldingDailyTempDetails`, data)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除(驳回)焊接日报待审核明细
|
||||||
|
* @param {Object} data - { TempDetailIds: string[] }
|
||||||
|
*/
|
||||||
|
export const reqDeleteWeldingDaily = (data = {}) => post(`/PreWeldingDaily/DeletePendingWeldingDailyTempDetails`, data)
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -50,7 +50,7 @@
|
|||||||
"quickapp" : {},
|
"quickapp" : {},
|
||||||
/* 小程序特有相关 */
|
/* 小程序特有相关 */
|
||||||
"mp-weixin" : {
|
"mp-weixin" : {
|
||||||
"appid" : "wx35c91aed9edf6e54",
|
"appid" : "wx61a8a2e0e6a46284",
|
||||||
"setting" : {
|
"setting" : {
|
||||||
"urlCheck" : false
|
"urlCheck" : false
|
||||||
},
|
},
|
||||||
|
|||||||
Generated
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "SHJ_APP",
|
"name": "shj-app",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|||||||
+12
@@ -151,6 +151,18 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "防腐处理"
|
"navigationBarTitleText": "防腐处理"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "hj/daily_audit",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "日报审核"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "hj/daily_audit_detail",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": "日报审核详情"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -307,6 +307,14 @@
|
|||||||
// 优先按 URL 规则解析(焊接接头等)
|
// 优先按 URL 规则解析(焊接接头等)
|
||||||
const parsed = parseScanResult(result)
|
const parsed = parseScanResult(result)
|
||||||
if (parsed) {
|
if (parsed) {
|
||||||
|
// 扫码跳转前校验岗位权限(现场人员 UserType=3 按岗位限制)
|
||||||
|
if (!menuStore.canAccessPath(parsed.path)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '当前岗位无此功能权限',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: `${parsed.path}?${parsed.query}`
|
url: `${parsed.path}?${parsed.query}`
|
||||||
})
|
})
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 131 KiB |
@@ -0,0 +1,199 @@
|
|||||||
|
pc地址:[lygcgs.com.cn:8078/shj/](https://lygcgs.com.cn:8078/shj/)
|
||||||
|
账号:`hfnbd`
|
||||||
|
密码:`1111`
|
||||||
|
需求内容:小程序日报填报后,也需要有专工进行和PC一致的日报审核功能。
|
||||||
|
![[Pasted image 20260807100722.png]]小程序修改
|
||||||
|
![[Pasted image 20260807100945.png]]
|
||||||
|
返回的实体类注释
|
||||||
|
``` C#
|
||||||
|
/// <summary>
|
||||||
|
/// 焊接日报待审核明细。
|
||||||
|
/// </summary>
|
||||||
|
public class WeldingDailyTempDetailItem
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 待审核明细ID。
|
||||||
|
/// </summary>
|
||||||
|
public string TempDetailId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 项目ID。
|
||||||
|
/// </summary>
|
||||||
|
public string ProjectId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单位ID。
|
||||||
|
/// </summary>
|
||||||
|
public string UnitId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单位工程ID。
|
||||||
|
/// </summary>
|
||||||
|
public string UnitWorkId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊口ID。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldJointId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 管线ID。
|
||||||
|
/// </summary>
|
||||||
|
public string PipelineId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 管线编号。
|
||||||
|
/// </summary>
|
||||||
|
public string PipelineCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊口编号。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldJointCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊接日期。
|
||||||
|
/// </summary>
|
||||||
|
public DateTime WeldingDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 盖面焊工ID。
|
||||||
|
/// </summary>
|
||||||
|
public string CoverWelderId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 盖面焊工编号。
|
||||||
|
/// </summary>
|
||||||
|
public string CoverWelderCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打底焊工ID。
|
||||||
|
/// </summary>
|
||||||
|
public string BackingWelderId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 打底焊工编号。
|
||||||
|
/// </summary>
|
||||||
|
public string BackingWelderCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊口属性。
|
||||||
|
/// </summary>
|
||||||
|
public string JointAttribute { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊接位置ID。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldingLocationId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊接位置编号。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldingLocationCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊接模式。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldingMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 材质1编号。
|
||||||
|
/// </summary>
|
||||||
|
public string Material1Code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 材质2编号。
|
||||||
|
/// </summary>
|
||||||
|
public string Material2Code { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公称直径字符串。
|
||||||
|
/// </summary>
|
||||||
|
public string DNDia { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊口尺寸。
|
||||||
|
/// </summary>
|
||||||
|
public decimal? Size { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 外径。
|
||||||
|
/// </summary>
|
||||||
|
public decimal? Dia { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 壁厚。
|
||||||
|
/// </summary>
|
||||||
|
public decimal? Thickness { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊口类型编号。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldTypeCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊接方法编号。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldingMethodCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊丝编号。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldingWireCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊条编号。
|
||||||
|
/// </summary>
|
||||||
|
public string WeldingRodCode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交人ID。
|
||||||
|
/// </summary>
|
||||||
|
public string SubmitPersonId { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交人姓名。
|
||||||
|
/// </summary>
|
||||||
|
public string SubmitPersonName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 提交时间。
|
||||||
|
/// </summary>
|
||||||
|
public DateTime SubmitDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊前照片地址。
|
||||||
|
/// </summary>
|
||||||
|
public string BeforePhotoUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 焊后照片地址。
|
||||||
|
/// </summary>
|
||||||
|
public string AfterPhotoUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 明细附件地址。
|
||||||
|
/// </summary>
|
||||||
|
public string AttachUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 审核状态:0待审核,1已审核。
|
||||||
|
/// </summary>
|
||||||
|
public int AuditState { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 审核人ID。
|
||||||
|
/// </summary>
|
||||||
|
public string AuditMan { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 审核时间。
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? AuditDate { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 审核备注。
|
||||||
|
/// </summary>
|
||||||
|
public string AuditRemark { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 83 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
Binary file not shown.
@@ -0,0 +1,248 @@
|
|||||||
|
---
|
||||||
|
title: 默认模块
|
||||||
|
language_tabs:
|
||||||
|
- shell: Shell
|
||||||
|
- http: HTTP
|
||||||
|
- javascript: JavaScript
|
||||||
|
- ruby: Ruby
|
||||||
|
- python: Python
|
||||||
|
- php: PHP
|
||||||
|
- java: Java
|
||||||
|
- go: Go
|
||||||
|
toc_footers: []
|
||||||
|
includes: []
|
||||||
|
search: true
|
||||||
|
code_clipboard: true
|
||||||
|
highlight_theme: darkula
|
||||||
|
headingLevel: 2
|
||||||
|
generator: "@tarslib/widdershins v4.0.30"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# 默认模块
|
||||||
|
|
||||||
|
Base URLs:
|
||||||
|
|
||||||
|
* <a href="https://lygcgs.com.cn:8078/shjapi">正式环境: https://lygcgs.com.cn:8078/shjapi</a>
|
||||||
|
|
||||||
|
# Authentication
|
||||||
|
|
||||||
|
# PreWeldingDaily
|
||||||
|
|
||||||
|
<a id="opIdPreWeldingDaily_GetPendingWeldingDailyTempDetailList"></a>
|
||||||
|
|
||||||
|
## GET 获取焊接日报待审核列表。
|
||||||
|
|
||||||
|
GET /api/PreWeldingDaily/GetPendingWeldingDailyTempDetailList
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
|名称|位置|类型|必选|说明|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|projectId|query|string| 是 |项目ID|
|
||||||
|
|unitWorkId|query|string| 否 |单位工程ID,可为空|
|
||||||
|
|weldingDate|query|string| 否 |焊接日期,可为空,格式如 yyyy-MM-dd|
|
||||||
|
|pipelineCode|query|string| 否 |管线编号关键字,可为空|
|
||||||
|
|welderCode|query|string| 否 |焊工编号关键字,可为空|
|
||||||
|
|pageIndex|query|integer(int32)| 否 |页码,从1开始;小于等于0时返回全部记录|
|
||||||
|
|token|header|string| 否 |none|
|
||||||
|
|
||||||
|
> 返回示例
|
||||||
|
|
||||||
|
> 200 Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"message": "string",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 返回结果
|
||||||
|
|
||||||
|
|状态码|状态码含义|说明|数据模型|
|
||||||
|
|---|---|---|---|
|
||||||
|
|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[Model.ResponeData](#schemamodel.responedata)|
|
||||||
|
|
||||||
|
<a id="opIdPreWeldingDaily_GetPendingWeldingDailyTempDetail"></a>
|
||||||
|
|
||||||
|
## GET 查看单条焊接日报待审核明细。
|
||||||
|
|
||||||
|
GET /api/PreWeldingDaily/GetPendingWeldingDailyTempDetail
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
|名称|位置|类型|必选|说明|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|tempDetailId|query|string| 是 |待审核明细ID|
|
||||||
|
|token|header|string| 否 |none|
|
||||||
|
|
||||||
|
> 返回示例
|
||||||
|
|
||||||
|
> 200 Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"message": "string",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 返回结果
|
||||||
|
|
||||||
|
|状态码|状态码含义|说明|数据模型|
|
||||||
|
|---|---|---|---|
|
||||||
|
|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[Model.ResponeData](#schemamodel.responedata)|
|
||||||
|
|
||||||
|
<a id="opIdPreWeldingDaily_AuditPendingWeldingDailyTempDetails"></a>
|
||||||
|
|
||||||
|
## POST 批量审核通过焊接日报待审核明细。
|
||||||
|
|
||||||
|
POST /api/PreWeldingDaily/AuditPendingWeldingDailyTempDetails
|
||||||
|
|
||||||
|
> Body 请求参数
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"TempDetailIds": [
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"AuditMan": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
TempDetailIds:
|
||||||
|
- string
|
||||||
|
AuditMan: string
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
|名称|位置|类型|必选|说明|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|token|header|string| 否 |none|
|
||||||
|
|body|body|[Model.WeldingDailyTempDetailBatchRequest](#schemamodel.weldingdailytempdetailbatchrequest)| 是 |none|
|
||||||
|
|
||||||
|
> 返回示例
|
||||||
|
|
||||||
|
> 200 Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"message": "string",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 返回结果
|
||||||
|
|
||||||
|
|状态码|状态码含义|说明|数据模型|
|
||||||
|
|---|---|---|---|
|
||||||
|
|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[Model.ResponeData](#schemamodel.responedata)|
|
||||||
|
|
||||||
|
<a id="opIdPreWeldingDaily_DeletePendingWeldingDailyTempDetails"></a>
|
||||||
|
|
||||||
|
## POST 批量删除焊接日报待审核明细。
|
||||||
|
|
||||||
|
POST /api/PreWeldingDaily/DeletePendingWeldingDailyTempDetails
|
||||||
|
|
||||||
|
> Body 请求参数
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"TempDetailIds": [
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"AuditMan": "string"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
TempDetailIds:
|
||||||
|
- string
|
||||||
|
AuditMan: string
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 请求参数
|
||||||
|
|
||||||
|
|名称|位置|类型|必选|说明|
|
||||||
|
|---|---|---|---|---|
|
||||||
|
|token|header|string| 否 |none|
|
||||||
|
|body|body|[Model.WeldingDailyTempDetailBatchRequest](#schemamodel.weldingdailytempdetailbatchrequest)| 是 |none|
|
||||||
|
|
||||||
|
> 返回示例
|
||||||
|
|
||||||
|
> 200 Response
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"message": "string",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 返回结果
|
||||||
|
|
||||||
|
|状态码|状态码含义|说明|数据模型|
|
||||||
|
|---|---|---|---|
|
||||||
|
|200|[OK](https://tools.ietf.org/html/rfc7231#section-6.3.1)|OK|[Model.ResponeData](#schemamodel.responedata)|
|
||||||
|
|
||||||
|
# 数据模型
|
||||||
|
|
||||||
|
<h2 id="tocS_Model.ResponeData">Model.ResponeData</h2>
|
||||||
|
|
||||||
|
<a id="schemamodel.responedata"></a>
|
||||||
|
<a id="schema_Model.ResponeData"></a>
|
||||||
|
<a id="tocSmodel.responedata"></a>
|
||||||
|
<a id="tocsmodel.responedata"></a>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 0,
|
||||||
|
"message": "string",
|
||||||
|
"data": {}
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### 属性
|
||||||
|
|
||||||
|
|名称|类型|必选|约束|中文名|说明|
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
|code|integer(int32)|false|none||代码 1-正常;0-异常;|
|
||||||
|
|message|string|false|none||消息|
|
||||||
|
|data|object|false|none||数据|
|
||||||
|
|
||||||
|
<h2 id="tocS_Model.WeldingDailyTempDetailBatchRequest">Model.WeldingDailyTempDetailBatchRequest</h2>
|
||||||
|
|
||||||
|
<a id="schemamodel.weldingdailytempdetailbatchrequest"></a>
|
||||||
|
<a id="schema_Model.WeldingDailyTempDetailBatchRequest"></a>
|
||||||
|
<a id="tocSmodel.weldingdailytempdetailbatchrequest"></a>
|
||||||
|
<a id="tocsmodel.weldingdailytempdetailbatchrequest"></a>
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"TempDetailIds": [
|
||||||
|
"string"
|
||||||
|
],
|
||||||
|
"AuditMan": "string"
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
焊接日报待审核批量操作参数。
|
||||||
|
|
||||||
|
### 属性
|
||||||
|
|
||||||
|
|名称|类型|必选|约束|中文名|说明|
|
||||||
|
|---|---|---|---|---|---|
|
||||||
|
|TempDetailIds|[string]|false|none||待审核明细ID集合。|
|
||||||
|
|AuditMan|string|false|none||审核人ID,批量删除时无需填写。|
|
||||||
|
|
||||||
@@ -0,0 +1,451 @@
|
|||||||
|
<template>
|
||||||
|
<view class="page-list">
|
||||||
|
<!-- 头部过滤区域 -->
|
||||||
|
<view class="filter-header">
|
||||||
|
<!-- 第一行:管线编号搜索 -->
|
||||||
|
<view class="search-row">
|
||||||
|
<u-search v-model="pipelineCode" placeholder="请输入管线编号" :show-action="false" shape="square"
|
||||||
|
bg-color="#f5f6f8" @change="handleSearch" />
|
||||||
|
</view>
|
||||||
|
<!-- 第二行:焊工编号 + 焊接日期 + 单位工程 -->
|
||||||
|
<view class="filter-row">
|
||||||
|
<view class="welder-input-wrap">
|
||||||
|
<input class="welder-input" v-model="welderCode" placeholder="焊工编号" confirm-type="search"
|
||||||
|
@confirm="handleSearch" @blur="handleSearch" />
|
||||||
|
</view>
|
||||||
|
<picker mode="date" :value="weldingDate" @change="onDateChange">
|
||||||
|
<view class="filter-btn">
|
||||||
|
<text class="filter-btn__text" :class="{ 'filter-btn__text--placeholder': !weldingDate }">
|
||||||
|
{{ weldingDate || '焊接日期' }}
|
||||||
|
</text>
|
||||||
|
<u-icon v-if="weldingDate" name="close" :size="20" color="#999" @click.stop="onDateClear" />
|
||||||
|
<u-icon v-else name="calendar" :size="24" color="#999" />
|
||||||
|
</view>
|
||||||
|
</picker>
|
||||||
|
<view class="filter-btn" @click="handleShowUnitWorkSelect">
|
||||||
|
<text class="filter-btn__text" :class="{ 'filter-btn__text--placeholder': !selectedUnitWork }">
|
||||||
|
{{ selectedUnitWork?.BaseInfoName || '单位工程' }}
|
||||||
|
</text>
|
||||||
|
<u-icon name="arrow-down" :size="18" color="#999" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 列表内容 -->
|
||||||
|
<scroll-view class="list-scroll" scroll-y refresher-enabled="true" :refresher-triggered="refreshing"
|
||||||
|
@refresherrefresh="handleRefresh">
|
||||||
|
<view class="list-wrap">
|
||||||
|
<view v-for="(item, index) in listData" :key="item.TempDetailId || index" class="card-item audit-card"
|
||||||
|
@click="handleItemClick(item)">
|
||||||
|
<!-- 勾选框 -->
|
||||||
|
<view class="check-circle" :class="{ 'check-circle--checked': isSelected(item) }"
|
||||||
|
@click.stop="toggleSelect(item)">
|
||||||
|
<u-icon v-if="isSelected(item)" name="checkmark" :size="24" color="#fff" />
|
||||||
|
</view>
|
||||||
|
<view class="audit-card__content">
|
||||||
|
<view class="card-header">
|
||||||
|
<text class="card-code">{{ item.WeldJointCode || '--' }}</text>
|
||||||
|
<text class="card-tag status-1">待审核</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-body">
|
||||||
|
<view class="card-row">
|
||||||
|
<text class="row-label">管线编号</text>
|
||||||
|
<text class="row-value">{{ item.PipelineCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-row">
|
||||||
|
<text class="row-label">焊接日期</text>
|
||||||
|
<text class="row-value">{{ fmtDate(item.WeldingDate) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-row">
|
||||||
|
<text class="row-label">焊工</text>
|
||||||
|
<text class="row-value">{{ formatWelders(item) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-row">
|
||||||
|
<text class="row-label">焊接方法</text>
|
||||||
|
<text class="row-value">{{ item.WeldingMethodCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-row">
|
||||||
|
<text class="row-label">提交人</text>
|
||||||
|
<text class="row-value">{{ item.SubmitPersonName || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card-row">
|
||||||
|
<text class="row-label">提交时间</text>
|
||||||
|
<text class="row-value">{{ fmtDateTime(item.SubmitDate) }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 空状态 -->
|
||||||
|
<u-empty v-if="!loading && listData.length === 0" mode="list" text="暂无待审核日报"></u-empty>
|
||||||
|
</view>
|
||||||
|
</scroll-view>
|
||||||
|
|
||||||
|
<!-- 底部批量操作栏 -->
|
||||||
|
<view class="audit-bar">
|
||||||
|
<view class="audit-bar__all" @click="handleToggleAll">
|
||||||
|
<view class="check-circle" :class="{ 'check-circle--checked': isAllSelected }">
|
||||||
|
<u-icon v-if="isAllSelected" name="checkmark" :size="24" color="#fff" />
|
||||||
|
</view>
|
||||||
|
<text class="audit-bar__all-text">全选</text>
|
||||||
|
</view>
|
||||||
|
<text class="audit-bar__count">已选 {{ selectedIds.length }} 项</text>
|
||||||
|
<view class="audit-bar__btns">
|
||||||
|
<u-button size="medium" type="error" :disabled="selectedIds.length === 0"
|
||||||
|
@click="handleBatchDelete">删除</u-button>
|
||||||
|
<u-button size="medium" type="primary" :disabled="selectedIds.length === 0"
|
||||||
|
@click="handleBatchAudit">审核通过</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 单位工程选择弹窗 -->
|
||||||
|
<nbd-select v-model="showUnitWorkSelect" :show-search="true" title="请选择单位工程" :list="unitWorkList"
|
||||||
|
label-key="BaseInfoName" value-key="BaseInfoId" v-model:model="selectedUnitWork"
|
||||||
|
@confirm="handleUnitWorkConfirm" />
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref,
|
||||||
|
computed
|
||||||
|
} from 'vue'
|
||||||
|
import {
|
||||||
|
onShow
|
||||||
|
} from '@dcloudio/uni-app'
|
||||||
|
import {
|
||||||
|
storeToRefs
|
||||||
|
} from 'pinia'
|
||||||
|
import {
|
||||||
|
useUserStore
|
||||||
|
} from '@/store'
|
||||||
|
import {
|
||||||
|
reqProjectWorkArea
|
||||||
|
} from '@/api/base.js'
|
||||||
|
import {
|
||||||
|
reqPendingWeldingDailyList,
|
||||||
|
reqAuditWeldingDaily,
|
||||||
|
reqDeleteWeldingDaily
|
||||||
|
} from '@/api/hj.js'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const {
|
||||||
|
currentProject,
|
||||||
|
userInfo
|
||||||
|
} = storeToRefs(userStore)
|
||||||
|
|
||||||
|
// ===== 筛选条件 =====
|
||||||
|
const pipelineCode = ref('')
|
||||||
|
const welderCode = ref('')
|
||||||
|
const weldingDate = ref('')
|
||||||
|
|
||||||
|
const onDateChange = (e) => {
|
||||||
|
weldingDate.value = e.detail.value
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const onDateClear = () => {
|
||||||
|
weldingDate.value = ''
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 单位工程选择 =====
|
||||||
|
const showUnitWorkSelect = ref(false)
|
||||||
|
const selectedUnitWork = ref(null)
|
||||||
|
const unitWorkList = ref([])
|
||||||
|
|
||||||
|
const handleShowUnitWorkSelect = () => {
|
||||||
|
reqProjectWorkArea(currentProject.value.ProjectId).then(res => {
|
||||||
|
unitWorkList.value = [{
|
||||||
|
BaseInfoId: '',
|
||||||
|
BaseInfoName: '全部'
|
||||||
|
}, ...(res.data || [])]
|
||||||
|
showUnitWorkSelect.value = true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleUnitWorkConfirm = (item) => {
|
||||||
|
selectedUnitWork.value = item?.BaseInfoId ? item : null
|
||||||
|
showUnitWorkSelect.value = false
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 列表数据 =====
|
||||||
|
const listData = ref([])
|
||||||
|
const loading = ref(false)
|
||||||
|
const refreshing = ref(false)
|
||||||
|
|
||||||
|
// 加载待审核列表(不分页,一次拉全部待审核记录)
|
||||||
|
const fetchData = async () => {
|
||||||
|
if (loading.value) return
|
||||||
|
loading.value = true
|
||||||
|
refreshing.value = true
|
||||||
|
try {
|
||||||
|
const res = await reqPendingWeldingDailyList({
|
||||||
|
projectId: currentProject.value?.ProjectId,
|
||||||
|
unitWorkId: selectedUnitWork.value?.BaseInfoId || '',
|
||||||
|
weldingDate: weldingDate.value || '',
|
||||||
|
pipelineCode: pipelineCode.value || '',
|
||||||
|
welderCode: welderCode.value || ''
|
||||||
|
})
|
||||||
|
listData.value = res.data?.list || res.data?.getDataList || (Array.isArray(res.data) ? res.data : [])
|
||||||
|
// 刷新后清空已选(原记录可能已不存在)
|
||||||
|
selectedIds.value = []
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载待审核日报失败:', error)
|
||||||
|
} finally {
|
||||||
|
loading.value = false
|
||||||
|
refreshing.value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRefresh = () => {
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleSearch = () => {
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 勾选 =====
|
||||||
|
const selectedIds = ref([])
|
||||||
|
|
||||||
|
const isSelected = (item) => selectedIds.value.includes(item.TempDetailId)
|
||||||
|
|
||||||
|
const toggleSelect = (item) => {
|
||||||
|
const id = item.TempDetailId
|
||||||
|
const idx = selectedIds.value.indexOf(id)
|
||||||
|
if (idx > -1) {
|
||||||
|
selectedIds.value.splice(idx, 1)
|
||||||
|
} else {
|
||||||
|
selectedIds.value.push(id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const isAllSelected = computed(() =>
|
||||||
|
listData.value.length > 0 && selectedIds.value.length === listData.value.length
|
||||||
|
)
|
||||||
|
|
||||||
|
const handleToggleAll = () => {
|
||||||
|
if (isAllSelected.value) {
|
||||||
|
selectedIds.value = []
|
||||||
|
} else {
|
||||||
|
selectedIds.value = listData.value.map(item => item.TempDetailId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 批量操作 =====
|
||||||
|
const handleBatchAudit = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '信息提示',
|
||||||
|
content: `确定审核通过选中的 ${selectedIds.value.length} 条日报吗?`,
|
||||||
|
success: async ({
|
||||||
|
confirm
|
||||||
|
}) => {
|
||||||
|
if (!confirm) return
|
||||||
|
try {
|
||||||
|
await reqAuditWeldingDaily({
|
||||||
|
TempDetailIds: selectedIds.value,
|
||||||
|
AuditMan: userInfo.value?.PersonId
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return // 报错已由 request.js 统一 toast
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: '审核成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleBatchDelete = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '信息提示',
|
||||||
|
content: `确定删除选中的 ${selectedIds.value.length} 条日报吗?`,
|
||||||
|
success: async ({
|
||||||
|
confirm
|
||||||
|
}) => {
|
||||||
|
if (!confirm) return
|
||||||
|
try {
|
||||||
|
await reqDeleteWeldingDaily({
|
||||||
|
TempDetailIds: selectedIds.value
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return // 报错已由 request.js 统一 toast
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
fetchData()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 跳转详情 =====
|
||||||
|
const handleItemClick = (item) => {
|
||||||
|
uni.navigateTo({
|
||||||
|
url: `/scanpages/hj/daily_audit_detail?id=${item.TempDetailId}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 工具 =====
|
||||||
|
const fmtDate = (val) => {
|
||||||
|
if (!val) return '--'
|
||||||
|
return String(val).slice(0, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fmtDateTime = (val) => {
|
||||||
|
if (!val) return '--'
|
||||||
|
return String(val).slice(0, 16).replace('T', ' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 焊工展示:盖面/打底
|
||||||
|
const formatWelders = (item) => {
|
||||||
|
const cover = item.CoverWelderCode || ''
|
||||||
|
const backing = item.BackingWelderCode || ''
|
||||||
|
if (cover && backing && cover !== backing) return `${cover}/${backing}`
|
||||||
|
return cover || backing || '--'
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 生命周期 =====
|
||||||
|
onShow(() => {
|
||||||
|
fetchData()
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$primary: $app-primary;
|
||||||
|
|
||||||
|
.filter-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 12rpx;
|
||||||
|
|
||||||
|
.welder-input-wrap {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
background: #f5f6f8;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 16rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.welder-input {
|
||||||
|
width: 100%;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-btn {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: #f5f6f8;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
padding: 0 16rpx;
|
||||||
|
height: 70rpx;
|
||||||
|
|
||||||
|
&__text {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #333;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
|
||||||
|
&--placeholder {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 勾选圆圈
|
||||||
|
.check-circle {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 2rpx solid #ccc;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
background: #fff;
|
||||||
|
|
||||||
|
&--checked {
|
||||||
|
background: $primary;
|
||||||
|
border-color: $primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 带勾选框的卡片
|
||||||
|
.audit-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 20rpx;
|
||||||
|
|
||||||
|
.check-circle {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__content {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 底部批量操作栏
|
||||||
|
.audit-bar {
|
||||||
|
position: fixed;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
background: #ffffff;
|
||||||
|
padding: 20rpx 32rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20rpx;
|
||||||
|
box-shadow: 0 -2rpx 12rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
&__all {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__all-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__count {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__btns {
|
||||||
|
display: flex;
|
||||||
|
gap: 16rpx;
|
||||||
|
|
||||||
|
.u-size-medium {
|
||||||
|
height: 72rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
border-radius: 8rpx;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 32rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 给底部操作栏留出空间
|
||||||
|
.list-scroll {
|
||||||
|
padding-bottom: 140rpx;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,337 @@
|
|||||||
|
<template>
|
||||||
|
<view class="detail-page">
|
||||||
|
<!-- 焊口主标识 -->
|
||||||
|
<view class="joint-hero">
|
||||||
|
<text class="joint-hero__code">{{ form.WeldJointCode || '--' }}</text>
|
||||||
|
<view class="joint-hero__meta">
|
||||||
|
<view class="joint-hero__pill">
|
||||||
|
<text class="pill-label">管线编码</text>
|
||||||
|
<text class="pill-value">{{ form.PipelineCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="joint-hero__pill">
|
||||||
|
<text class="pill-label">提交人</text>
|
||||||
|
<text class="pill-value">{{ form.SubmitPersonName || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 焊口信息 -->
|
||||||
|
<view class="section">
|
||||||
|
<view class="section__header">
|
||||||
|
<view class="section__bar"></view>
|
||||||
|
<text class="section__title">焊口信息</text>
|
||||||
|
</view>
|
||||||
|
<view class="card">
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">材质1</text>
|
||||||
|
<text class="card__value">{{ form.Material1Code || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">材质2</text>
|
||||||
|
<text class="card__value">{{ form.Material2Code || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">达因</text>
|
||||||
|
<text class="card__value">{{ form.Size ?? '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">外径</text>
|
||||||
|
<text class="card__value">{{ form.Dia ?? '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">DN公称直径</text>
|
||||||
|
<text class="card__value">{{ form.DNDia || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">壁厚</text>
|
||||||
|
<text class="card__value">{{ form.Thickness ?? '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊缝类型</text>
|
||||||
|
<text class="card__value">{{ form.WeldTypeCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊口属性</text>
|
||||||
|
<text class="card__value">{{ form.JointAttribute || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 日报信息 -->
|
||||||
|
<view class="section">
|
||||||
|
<view class="section__header">
|
||||||
|
<view class="section__bar"></view>
|
||||||
|
<text class="section__title">日报信息</text>
|
||||||
|
</view>
|
||||||
|
<view class="card">
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊口位置</text>
|
||||||
|
<text class="card__value">{{ form.WeldingLocationCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊接日期</text>
|
||||||
|
<text class="card__value">{{ fmtDate(form.WeldingDate) }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">盖面焊工</text>
|
||||||
|
<text class="card__value">{{ form.CoverWelderCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">打底焊工</text>
|
||||||
|
<text class="card__value">{{ form.BackingWelderCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊接方法</text>
|
||||||
|
<text class="card__value">{{ form.WeldingMethodCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊接模式</text>
|
||||||
|
<text class="card__value">{{ form.WeldingMode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊丝</text>
|
||||||
|
<text class="card__value">{{ form.WeldingWireCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">焊条</text>
|
||||||
|
<text class="card__value">{{ form.WeldingRodCode || '--' }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="card__row">
|
||||||
|
<text class="card__label">提交时间</text>
|
||||||
|
<text class="card__value">{{ fmtDateTime(form.SubmitDate) }}</text>
|
||||||
|
</view>
|
||||||
|
<!-- 焊前拍照 -->
|
||||||
|
<view class="card__row card__row--stack">
|
||||||
|
<text class="card__label">焊前拍照</text>
|
||||||
|
<view class="card__value-wrap">
|
||||||
|
<nbd-photo-view :attachUrl="form.BeforePhotoUrl || ''" :cols="4" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 焊后拍照 -->
|
||||||
|
<view class="card__row card__row--stack">
|
||||||
|
<text class="card__label">焊后拍照</text>
|
||||||
|
<view class="card__value-wrap">
|
||||||
|
<nbd-photo-view :attachUrl="form.AfterPhotoUrl || ''" :cols="4" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<!-- 明细附件 -->
|
||||||
|
<view class="card__row card__row--stack" v-if="form.AttachUrl">
|
||||||
|
<text class="card__label">附件</text>
|
||||||
|
<view class="card__value-wrap">
|
||||||
|
<nbd-photo-view :attachUrl="form.AttachUrl" :cols="4" />
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 底部按钮 -->
|
||||||
|
<view class="bottom-btns">
|
||||||
|
<u-button class="btn-delete" size="medium" type="error" @click="handleDelete">删除</u-button>
|
||||||
|
<u-button class="btn-audit" size="medium" type="primary" @click="handleAudit">审核通过</u-button>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import {
|
||||||
|
ref
|
||||||
|
} from 'vue'
|
||||||
|
import {
|
||||||
|
onLoad
|
||||||
|
} from '@dcloudio/uni-app'
|
||||||
|
import {
|
||||||
|
useUserStore
|
||||||
|
} from '@/store'
|
||||||
|
import {
|
||||||
|
reqPendingWeldingDailyDetail,
|
||||||
|
reqAuditWeldingDaily,
|
||||||
|
reqDeleteWeldingDaily
|
||||||
|
} from '@/api/hj.js'
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const {
|
||||||
|
userInfo
|
||||||
|
} = userStore
|
||||||
|
|
||||||
|
const tempDetailId = ref('')
|
||||||
|
const form = ref({})
|
||||||
|
|
||||||
|
// ===== 操作 =====
|
||||||
|
const handleAudit = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '信息提示',
|
||||||
|
content: '确定审核通过该日报吗?',
|
||||||
|
success: async ({
|
||||||
|
confirm
|
||||||
|
}) => {
|
||||||
|
if (!confirm) return
|
||||||
|
try {
|
||||||
|
await reqAuditWeldingDaily({
|
||||||
|
TempDetailIds: [tempDetailId.value],
|
||||||
|
AuditMan: userInfo.PersonId
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return // 报错已由 request.js 统一 toast
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: '审核成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleDelete = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '信息提示',
|
||||||
|
content: '确定删除该日报吗?',
|
||||||
|
success: async ({
|
||||||
|
confirm
|
||||||
|
}) => {
|
||||||
|
if (!confirm) return
|
||||||
|
try {
|
||||||
|
await reqDeleteWeldingDaily({
|
||||||
|
TempDetailIds: [tempDetailId.value]
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
return // 报错已由 request.js 统一 toast
|
||||||
|
}
|
||||||
|
uni.showToast({
|
||||||
|
title: '删除成功',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
setTimeout(() => {
|
||||||
|
uni.navigateBack()
|
||||||
|
}, 1500)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 工具 =====
|
||||||
|
const fmtDate = (val) => {
|
||||||
|
if (!val) return '--'
|
||||||
|
return String(val).slice(0, 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fmtDateTime = (val) => {
|
||||||
|
if (!val) return '--'
|
||||||
|
return String(val).slice(0, 16).replace('T', ' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 生命周期 =====
|
||||||
|
onLoad((opt) => {
|
||||||
|
tempDetailId.value = opt.id || ''
|
||||||
|
// 接口报错时 request.js 已统一 toast,这里 catch 住避免未处理 Promise 异常
|
||||||
|
reqPendingWeldingDailyDetail(opt.id).then(res => {
|
||||||
|
form.value = res.data || {}
|
||||||
|
}).catch(() => {})
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$primary: $app-primary;
|
||||||
|
$primary-light: $app-primary-light;
|
||||||
|
$primary-mid: $app-primary-mid;
|
||||||
|
$primary-dark: $app-primary-dark;
|
||||||
|
$text: $app-text;
|
||||||
|
$text-secondary: $app-text-secondary;
|
||||||
|
$card-bg: #ffffff;
|
||||||
|
$shadow-md: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||||
|
|
||||||
|
.detail-page {
|
||||||
|
background: #f0f2f5;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===== 焊口主标识(同 daily_paper) =====
|
||||||
|
.joint-hero {
|
||||||
|
position: relative;
|
||||||
|
margin: 24rpx;
|
||||||
|
padding: 36rpx 32rpx 28rpx;
|
||||||
|
background: $card-bg;
|
||||||
|
border-radius: $app-radius;
|
||||||
|
box-shadow: $shadow-md;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
height: 4rpx;
|
||||||
|
background: linear-gradient(90deg, $primary, #6ba3ff, $primary);
|
||||||
|
background-size: 200% 100%;
|
||||||
|
animation: shimmer 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shimmer {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
background-position: 0% 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
background-position: 100% 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__code {
|
||||||
|
display: block;
|
||||||
|
font-size: 52rpx;
|
||||||
|
font-weight: 800;
|
||||||
|
color: $text;
|
||||||
|
line-height: 1.2;
|
||||||
|
word-break: break-all;
|
||||||
|
font-family: monospace;
|
||||||
|
letter-spacing: 2rpx;
|
||||||
|
margin-bottom: 28rpx;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 24rpx;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 6rpx;
|
||||||
|
bottom: 6rpx;
|
||||||
|
width: 4rpx;
|
||||||
|
background: $primary;
|
||||||
|
border-radius: 2rpx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__meta {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 12rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__pill {
|
||||||
|
display: inline-flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
background: $primary-light;
|
||||||
|
padding: 10rpx 18rpx;
|
||||||
|
border-radius: 10rpx;
|
||||||
|
border: 1rpx solid $primary-mid;
|
||||||
|
|
||||||
|
.pill-label {
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: $text-secondary;
|
||||||
|
width: 60rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pill-value {
|
||||||
|
font-size: 24rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: $primary-dark;
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
+35
-16
@@ -6,8 +6,9 @@ import {
|
|||||||
computed,
|
computed,
|
||||||
watch
|
watch
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import {pastelColors,defaultApps} from '@/utils/constant.js'
|
import {pastelColors,defaultApps,postMenuPermissions,scanPathFuncKeyMap} from '@/utils/constant.js'
|
||||||
import {reqMenuPowerList} from '@/api/auth.js'
|
import {reqMenuPowerList} from '@/api/auth.js'
|
||||||
|
import { useUserStore } from '@/store'
|
||||||
|
|
||||||
export const useMenuStore = defineStore('menu', () => {
|
export const useMenuStore = defineStore('menu', () => {
|
||||||
// 持久化:仅缓存快捷应用的 menuId 列表,不缓存全部菜单
|
// 持久化:仅缓存快捷应用的 menuId 列表,不缓存全部菜单
|
||||||
@@ -34,17 +35,44 @@ export const useMenuStore = defineStore('menu', () => {
|
|||||||
// 菜单的权限列表(后端返回的有权限的菜单 code 数组)
|
// 菜单的权限列表(后端返回的有权限的菜单 code 数组)
|
||||||
const menuProwerList = ref([])
|
const menuProwerList = ref([])
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 岗位权限校验:现场人员(UserType=3)按 WorkPostName 硬编码限制(见 constant.js postMenuPermissions),
|
||||||
|
* 其余用户不限制
|
||||||
|
* @param {string} funcKey 功能 key;空表示非扫码类菜单(pipe 管理应用),对现场人员一律隐藏
|
||||||
|
*/
|
||||||
|
const hasPostPermission = (funcKey) => {
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const info = userStore.userInfo
|
||||||
|
if (String(info?.UserType) !== '3') return true
|
||||||
|
if (!funcKey) return false
|
||||||
|
const allows = postMenuPermissions[info?.WorkPostName]
|
||||||
|
return !!allows && allows.includes(funcKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验扫码跳转的页面路径是否有岗位权限(非扫码类路径不限制)
|
||||||
|
* @param {string} path 页面路径
|
||||||
|
*/
|
||||||
|
const canAccessPath = (path) => {
|
||||||
|
const funcKey = scanPathFuncKeyMap[path]
|
||||||
|
if (!funcKey) return true
|
||||||
|
return hasPostPermission(funcKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应用是否可见:后端菜单权限 + 岗位权限双重过滤
|
||||||
|
const appVisible = (app) => hasMenuPermission(app.menuId) && hasPostPermission(app.funcKey)
|
||||||
|
|
||||||
// 快捷应用列表(已选择的)
|
// 快捷应用列表(已选择的)
|
||||||
const quickApps = computed(() => appsList.value.filter(app => app.selected && hasMenuPermission(app.menuId)))
|
const quickApps = computed(() => appsList.value.filter(app => app.selected && appVisible(app)))
|
||||||
|
|
||||||
// 业务查询列表(未选择的)
|
// 业务查询列表(未选择的)
|
||||||
const queryApps = computed(() => appsList.value.filter(app => !app.selected && hasMenuPermission(app.menuId)))
|
const queryApps = computed(() => appsList.value.filter(app => !app.selected && appVisible(app)))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 打开编辑弹窗(备份当前状态)
|
* 打开编辑弹窗(备份当前状态)
|
||||||
*/
|
*/
|
||||||
const openEdit = () => {
|
const openEdit = () => {
|
||||||
editCache.value = appsList.value.filter(app => hasMenuPermission(app.menuId))
|
editCache.value = appsList.value.filter(appVisible)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,22 +117,11 @@ export const useMenuStore = defineStore('menu', () => {
|
|||||||
return menuProwerList.value.includes(menuCode)
|
return menuProwerList.value.includes(menuCode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 根据权限过滤快捷应用
|
|
||||||
*/
|
|
||||||
const quickAppsWithPermission = computed(() => {
|
|
||||||
if (menuProwerList.value.length === 0) return quickApps.value
|
|
||||||
return quickApps.value.filter(app => {
|
|
||||||
return hasMenuPermission(app.permissionCode)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
appsList,
|
appsList,
|
||||||
quickAppIds,
|
quickAppIds,
|
||||||
editCache,
|
editCache,
|
||||||
quickApps,
|
quickApps,
|
||||||
quickAppsWithPermission,
|
|
||||||
queryApps,
|
queryApps,
|
||||||
menuProwerList,
|
menuProwerList,
|
||||||
pastelColors,
|
pastelColors,
|
||||||
@@ -112,7 +129,9 @@ export const useMenuStore = defineStore('menu', () => {
|
|||||||
toggleSelect,
|
toggleSelect,
|
||||||
confirmEdit,
|
confirmEdit,
|
||||||
fetchMenuPowerList,
|
fetchMenuPowerList,
|
||||||
hasMenuPermission
|
hasMenuPermission,
|
||||||
|
hasPostPermission,
|
||||||
|
canAccessPath
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
persist: {
|
persist: {
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ export const defaultApps = [{
|
|||||||
menuId: "",
|
menuId: "",
|
||||||
path: "/scanpages/hj/material_sampling",
|
path: "/scanpages/hj/material_sampling",
|
||||||
isScan: true,
|
isScan: true,
|
||||||
|
funcKey: 'sampling',
|
||||||
prefix: 'nbd-icon',
|
prefix: 'nbd-icon',
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
@@ -65,6 +66,7 @@ export const defaultApps = [{
|
|||||||
menuId: "",
|
menuId: "",
|
||||||
path: "/scanpages/hj/make_right",
|
path: "/scanpages/hj/make_right",
|
||||||
isScan: true,
|
isScan: true,
|
||||||
|
funcKey: 'makeRight',
|
||||||
prefix: 'nbd-icon',
|
prefix: 'nbd-icon',
|
||||||
selected: false
|
selected: false
|
||||||
},
|
},
|
||||||
@@ -74,7 +76,57 @@ export const defaultApps = [{
|
|||||||
menuId: "",
|
menuId: "",
|
||||||
path: "/scanpages/hj/do_anti_rust",
|
path: "/scanpages/hj/do_anti_rust",
|
||||||
isScan: true,
|
isScan: true,
|
||||||
|
funcKey: 'antiRust',
|
||||||
|
prefix: 'nbd-icon',
|
||||||
|
selected: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '日报审核',
|
||||||
|
icon: 'daiban',
|
||||||
|
menuId: "",
|
||||||
|
path: "/scanpages/hj/daily_audit",
|
||||||
|
funcKey: 'dailyAudit',
|
||||||
prefix: 'nbd-icon',
|
prefix: 'nbd-icon',
|
||||||
selected: false
|
selected: false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
||||||
|
// 扫码类功能 key:sampling 下料抽检 / makeRight 组对抽查 / antiRust 防腐处理 / dailyPaper 焊接日报 / dailyAudit 日报审核
|
||||||
|
const ALL_SCAN_FUNCS = ['sampling', 'makeRight', 'antiRust', 'dailyPaper']
|
||||||
|
// 管理/技术岗位在 4 个扫码功能之外,额外拥有日报审核
|
||||||
|
const MANAGE_SCAN_FUNCS = [...ALL_SCAN_FUNCS, 'dailyAudit']
|
||||||
|
|
||||||
|
// 现场人员(UserType=3)岗位菜单权限,小程序端硬编码(来源:requests/权限.xlsx)
|
||||||
|
// 未列出的岗位默认无任何扫码类菜单权限;pipe 管理类应用(无 funcKey)对现场人员一律隐藏
|
||||||
|
export const postMenuPermissions = {
|
||||||
|
'项目经理': MANAGE_SCAN_FUNCS,
|
||||||
|
'项目总工': MANAGE_SCAN_FUNCS,
|
||||||
|
'控制经理': MANAGE_SCAN_FUNCS,
|
||||||
|
'安环经理': MANAGE_SCAN_FUNCS,
|
||||||
|
'质量经理': MANAGE_SCAN_FUNCS,
|
||||||
|
'材料部长': MANAGE_SCAN_FUNCS,
|
||||||
|
'防腐工程师': MANAGE_SCAN_FUNCS,
|
||||||
|
'费控工程师': MANAGE_SCAN_FUNCS,
|
||||||
|
'物流工程师': MANAGE_SCAN_FUNCS,
|
||||||
|
'管道工程师': MANAGE_SCAN_FUNCS,
|
||||||
|
'包装工程师': MANAGE_SCAN_FUNCS,
|
||||||
|
'项目信息员': MANAGE_SCAN_FUNCS,
|
||||||
|
'材料员': MANAGE_SCAN_FUNCS,
|
||||||
|
'资料员': MANAGE_SCAN_FUNCS,
|
||||||
|
'技术员': MANAGE_SCAN_FUNCS,
|
||||||
|
'质量员': MANAGE_SCAN_FUNCS,
|
||||||
|
'施工员': MANAGE_SCAN_FUNCS,
|
||||||
|
'焊工': ['sampling', 'makeRight', 'dailyPaper'],
|
||||||
|
'管工': ALL_SCAN_FUNCS,
|
||||||
|
'防腐工': ['antiRust'],
|
||||||
|
'无损检测工': ['dailyPaper'],
|
||||||
|
}
|
||||||
|
|
||||||
|
// 扫码类页面路径 → 功能 key(用于扫码跳转前的岗位权限校验)
|
||||||
|
export const scanPathFuncKeyMap = {
|
||||||
|
'/scanpages/hj/material_sampling': 'sampling',
|
||||||
|
'/scanpages/hj/make_right': 'makeRight',
|
||||||
|
'/scanpages/hj/do_anti_rust': 'antiRust',
|
||||||
|
'/scanpages/hj/daily_paper': 'dailyPaper',
|
||||||
|
'/scanpages/hj/daily_audit': 'dailyAudit',
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,231 @@
|
|||||||
|
# SHJ_APP 业务功能框架
|
||||||
|
|
||||||
|
> 本文档面向业务理解与新人上手,梳理项目的完整功能结构、业务流程、权限体系与接口分布。
|
||||||
|
> 技术架构与编码约定见 `AGENTS.md`。
|
||||||
|
|
||||||
|
## 一、项目定位
|
||||||
|
|
||||||
|
**管道安装管理系统**(施工管理 App),服务于管道预制与安装现场的两条主线业务:
|
||||||
|
|
||||||
|
1. **焊接工序质检链**(扫码驱动):下料 → 组对 → 焊接 → 防腐,逐级填报 + 互检上一工序。
|
||||||
|
2. **物流配送链**(状态机驱动):预制组件 → 包装(组包)→ 车次(装车发货)→ 到场签收 / 验收。
|
||||||
|
|
||||||
|
辅助业务:点口管理(NDE 委托批次)、试压管理(试压包条件确认)、待办、焊接数据看板。
|
||||||
|
|
||||||
|
- 运行端:微信小程序为主,兼容 H5 / App。
|
||||||
|
- 后端:`https://lygcgs.com.cn:8078/shjapi/api/`(接口)、`https://lygcgs.com.cn:8078/shj/`(附件)。
|
||||||
|
- 后端约定:`body.code === 1` 成功;`401` 自动登出;多数"写"操作也是 GET 带参,仅保存类用 POST。
|
||||||
|
|
||||||
|
## 二、页面与路由总览
|
||||||
|
|
||||||
|
```
|
||||||
|
主包
|
||||||
|
├── pages/login/index 登录(非 tab)
|
||||||
|
├── pages/index/index 首页工作台(tab)
|
||||||
|
├── pages/mine/index 我的(tab)
|
||||||
|
└── pages/todo/list 待办(首页进入,非 tab)
|
||||||
|
|
||||||
|
分包 pipe(管理类业务,共 13 页)
|
||||||
|
├── diankou/ list、port_list 点口管理
|
||||||
|
├── pressure/ index、pressure_before/list|detail、 试压管理
|
||||||
|
│ check_remove/list(空页面)
|
||||||
|
├── packaging/ list、add、detail 包装管理
|
||||||
|
├── deliver/ list、detail 发货管理(车次)
|
||||||
|
└── precast/ list、detail 预制组件管理
|
||||||
|
|
||||||
|
分包 scanpages(扫码类业务,共 7 页)
|
||||||
|
└── hj/ materials_detail 材料详情(扫材料条码)
|
||||||
|
material_sampling 下料抽检(工序①)
|
||||||
|
make_right 组对抽查(工序②)
|
||||||
|
daily_paper 焊接日报(工序③,扫焊接接头码)
|
||||||
|
do_anti_rust 防腐处理(工序④)
|
||||||
|
daily_audit 日报审核列表(专工批量审核/删除)
|
||||||
|
daily_audit_detail 日报审核详情(单条审核/删除)
|
||||||
|
```
|
||||||
|
|
||||||
|
tabBar 仅两个 tab:首页、个人中心。待办从首页图标进入。
|
||||||
|
|
||||||
|
## 三、登录与权限体系
|
||||||
|
|
||||||
|
### 3.1 登录
|
||||||
|
|
||||||
|
- `POST user/postLoginOn` → 返回 `PersonId`(即 token,每请求以 `token` 头携带)、`UserType`、`WorkPostName`(岗位)、默认项目 `LoginProjectId/LoginProjectName`。
|
||||||
|
- 登录成功 → 设当前项目 → reLaunch 首页;账号密码持久化记住。
|
||||||
|
- user store 中 `watch(currentProject.ProjectId)`:项目变化自动重拉①菜单权限 ②焊接看板数据。
|
||||||
|
|
||||||
|
### 3.2 菜单权限(双重过滤,`store/modules/menu.js` 的 `appVisible`)
|
||||||
|
|
||||||
|
| 层 | 来源 | 规则 |
|
||||||
|
|---|---|---|
|
||||||
|
| 后端权限 | `GET User/getMenuPowerList?userId&projectId` | 返回有权限的菜单 GUID 数组,与 `defaultApps` 中 5 个管理类应用的 `menuId` 匹配 |
|
||||||
|
| 岗位权限 | 小程序端硬编码 `utils/constant.js` 的 `postMenuPermissions` | 仅对 `UserType === '3'` 现场人员按 `WorkPostName` 限制 4 个扫码功能;pipe 管理类应用对现场人员一律隐藏;其余用户不限制 |
|
||||||
|
|
||||||
|
岗位 → 扫码功能对照(`sampling` 下料 / `makeRight` 组对 / `antiRust` 防腐 / `dailyPaper` 日报 / `dailyAudit` 日报审核):
|
||||||
|
|
||||||
|
- 全部 4 项 + 日报审核:项目经理、项目总工、控制经理、安环经理、质量经理、材料部长、防腐/费控/物流/管道/包装工程师、项目信息员、材料员、资料员、技术员、质量员、施工员
|
||||||
|
- 焊工:下料、组对、日报
|
||||||
|
- 管工:全部 4 项(无日报审核)
|
||||||
|
- 防腐工:仅防腐
|
||||||
|
- 无损检测工:仅日报
|
||||||
|
- 未列出岗位:无扫码功能权限
|
||||||
|
|
||||||
|
扫码跳转页面前统一过 `menuStore.canAccessPath` 校验(首页扫一扫已接入)。
|
||||||
|
|
||||||
|
### 3.3 操作权限
|
||||||
|
|
||||||
|
详情页的「到场确认 / 验收」类按钮由 **`from=0`(扫码入口)+ 后端返回 `isPower`** 双重控制(包装到场确认、预制组件验收)。
|
||||||
|
|
||||||
|
## 四、首页工作台(pages/index/index.vue)
|
||||||
|
|
||||||
|
- **项目选择**:`nbd-select` 弹窗(可搜索),`GET Project/getProjectsByUserId`;切换项目触发权限与看板数据重拉。
|
||||||
|
- **扫一扫**(通用入口,分流规则见 §6)。
|
||||||
|
- **待办入口** → `/pages/todo/list`。
|
||||||
|
- **焊接数据看板**:`GET HJGLIndex/GetJGLIndexItem?projectId`,展示工厂/现场焊接一次合格率、预制进度、焊接功效、管道实时预制率。
|
||||||
|
- **快捷应用 + 业务查询**:8 个应用(5 管理类 + 3 扫码类),底部弹窗编辑勾选(可搜索),选中态按 `path` 持久化;点击进入前若无当前项目先弹项目选择;`isScan` 应用点击即调起扫码。
|
||||||
|
|
||||||
|
## 五、pipe 分包:管理类业务
|
||||||
|
|
||||||
|
所有列表页同构:filter-header(`nbd-select`/`u-search`/`u-radio-group`)+ scroll-view(下拉刷新 + 上拉分页)+ 卡片 + 空态。新列表页参照 `pipe/packaging/list.vue`。
|
||||||
|
|
||||||
|
### 5.1 点口管理 diankou(NDE 委托)
|
||||||
|
|
||||||
|
| 页面 | 功能 |
|
||||||
|
|---|---|
|
||||||
|
| `list` | 点口批次列表:单位工程筛选 + 批号搜索;接口 `NDETrust/getNotEndPointBatch` |
|
||||||
|
| `port_list` | 批次内焊口明细(管线号/焊口代号/已点未点状态);接口 `NDETrust/getPointBatchDetail`。⚠️「自动点口/强制关闭/点口调整」三个按钮目前为 TODO 桩 |
|
||||||
|
|
||||||
|
### 5.2 试压管理 pressure
|
||||||
|
|
||||||
|
| 页面 | 功能 |
|
||||||
|
|---|---|
|
||||||
|
| `index` | 导航页:试压前条件确认 / 尾项检查及消项 |
|
||||||
|
| `pressure_before/list` | 试压包列表:单位工程(必选)+ 具备/不具备条件 + 包号搜索;接口 `TestPackage/getTestPackageNo` |
|
||||||
|
| `pressure_before/detail` | 试压包焊口统计表:按管线号展示焊口完成数、合格/不合格数、实际/应检检测比例,前端按完成度着色(红/黄/紫/绿/青),纯展示;接口 `TestPackage/GetTestPackageDetail` |
|
||||||
|
| `check_remove/list` | ⚠️ 空页面(尾项检查及消项未开发) |
|
||||||
|
|
||||||
|
### 5.3 包装管理 packaging(组包)
|
||||||
|
|
||||||
|
- **状态机**:0 未到场 → 1 已发货 → 2 已到场。
|
||||||
|
- `list`:包装编号搜索 + 车次关联筛选 + 单位筛选;卡片含 `PackagingCode`、`State`、预制工作包、车次、数量、签收信息;FAB 进新增。
|
||||||
|
- `add`:先取号(`GetPackagingNumberByProjectId`)→ 填预制工作包、包装分类(字典 `GetPackagingCategories`)→ `POST PackagingManage/SavePackaging` → 跳详情。
|
||||||
|
- `detail`:`State==0` 时可**扫码添加预制组件**(扫 `PrePipeline$` 前缀码 → 查详情 → 防重 → `SavePipelineComponentToPackaging`)与删除;`from=0` 且 `isPower` 显示「确定到场」(`GetPackingInfoConfirmArrival`)。
|
||||||
|
|
||||||
|
### 5.4 发货管理 deliver(车次)
|
||||||
|
|
||||||
|
- **状态机**:0 待发货 → 1 已发货 → 2 已签收。
|
||||||
|
- `list`:单位筛选;卡片含 `TrainNumber`、状态标签、驾驶员/车牌/联系人;接口 `TrainNumberManage/GetTrainNumberList?preapitype=3`。
|
||||||
|
- `detail`(新增/编辑/发货/签收一体):
|
||||||
|
- 待发货:必填表单(车次/单位/驾驶员/车牌/联系人)→ `POST SaveTrainNumber`;可**扫码添加包装**(扫 `PackagingManage$` 码 → 弹窗确认 → `SavePackagingToTrain`);
|
||||||
|
- 底部按钮按状态切换:保存/发货 → 签收(`SaveTrainInfoConfirmArrival`)→ 只读。
|
||||||
|
- ⚠️ 已知 bug:`handleSign` 按位置参数调 `reqTrainInfoConfirmArrival(userId, id)`,但 api 签名为 `(params={})` 解构,签收参数会错。
|
||||||
|
|
||||||
|
### 5.5 预制组件管理 precast
|
||||||
|
|
||||||
|
- **状态机**:0 未验收 / 1 已验收 / 2 已出库 / -2 待整改 / -1 已整改。
|
||||||
|
- `list`:`u-tabs` 按五状态切换;卡片含图纸名、组件编号 `PipelineComponentCode`、物流箱号、计划安装日期、验收人。
|
||||||
|
- `detail`:组件信息展示;`from=0` + `isPower` + `State==0` 时显示验收区:通过/不通过(不通过须选 5 项硬编码验收意见之一:焊缝外观成形差/未酸洗/标识不全/污迹/未进行成品保护)→ `GetComponentConfirmArrival` 确认后回首页。
|
||||||
|
|
||||||
|
### 5.6 物流链串联
|
||||||
|
|
||||||
|
```
|
||||||
|
预制组件(扫码 PrePipeline$) → 加入包装(组包) → 包装(扫码 PackagingManage$) → 挂到车次(装车)
|
||||||
|
→ 发货 → 现场签收/包装到场确认 → 预制组件验收
|
||||||
|
```
|
||||||
|
|
||||||
|
## 六、scanpages 分包:扫码业务与工序链
|
||||||
|
|
||||||
|
### 6.1 扫码分流规则(首页 handleScan + utils/scanUtils.js)
|
||||||
|
|
||||||
|
| 扫码内容 | scanType | 去向 |
|
||||||
|
|---|---|---|
|
||||||
|
| 焊接接头二维码(URL 含 `weldjoint`,取 `id`) | QR_CODE | `daily_paper?id=`(先过岗位权限校验) |
|
||||||
|
| 其他二维码 | QR_CODE | toast「无对应业务」 |
|
||||||
|
| 材料条码(原文即材料编码) | 非 QR_CODE | `materials_detail?id=` |
|
||||||
|
| 菜单扫码(下料/组对/防腐入口) | 不限 | 取 URL 中 `id` 参数拼到目标页 |
|
||||||
|
|
||||||
|
### 6.2 工序互检链
|
||||||
|
|
||||||
|
```
|
||||||
|
下料抽检(焊口) → 组对抽查(焊口) → 焊接日报(焊口) → 防腐处理(材料)
|
||||||
|
每个页面可查看「上一工序记录」并跳转互检:
|
||||||
|
daily_paper → make_right → material_sampling → do_anti_rust
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6.3 各页面要点
|
||||||
|
|
||||||
|
| 页面 | id 含义 | 核心填报字段 | 提交接口 |
|
||||||
|
|---|---|---|---|
|
||||||
|
| `materials_detail` 材料详情 | 材料编码 | 只读档案(MaterialCode/炉号/批号/规格等)+ **蓝牙打印标签** | `BaseInfo/GetMaterialInfoByMaterialCode` |
|
||||||
|
| `material_sampling` 下料抽检 | WeldJointId | 下料长度、坡口形式/角度、材料编码与数量是否准确、检查结果(不合格填原因+整改)、备注、照片 | `POST PreWeldCuttingCheck/SaveRecord` |
|
||||||
|
| `make_right` 组对抽查 | WeldJointId | 坡口加工类型、组对间隙、错边量、检查结果、原因/整改、备注、照片 | `POST PreWeldFitupCheck/SaveRecord` |
|
||||||
|
| `daily_paper` 焊接日报 | WeldJointId | 焊口位置(字典)、焊接日期、焊工类型(打底/盖面)、焊工、焊接方法、焊前/焊后拍照;已有日报时可一键「点口」(`NDETrust/getManualPointSave`) | `POST PreWeldingDaily/SaveWeldingDailyByWeldJointId` |
|
||||||
|
| `do_anti_rust` 防腐处理 | MaterialCode | 防腐等级(联动带出中间漆/面漆)、漆膜厚度、喷砂/除锈情况、自检结果、备注、照片 | `POST AntiCorrosionCheck/SaveRecord` |
|
||||||
|
|
||||||
|
- 各工序页进入时拉对应记录列表回填(`GetRecordsByWeldJointId` / `GetRecordsByMaterialCode`),历史记录用 `nbd-record-card` 展示。
|
||||||
|
- 照片统一走 `nbd-photo-upload`(仅相机拍照)→ `FileUpload/Post` 上传 → 逗号分隔路径回写。
|
||||||
|
|
||||||
|
### 6.4 日报审核(daily_audit / daily_audit_detail)
|
||||||
|
|
||||||
|
焊工填报的日报先进入待审核(Temp)状态,由专工在小程序端审核,与 PC 端一致:
|
||||||
|
|
||||||
|
- **入口**:首页应用网格「日报审核」(`dailyAudit` 功能 key,见 §3.2)。
|
||||||
|
- **列表页**:筛选为单位工程(`nbd-select`)+ 焊接日期 + 管线编号 + 焊工编号;卡片展示焊口编号/管线编号/焊接日期/焊工/焊接方法/提交人/提交时间;支持勾选(含全选)后底部栏**批量审核通过 / 批量删除**;点卡片进详情。不分页,一次拉全部待审核记录。
|
||||||
|
- **详情页**:版式参照焊接日报(焊口主标识 + 焊口信息 + 日报信息,照片用 `nbd-photo-view` 只读展示焊前/焊后/附件),底部「审核通过 / 删除」单条操作。
|
||||||
|
- 接口(`api/hj.js`):
|
||||||
|
- `GET PreWeldingDaily/GetPendingWeldingDailyTempDetailList`(待审核列表:projectId 必填,unitWorkId/weldingDate/pipelineCode/welderCode/pageIndex 可选)
|
||||||
|
- `GET PreWeldingDaily/GetPendingWeldingDailyTempDetail`(单条明细)
|
||||||
|
- `POST PreWeldingDaily/AuditPendingWeldingDailyTempDetails`(批量审核:`{TempDetailIds, AuditMan}`)
|
||||||
|
- `POST PreWeldingDaily/DeletePendingWeldingDailyTempDetails`(批量删除:`{TempDetailIds}`)
|
||||||
|
|
||||||
|
### 6.5 标签打印(nbd-print-prop)
|
||||||
|
|
||||||
|
- 蓝牙热敏标签打印组件:bwip-js 生成 **PDF417** 条码(隐藏 canvas,203dpi 换算),经 `assets/js/js_sdk`(LPAPI 蓝牙打印机 SDK)绘制 50×30mm 标签(上文字 + 条码 + 下文字)并打印;支持打印机搜索、出纸方向、浓度/速度等参数。
|
||||||
|
- 微信小程序无原生 `atob`,`main.js` 顶部内联 polyfill(`utils/bwipjs-polyfill.js` 为双保险)。
|
||||||
|
- 目前仅材料详情页使用。
|
||||||
|
|
||||||
|
## 七、其他主包页面
|
||||||
|
|
||||||
|
- **我的 mine**:用户信息卡(姓名/账号/单位)、当前项目卡、退出登录;不调接口;个人设置/改密/关于已注释预留。
|
||||||
|
- **待办 todo**:按 `MenuName` 着色的待办卡片列表,点击按 `UrlStr` 拼参跳转。⚠️ 当前 `USE_MOCK = true` 用 mock 数据;真实接口 `ToDoItem/getToDoItemByProjectIdUserId` 代码已预留但未 import,切换前需补导入。
|
||||||
|
|
||||||
|
## 八、接口层分布(api/)
|
||||||
|
|
||||||
|
| 文件 | 职责 | 代表接口 |
|
||||||
|
|---|---|---|
|
||||||
|
| `auth.js` | 登录与菜单权限 | `user/postLoginOn`、`User/getMenuPowerList` |
|
||||||
|
| `user.js` | 用户相关 | `Project/getProjectsByUserId` |
|
||||||
|
| `base.js` | 基础数据字典 + 附件上传 | `BaseInfo/getProjectWorkArea`(单位工程)、`getWeldingLocation`(焊口位置)、`GetGrooveType`(坡口类型)、`Unit/getUnitByProjectIdUnitType`(单位)、`FileUpload/Post`(`uploadAttach`) |
|
||||||
|
| `hj.js` | 全业务接口合集(焊接/点口/包装/车次/预制/试压/扫码质检,30+ 个) | 见 §5、§6 各模块 |
|
||||||
|
|
||||||
|
请求封装 `utils/request.js`:自动带 token 头、GET 参数对象自动编码(兼容 URL 拼接旧风格)、默认 loading、`code!==1` 自动 toast + reject、`401` 自动登出;`parseAttachUrls` 解析逗号分隔附件为可展示列表。
|
||||||
|
|
||||||
|
## 九、状态管理(Pinia,组合式)
|
||||||
|
|
||||||
|
| Store | 状态 | 持久化 |
|
||||||
|
|---|---|---|
|
||||||
|
| `user` | `token`(=PersonId)、`userInfo`、`loginForm`、`projectList`、`currentProject`;watch 项目变化联动拉权限+看板 | `loginForm/userInfo/token/currentProject` |
|
||||||
|
| `menu` | `appsList`、`quickAppIds`、`editCache`、`menuProwerList`;`appVisible` 双重权限过滤;`hasPostPermission`/`canAccessPath` | 仅 `quickAppIds` |
|
||||||
|
| `large` | `hjIndexData`(焊接看板) | 否 |
|
||||||
|
|
||||||
|
## 十、公共组件(components/,easycom 自动注册)
|
||||||
|
|
||||||
|
| 组件 | 用途 |
|
||||||
|
|---|---|
|
||||||
|
| `nbd-select` | 底部弹窗选择器(单/多选、搜索),项目/单位/字典选择统一用它 |
|
||||||
|
| `nbd-record-card` | 通用记录卡片(text/tag/photo 字段、条件显示、合格状态着色),扫码工序页展示历史记录 |
|
||||||
|
| `nbd-check-btn` | 通过/不通过二选一按钮组 |
|
||||||
|
| `nbd-photo-upload` | 拍照上传(仅相机、最多 6 张、逗号分隔回写) |
|
||||||
|
| `nbd-photo-view` | 附件照片只读网格 + 预览 |
|
||||||
|
| `nbd-submit-bar` | 底部渐变提交按钮(带 loading 拦截) |
|
||||||
|
| `nbd-print-prop` | 蓝牙标签打印弹窗(scanpages 分包组件) |
|
||||||
|
|
||||||
|
## 十一、已知未完成项与问题清单
|
||||||
|
|
||||||
|
| 位置 | 问题 |
|
||||||
|
|---|---|
|
||||||
|
| `pipe/diankou/port_list.vue` | 自动点口/强制关闭/点口调整三个按钮为 TODO 桩 |
|
||||||
|
| `pipe/pressure/check_remove/list.vue` | 空页面,尾项检查及消项未开发 |
|
||||||
|
| `pipe/deliver/detail.vue` | 签收接口参数签名不匹配(位置参数 vs 对象解构),疑似 bug |
|
||||||
|
| `pages/todo/list.vue` | 使用 mock 数据,真实接口已预留未启用(且缺 import) |
|
||||||
|
| `pipe/deliver/list.vue` | 用 `onMounted` 而非页面级生命周期,与项目约定不符 |
|
||||||
|
| `make_right.vue` | 坡口类型下拉已写好但模板中仍是手输 input |
|
||||||
Reference in New Issue
Block a user