feat: 完善设计报工、质检及齐套跟踪

This commit is contained in:
2026-07-15 14:33:07 +08:00
parent 9e5819355d
commit 38771efb9f
7 changed files with 1200 additions and 79 deletions

View File

@@ -0,0 +1,528 @@
USE [YL_MESDB];
GO
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
IF COL_LENGTH(N'[dbo].[MES_设计报工_记录]', N'进度说明') IS NULL
BEGIN
ALTER TABLE [dbo].[MES_设计报工_记录] ADD [] nvarchar(500) NULL;
END
GO
IF COL_LENGTH(N'[dbo].[MES_设计报工_任务]', N'对齐可见ID') IS NULL
BEGIN
ALTER TABLE [dbo].[MES_设计报工_任务] ADD [ID] nvarchar(1000) NULL;
END
GO
IF COL_LENGTH(N'[dbo].[MES_设计报工_任务]', N'对齐可见') IS NULL
BEGIN
ALTER TABLE [dbo].[MES_设计报工_任务] ADD [] nvarchar(1000) NULL;
END
GO
IF OBJECT_ID(N'[dbo].[MES_设计报工_任务说明]', N'U') IS NULL
BEGIN
CREATE TABLE [dbo].[MES_设计报工_任务说明]
(
[SID] int IDENTITY(1,1) NOT NULL CONSTRAINT [PK_MES_设计报工_任务说明] PRIMARY KEY,
[DID] int NOT NULL,
[] nvarchar(20) NOT NULL,
[] nvarchar(2000) NOT NULL,
[ID] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] datetime NOT NULL CONSTRAINT [DF_MES_设计报工_任务说明_录入时间] DEFAULT (GETDATE()),
CONSTRAINT [FK_MES_设计报工_任务说明_任务] FOREIGN KEY ([DID])
REFERENCES [dbo].[MES_设计报工_任务]([DID]) ON DELETE CASCADE,
CONSTRAINT [CK_MES_设计报工_任务说明_类型] CHECK ([] IN (N'异常说明', N'奇思妙想'))
);
CREATE INDEX [IX_MES_设计报工_任务说明_DID_类型_时间]
ON [dbo].[MES_设计报工_任务说明]([DID], [], [], [SID]);
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务说明_新增]
@DID int,
@ nvarchar(20),
@ nvarchar(2000),
@ID nvarchar(100) = N'',
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
SET @ = LTRIM(RTRIM(ISNULL(@, N'')));
SET @ = LTRIM(RTRIM(ISNULL(@, N'')));
IF @ NOT IN (N'异常说明', N'奇思妙想')
BEGIN
SELECT CAST(0 AS int) AS [result], N'说明类型不正确' AS [message];
RETURN;
END
IF @ = N''
BEGIN
SELECT CAST(0 AS int) AS [result], N'说明内容不能为空' AS [message];
RETURN;
END
IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_任务] WHERE [DID] = @DID)
BEGIN
SELECT CAST(0 AS int) AS [result], N'任务不存在' AS [message];
RETURN;
END
INSERT INTO [dbo].[MES_设计报工_任务说明]
([DID], [], [], [ID], [])
VALUES
(@DID, @, @, NULLIF(@ID, N''), NULLIF(@, N''));
SELECT CAST(1 AS int) AS [result], N'保存成功' AS [message], CONVERT(int, SCOPE_IDENTITY()) AS [SID];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_查询]
@DID int = NULL,
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@_Start nvarchar(30) = N'',
@_End nvarchar(30) = N'',
@_Start nvarchar(30) = N'',
@_End nvarchar(30) = N'',
@ nvarchar(50) = N'',
@ID nvarchar(100) = N'',
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @1 datetime = TRY_CONVERT(datetime, NULLIF(@_Start, N''));
DECLARE @2 datetime = TRY_CONVERT(datetime, NULLIF(@_End, N''));
DECLARE @1 datetime = TRY_CONVERT(datetime, NULLIF(@_Start, N''));
DECLARE @2 datetime = TRY_CONVERT(datetime, NULLIF(@_End, N''));
SELECT TOP 1000
t.[DID],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[ID],
t.[],
t.[ID],
t.[],
CONVERT(varchar(19), t.[], 120) AS [],
CONVERT(varchar(19), t.[], 120) AS [],
t.[],
CONVERT(varchar(19), t.[], 120) AS [],
t.[],
t.[],
CONVERT(varchar(19), t.[], 120) AS [],
t.[],
ISNULL(r.[], 0) AS [],
ISNULL(r.[], 0) AS [],
ISNULL(r.[], 0) AS [],
ISNULL(p.[], N'') AS [],
CONVERT(varchar(19), r.[], 120) AS [],
CONVERT(varchar(19), r.[], 120) AS [],
ISNULL(progress_notes.[], N'') AS [],
ISNULL(task_notes.[], N'') AS [],
ISNULL(task_notes.[], N'') AS []
FROM [dbo].[MES_设计报工_任务] AS t
OUTER APPLY
(
SELECT
COUNT(1) AS [],
SUM(CASE WHEN rr.[] IS NULL THEN 1 ELSE 0 END) AS [],
SUM(CASE
WHEN rr.[] IS NULL
AND (
(NULLIF(@ID, N'') IS NOT NULL AND ISNULL(rr.[ID], N'') = @ID)
OR (NULLIF(@ID, N'') IS NULL AND NULLIF(@, N'') IS NOT NULL AND ISNULL(rr.[], N'') = @)
)
THEN 1 ELSE 0 END) AS [],
MAX(rr.[]) AS [],
MAX(rr.[]) AS []
FROM [dbo].[MES_设计报工_记录] AS rr
WHERE rr.[DID] = t.[DID]
) AS r
OUTER APPLY
(
SELECT STRING_AGG(CONVERT(nvarchar(max), x.[]), N'') AS []
FROM
(
SELECT DISTINCT COALESCE(NULLIF(rr2.[], N''), NULLIF(rr2.[ID], N''), N'未填写操作人') AS []
FROM [dbo].[MES_设计报工_记录] AS rr2
WHERE rr2.[DID] = t.[DID]
AND rr2.[] IS NULL
) AS x
) AS p
OUTER APPLY
(
SELECT STRING_AGG(
CONVERT(nvarchar(max), CONVERT(nvarchar(19), rr3.[], 120) + NCHAR(13) + NCHAR(10) + rr3.[]),
NCHAR(13) + NCHAR(10) + NCHAR(13) + NCHAR(10)
) WITHIN GROUP (ORDER BY rr3.[], rr3.[RID]) AS []
FROM [dbo].[MES_设计报工_记录] AS rr3
WHERE rr3.[DID] = t.[DID]
AND NULLIF(LTRIM(RTRIM(rr3.[])), N'') IS NOT NULL
) AS progress_notes
OUTER APPLY
(
SELECT
STRING_AGG(
CASE WHEN n.[] = N'异常说明'
THEN CONVERT(nvarchar(max), CONVERT(nvarchar(19), n.[], 120) + NCHAR(13) + NCHAR(10) + n.[]) END,
NCHAR(13) + NCHAR(10) + NCHAR(13) + NCHAR(10)
) WITHIN GROUP (ORDER BY n.[], n.[SID]) AS [],
STRING_AGG(
CASE WHEN n.[] = N'奇思妙想'
THEN CONVERT(nvarchar(max), CONVERT(nvarchar(19), n.[], 120) + NCHAR(13) + NCHAR(10) + n.[]) END,
NCHAR(13) + NCHAR(10) + NCHAR(13) + NCHAR(10)
) WITHIN GROUP (ORDER BY n.[], n.[SID]) AS []
FROM [dbo].[MES_设计报工_任务说明] AS n
WHERE n.[DID] = t.[DID]
) AS task_notes
WHERE
(@DID IS NULL OR @DID = 0 OR t.[DID] = @DID)
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR @ = N'全部' OR t.[] = @)
AND (@1 IS NULL OR t.[] >= @1)
AND (@2 IS NULL OR t.[] < DATEADD(day, 1, @2))
AND (@1 IS NULL OR t.[] >= @1)
AND (@2 IS NULL OR t.[] < DATEADD(day, 1, @2))
AND
(
(NULLIF(@ID, N'') IS NULL AND NULLIF(@, N'') IS NULL)
OR (NULLIF(@, N'') IS NOT NULL AND ISNULL(t.[], N'') = @)
OR
(
NULLIF(@ID, N'') IS NOT NULL
AND CHARINDEX(N',' + @ID + N',', N',' + ISNULL(t.[ID], N'') + N',') > 0
)
OR
(
NULLIF(@, N'') IS NOT NULL
AND CHARINDEX(N',' + @ + N',', N',' + ISNULL(t.[], N'') + N',') > 0
)
OR
(
NULLIF(@ID, N'') IS NOT NULL
AND CHARINDEX(N',' + @ID + N',', N',' + ISNULL(t.[ID], N'') + N',') > 0
)
OR
(
NULLIF(@, N'') IS NOT NULL
AND CHARINDEX(N',' + @ + N',', N',' + ISNULL(t.[], N'') + N',') > 0
)
)
ORDER BY t.[DID] DESC;
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_新增]
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(200) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N'',
@ nvarchar(100) = N'',
@ nvarchar(200) = N'',
@ nvarchar(max) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N'',
@ID nvarchar(1000) = N'',
@ nvarchar(1000) = N'',
@ nvarchar(30) = N'',
@ nvarchar(30) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N'',
@ID nvarchar(1000) = N'',
@ nvarchar(1000) = N''
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[MES_设计报工_任务]
(
[], [], [], [], [], [],
[], [], [],
[], [], [ID], [], [ID], [],
[], [], [],
[], [], [], []
)
VALUES
(
NULLIF(@, N''), NULLIF(@, N''), NULLIF(@, N''), NULLIF(@, N''), NULLIF(@, N''), NULLIF(@, N''),
NULLIF(@, N''), NULLIF(@, N''), NULLIF(@, N''),
NULLIF(@, N''), NULLIF(@, N''), NULLIF(@ID, N''), NULLIF(@, N''), NULLIF(@ID, N''), NULLIF(@, N''),
TRY_CONVERT(datetime, NULLIF(@, N'')), TRY_CONVERT(datetime, NULLIF(@, N'')), N'待开始',
NULLIF(@, N''), NULLIF(@, N''), GETDATE(), NULLIF(@, N'')
);
SELECT CAST(1 AS int) AS [result], N'新增成功' AS [message], SCOPE_IDENTITY() AS [DID];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_编辑]
@DID int,
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(200) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N'',
@ nvarchar(100) = N'',
@ nvarchar(200) = N'',
@ nvarchar(max) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N'',
@ID nvarchar(1000) = N'',
@ nvarchar(1000) = N'',
@ nvarchar(30) = N'',
@ nvarchar(30) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N'',
@ID nvarchar(1000) = N'',
@ nvarchar(1000) = N''
AS
BEGIN
SET NOCOUNT ON;
IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_任务] WHERE [DID] = @DID)
BEGIN
SELECT CAST(0 AS int) AS [result], N'任务不存在' AS [message];
RETURN;
END
UPDATE [dbo].[MES_设计报工_任务]
SET
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[] = NULLIF(@, N''),
[ID] = NULLIF(@ID, N''),
[] = NULLIF(@, N''),
[ID] = NULLIF(@ID, N''),
[] = NULLIF(@, N''),
[] = TRY_CONVERT(datetime, NULLIF(@, N'')),
[] = TRY_CONVERT(datetime, NULLIF(@, N'')),
[] = NULLIF(@, N''),
[] = GETDATE(),
[] = NULLIF(@, N'')
WHERE [DID] = @DID;
SELECT CAST(1 AS int) AS [result], N'编辑成功' AS [message];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_开始]
@DID int,
@ID nvarchar(100) = N'',
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT OFF;
DECLARE @ID nvarchar(100) = NULLIF(@ID, N'');
DECLARE @ nvarchar(100) = NULLIF(@, N'');
DECLARE @ nvarchar(255);
DECLARE @ int;
DECLARE @DID int;
DECLARE @ nvarchar(500);
DECLARE @RID int;
DECLARE @ int = @@TRANCOUNT;
DECLARE @ sysname = N'DRT_Task_Start';
IF @ID IS NULL AND @ IS NULL
BEGIN
SELECT CAST(0 AS int) AS [result], N'未获取到当前操作人,不能开始' AS [message];
RETURN;
END
SET @ = N'DesignReportTask:' + COALESCE(@ID, N'NAME:' + @);
BEGIN TRY
IF @ = 0 BEGIN TRANSACTION;
ELSE SAVE TRANSACTION @;
EXEC @ = sys.sp_getapplock
@Resource = @,
@LockMode = N'Exclusive',
@LockOwner = N'Transaction',
@LockTimeout = 10000;
IF @ < 0
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE ROLLBACK TRANSACTION @;
SELECT CAST(0 AS int) AS [result], N'开始校验繁忙,请稍后重试' AS [message];
RETURN;
END
IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_任务] WITH (UPDLOCK, HOLDLOCK) WHERE [DID] = @DID)
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE ROLLBACK TRANSACTION @;
SELECT CAST(0 AS int) AS [result], N'任务不存在' AS [message];
RETURN;
END
SELECT TOP 1
@DID = r.[DID],
@ = t.[]
FROM [dbo].[MES_设计报工_记录] AS r WITH (UPDLOCK, HOLDLOCK)
INNER JOIN [dbo].[MES_设计报工_任务] AS t ON t.[DID] = r.[DID]
WHERE r.[] IS NULL
AND (
(@ID IS NOT NULL AND ISNULL(r.[ID], N'') = @ID)
OR (@ID IS NULL AND @ IS NOT NULL AND ISNULL(r.[], N'') = @)
)
ORDER BY r.[] DESC, r.[RID] DESC;
IF @DID IS NOT NULL
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE ROLLBACK TRANSACTION @;
SELECT
CAST(0 AS int) AS [result],
N'任务 DID ' + CONVERT(nvarchar(20), @DID)
+ CASE WHEN NULLIF(@, N'') IS NULL THEN N'' ELSE N'' + @ + N'' END
+ N' 尚未关闭,请先结束该任务' AS [message],
@DID AS [DID];
RETURN;
END
INSERT INTO [dbo].[MES_设计报工_记录]([DID], [ID], [], [], [])
VALUES(@DID, @ID, @, GETDATE(), N'执行中');
SET @RID = CONVERT(int, SCOPE_IDENTITY());
UPDATE [dbo].[MES_设计报工_任务]
SET [] = N'执行中', [] = @, [] = GETDATE()
WHERE [DID] = @DID;
IF @ = 0 COMMIT TRANSACTION;
SELECT CAST(1 AS int) AS [result], N'开始成功' AS [message], @RID AS [RID];
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE IF XACT_STATE() = 1 ROLLBACK TRANSACTION @;
END
SELECT CAST(0 AS int) AS [result], ERROR_MESSAGE() AS [message];
END CATCH
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_结束]
@DID int,
@ID nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N''
AS
BEGIN
SET NOCOUNT ON;
SET XACT_ABORT OFF;
DECLARE @ID nvarchar(100) = NULLIF(@ID, N'');
DECLARE @ nvarchar(100) = NULLIF(@, N'');
DECLARE @RID int;
DECLARE @ int = @@TRANCOUNT;
DECLARE @ sysname = N'DRT_Task_End';
IF @ID IS NULL AND @ IS NULL
BEGIN
SELECT CAST(0 AS int) AS [result], N'未获取到当前操作人,不能结束' AS [message];
RETURN;
END
BEGIN TRY
IF @ = 0 BEGIN TRANSACTION;
ELSE SAVE TRANSACTION @;
IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_任务] WITH (UPDLOCK, HOLDLOCK) WHERE [DID] = @DID)
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE ROLLBACK TRANSACTION @;
SELECT CAST(0 AS int) AS [result], N'任务不存在' AS [message];
RETURN;
END
SELECT TOP 1 @RID = [RID]
FROM [dbo].[MES_设计报工_记录] WITH (UPDLOCK, HOLDLOCK)
WHERE [DID] = @DID
AND [] IS NULL
AND (
(@ID IS NOT NULL AND ISNULL([ID], N'') = @ID)
OR (@ID IS NULL AND @ IS NOT NULL AND ISNULL([], N'') = @)
)
ORDER BY [] DESC, [RID] DESC;
IF @RID IS NULL
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE ROLLBACK TRANSACTION @;
SELECT CAST(0 AS int) AS [result], N'当前人员没有未结束的报工记录' AS [message];
RETURN;
END
UPDATE [dbo].[MES_设计报工_记录]
SET
[] = GETDATE(),
[] = DATEDIFF(second, [], GETDATE()),
[] = N'已结束',
[] = NULLIF(LTRIM(RTRIM(@)), N'')
WHERE [RID] = @RID;
UPDATE [dbo].[MES_设计报工_任务]
SET
[] = CASE
WHEN EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_记录] WHERE [DID] = @DID AND [] IS NULL) THEN N'执行中'
ELSE N'已结束'
END,
[] = @,
[] = GETDATE()
WHERE [DID] = @DID;
IF @ = 0 COMMIT TRANSACTION;
SELECT CAST(1 AS int) AS [result], N'结束成功' AS [message], @RID AS [RID];
END TRY
BEGIN CATCH
IF XACT_STATE() <> 0
BEGIN
IF @ = 0 ROLLBACK TRANSACTION;
ELSE IF XACT_STATE() = 1 ROLLBACK TRANSACTION @;
END
SELECT CAST(0 AS int) AS [result], ERROR_MESSAGE() AS [message];
END CATCH
END
GO

View File

@@ -203,6 +203,7 @@ BEGIN
p2.[],
p2.[],
p2.[],
p2.[],
p2.[],
p2.[],
ISNULL(p2.[], 0) AS [],

View File

@@ -3186,3 +3186,259 @@ pm run build通过仅有既有警告。
### 结论
- 当前工作区内的设计工时报表导出、产品合格率工位菜单迁移、旧菜单脚本修正和对应中文日志已全部提交并上传到远程。
- 功能提交号为 `0784746`
### 验证结果
- `git diff --check` 通过。
- `git diff --cached --check` 通过。
- 凭据特征扫描结果为 0。
- 上传前本地与远端分叉为 `0 0`
- 推送后本地与远端同步,工作区无未提交修改。
## 2026-07-15 设计报工限制、重复报工及多类说明功能
### 用户提问
- 修改 `src/views/ProductionManagement/DesignReportTask/Report/index.vue`:一个人不能同时开始多个任务,点击开始时提示哪个任务未关闭。
- 任务点击完成后仍允许再次开始和结束,第二次开始、结束后也可以再次完成。
- 增加“异常说明”和“奇思妙想”功能,允许随时多次录入文字;列表按“时间换行内容”的格式显示,多次录入显示多条。
- “进度说明”采用与异常说明相同的列表显示格式。
- 将“未结束人员”改名为“设计正在对应”。
- 在设计任务页面同时显示异常说明、奇思妙想、进度说明和设计正在对应字段。
### 执行过程
1. 读取仓库根目录 `AGENTS.md`,确认本次执行结束后必须将提问、结论和完整执行过程以中文追加到 `gptlog-process/gpdlog.md`
2. 检查目标报工页、设计任务页、校验页、工时报表页、相关 SQL 增量脚本、项目命令和 Git 工作区状态。
3. 确认报工页原有逻辑只校验当前行的 `当前用户未结束报工数`,无法可靠阻止同一人员跨任务同时开始;前后端还把“已完成”作为禁止重新开始的终态。
4. 确认原有结束弹窗已经可以录入进度说明,数据库报工记录也已有对应字段,但任务查询和两个任务列表尚未聚合显示进度历史。
5. 确认异常说明和奇思妙想没有独立数据表及保存过程,不能仅靠前端完成持久化和多条历史展示,因此确定增加幂等数据库增量脚本。
6. 检查工作区已有改动,发现设计任务页存在用户未提交的表单布局调整,质量检验页面也存在无关修改;本次保留所有已有改动,只在设计任务页追加所需列表字段,并对该页原有布局改动做必要的空格格式整理。
7. 修改报工页列表:
- 将“未结束人员”列标题改为“设计正在对应”,继续使用原有 `未结束报工人员` 返回字段。
- 新增进度说明、异常说明和奇思妙想三列。
- 三列使用保留换行的样式展示历史内容。
8. 修改报工页操作区:
- “开始”按钮不再因任务已完成而禁用。
- 新增“异常说明”和“奇思妙想”两个文字按钮。
- 新增通用说明录入弹窗,显示 DID 和任务描述,内容必填,最多 2000 字。
- 保存时调用新增存储过程,并携带当前操作人 ID 和姓名。
9. 增加开始前全任务实时查询:如果当前人员已有任何未结束记录,提示“任务 DID + 任务描述尚未关闭,请先结束该任务”;查询失败时阻止开始,避免绕过校验。
10. 保留结束按钮仅在当前任务存在本人未结束记录时启用;已完成任务重新开始后状态变为执行中,结束后变为已结束,因此可以再次点击完成。
11. 修改设计任务页列表,新增“设计正在对应”、进度说明、异常说明和奇思妙想四列,展示格式与报工页一致。
12. 新增 `db_backups/update_design_report_task_notes_and_restart_20260715.sql`
- 幂等补齐报工记录的进度说明字段。
- 新建 `MES_设计报工_任务说明` 表,保存异常说明和奇思妙想的多条记录、操作人及录入时间。
- 新建 `设计报工_任务说明_新增` 保存过程,校验任务、说明类型和非空内容。
- 重建 `设计报工_任务_查询`,聚合进度说明、异常说明和奇思妙想,单条格式为“时间 + 换行 + 内容”,多条之间留空行。
- 重建设计报工开始过程,取消已完成任务禁止开始的限制。
- 开始过程使用按人员标识生成的 `sp_getapplock` 事务锁,防止两个页面并发点击时同时产生两条未结束记录。
- 开始过程跨全部任务检查当前人员的未结束记录,返回未关闭 DID 和任务描述。
- 重建设计报工结束过程,允许重新开始后的任务结束,并按现有方式保存本轮进度说明。
13. 首次执行两目标页面 ESLint 时,报工页无错误;设计任务页报告用户原有布局调整中的多余空格、空行和异步箭头函数格式问题。
14. 对设计任务页做最小格式整理后,再次执行两目标页面 ESLint检查通过仅输出项目依赖的 Browserslist 和 Baseline 数据过期提示。
15. 对三个目标文件执行 `git diff --check`,检查通过;全工作区检查仍能看到无关的 `OtherInbound.vue` 原有尾随空格,本次没有修改该文件。
16. 执行 `npm run build`webpack 生产构建成功;仅有项目原有的大资源体积警告和浏览器兼容数据过期提示,构建没有留下受版本控制的 `dist` 改动。
17. 尝试使用当前 Windows 集成身份对目标数据库 `192.168.2.92 / YL_MESDB` 做只读连通性检查,服务器拒绝 Guest 身份登录;未猜测或查找数据库凭据,也未向目标数据库发布脚本。
18. 检查本地开发服务,确认进程来自当前仓库,访问 `https://localhost:1997/` 返回 HTTP 200。
19. 为验证 SQL在独立 LocalDB 测试实例中创建最小基础表。前两次使用 PowerShell 标准输入传递中文 SQL 时发生代码页解析错误,均未进入增量脚本有效验证;每次都在 `finally` 中删除测试实例,随后核对并清理由第一次测试生成的 MDF/LDF 文件。
20. 改用 UTF-8 SQL 测试夹具和 `sqlcmd -i -f 65001` 重跑隔离测试,增量脚本编译及业务场景验证通过:
- 状态为已完成的任务可以重新开始。
- 同一人员未结束第一项任务时开始第二项任务,被正确拦截并返回第一项任务的 DID 和描述。
- 第一项任务可以正常结束并保存进度说明,状态回到已结束。
- 连续保存两条异常说明和一条奇思妙想均成功。
- 任务查询按要求返回进度说明、两条异常说明和奇思妙想的“时间换行内容”历史。
21. 验证结束后删除临时 SQL 测试夹具、LocalDB 实例及测试数据文件,确认不保留测试数据。
22. 最终检查目标文件状态和差异,确认未修改用户无关的质量检验页面,未提交或推送任何文件。
### 修改文件
- `src/views/ProductionManagement/DesignReportTask/Report/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Task/index.vue`
- `db_backups/update_design_report_task_notes_and_restart_20260715.sql`
- `gptlog-process/gpdlog.md`
### 结论
- 同一人员只能保留一个未结束的设计报工任务,前端会提示具体未关闭任务,数据库事务锁同时保证并发场景不会绕过限制。
- 已完成任务可以重新开始、结束,并在新一轮结束后再次完成。
- 异常说明和奇思妙想支持在任意任务状态下多次录入;进度说明、异常说明和奇思妙想均按“时间换行内容”显示多条历史。
- 报工页和设计任务页都已显示进度说明、异常说明、奇思妙想和“设计正在对应”。
- 前端代码和数据库增量脚本均已在本机验证;由于当前身份没有目标 SQL Server 登录权限,增量脚本尚未发布到目标数据库,目标环境启用新功能前必须执行该脚本。
### 验证结果
- 两目标页面 ESLint 检查通过。
- 三个目标文件 `git diff --check` 通过。
- `npm run build` 生产构建通过。
- 隔离 LocalDB 中增量脚本编译通过,重新开始、跨任务拦截、结束及多条说明聚合场景验证通过。
- `https://localhost:1997/` 返回 HTTP 200本地开发服务保持运行。
## 2026-07-15 发布设计报工增量脚本到目标数据库
### 用户提问
- 用户提供目标数据库地址 `192.168.2.92`、数据库管理员账号及密码,要求继续完成数据库发布。
- 按安全要求,本日志不记录数据库明文密码。
### 执行过程
1. 使用用户提供的 SQL Server 凭据连接 `192.168.2.92 / YL_MESDB`,先执行只读预检。
2. 预检确认目标数据库为 `YL_MESDB`,服务器为 `YLLT-MES`,数据库兼容级别为 150。
3. 确认 `MES_设计报工_任务``MES_设计报工_记录` 和记录表的 `进度说明` 字段已经存在;`MES_设计报工_任务说明` 表和 `设计报工_任务说明_新增` 过程尚不存在。
4. 确认设计报工查询、开始、结束、完成过程均存在,其中查询和开始过程仍为本次修改前的旧版本。
5. 使用 `sqlcmd` 的失败即退出模式和 UTF-8 输入模式执行 `db_backups/update_design_report_task_notes_and_restart_20260715.sql`,脚本发布成功。
6. 发布后检查数据库对象定义,确认:
- 任务说明表已创建。
- 任务说明保存过程已创建。
- 开始过程已包含 `sp_getapplock` 人员并发锁。
- 查询过程已包含异常说明、奇思妙想和进度说明聚合。
- 开始过程已移除“任务已完成,不能开始”的旧限制。
7. 在目标数据库外层事务中插入两条临时设计任务,执行完整业务验证:
- 状态为已完成的第一条任务开始成功。
- 同一测试人员在第一条任务未结束时开始第二条任务,被正确拦截,返回第一条任务 DID 和任务描述。
- 第一条任务结束成功并保存第一轮进度,随后完成成功。
- 第一条任务第二次开始、结束并保存第二轮进度,随后再次完成成功。
- 连续新增两条异常说明和一条奇思妙想,三次保存均成功。
- 任务查询返回两次报工记录、最终已完成状态、两轮进度说明、两条异常说明和一条奇思妙想;显示内容符合“时间换行内容”的多条格式。
8. 回滚外层测试事务,并查询确认名称以 `Codex发布验证_` 开头的测试任务数量为 0没有向正式库遗留测试任务、报工记录或说明记录。
9. 检查本地工作区,数据库发布没有生成新的临时文件或构建产物;保留用户原有的无关工作区修改。
### 结论
- `update_design_report_task_notes_and_restart_20260715.sql` 已成功发布到 `192.168.2.92 / YL_MESDB`
- 同一人员跨任务同时开始限制、未关闭任务提示、已完成任务重新开始和再次完成、进度说明历史、异常说明及奇思妙想多条录入功能均已在目标数据库验证通过。
- 验证数据已全部回滚,正式数据库无测试数据残留。
### 验证结果
- 数据库对象和过程定义检查通过。
- 两轮“开始、结束、完成”验证通过。
- 跨任务重复开始拦截验证通过。
- 多条进度、异常说明和奇思妙想聚合验证通过。
- 回滚后测试任务数量为 0。
## 2026-07-15 设计报工按钮、说明悬停及任务可见范围调整
### 用户提问
- 设计报工点击开始后,当前任务的开始按钮应变为灰色且不可点击。
- 进度说明、异常说明和奇思妙想在列表正常显示时应单行省略,避免撑高行高;鼠标悬停对应字段时显示完整内容。
- 设计任务新建弹窗需在指派对象前增加“对齐可见”字段,并使用与指派对象相同的人员多选方式。
- 设计报工页面根据登录账号限制任务范围,只显示本人创建、对齐可见包含本人以及指派对象包含本人的任务。
### 执行过程
1. 重新检查报工页和设计任务页现有模板、数据模型、人员查询、任务新增/编辑参数及目标数据库过程结构。
2. 检查登录流程和 Vuex 用户状态,确认登录态 `id` 来源于 `Personnel_Number`,与设计任务人员选择器使用的 `人员编号`一致,可以直接用于对齐可见和指派对象精确匹配。
3. 调整设计报工开始按钮:
- 恢复 `canStart` 行级判断。
- 当前行 `当前用户未结束报工数` 大于 0 时开始按钮禁用并显示为灰色。
- 其他任务的开始按钮仍可点击,继续保留提示具体未关闭任务的逻辑。
4. 调整报工页和设计任务页的三类说明展示:
- 进度说明、异常说明和奇思妙想正常状态使用单行、溢出隐藏和省略号,不再撑高表格行。
- 每个字段外层增加 Element UI Tooltip非空内容悬停时显示完整历史。
- Tooltip 内容保留原有换行,设置最大宽度、最大高度、自动纵向滚动和长文本换行。
5. 在设计任务列表增加“对齐可见”列,便于维护人员直接确认任务可见范围。
6. 在设计任务新增/编辑弹窗的“指派对象”之前增加“对齐可见”多选人员字段:
- 使用独立的远程人员选项集合,避免与指派对象搜索互相覆盖。
- 保存人员编号列表到 `对齐可见ID`,保存人员姓名列表到 `对齐可见`
- 编辑时还原已选人员,并补齐当前远程列表中不存在的已选项。
- 每次打开新建弹窗时刷新对齐可见人员列表。
7. 扩展数据库增量脚本:
- 幂等增加任务表 `对齐可见ID``对齐可见` 两个字段。
- 查询过程返回两个新字段。
- 重建任务新增和编辑过程,支持保存及修改对齐可见人员。
- 仅当查询传入当前登录人员时应用报工页可见范围;不传人员的设计任务维护页继续返回全部任务。
8. 第一版可见范围按用户最初要求实现为“本人创建或对齐可见包含本人”。用户随后补充“指派对象的任务也可见”,立即终止正在进行的旧版本构建,避免把不完整版本作为最终验证结果。
9. 将查询可见范围扩展为三种关系的并集:
- 当前人员姓名等于创建人。
- 当前人员编号或姓名存在于对齐可见列表。
- 当前人员编号或姓名存在于指派对象列表。
10. 使用隔离 LocalDB 对第一版字段和查询规则进行验证:
- 不传当前人员时维护页返回全部三条任务。
- 创建人只能看到本人创建任务。
- 同时具有创建和对齐关系的人员返回两条任务。
- 仅对齐可见人员返回对应任务。
- 无任何关系人员返回 0 条。
- 编辑对齐可见后,新人员立即能查询到任务,并返回对齐可见字段。
11. 用户补充指派对象规则后,再次使用隔离 LocalDB 验证:
- 指派对象列表包含当前人员时能返回对应任务。
- 无创建、对齐或指派关系的人员返回 0 条。
12. 两次 LocalDB 验证均使用独立临时实例;验证后删除 SQL 测试夹具、实例及 MDF/LDF 文件,没有遗留测试资源。
13. 执行两目标页面 ESLint检查通过仅输出项目依赖的 Browserslist 和 Baseline 数据过期提示。
14. 对目标前端文件和数据库脚本执行 `git diff --check`,检查通过。
15. 执行 `npm run build`;用户补充指派对象规则前的构建被主动终止,补齐最终规则后重新执行生产构建并成功通过,仅有项目原有的大资源体积及浏览器数据过期警告。
16. 使用用户此前提供的数据库凭据,将扩展后的幂等脚本重新发布到 `192.168.2.92 / YL_MESDB`,发布成功;日志不记录明文密码。
17. 在目标数据库检查确认:
- 两个对齐可见字段已经存在。
- 查询过程包含指派对象可见逻辑。
- 新增和编辑过程均包含对齐可见参数。
18. 在目标数据库外层事务中执行正式环境验证:
- 本人创建任务查询返回 1 条。
- 对齐可见任务查询返回 1 条。
- 指派对象任务查询返回 1 条。
- 无关系人员查询返回 0 条。
- 不传人员的设计任务维护查询仍返回指定任务。
19. 回滚目标数据库测试事务,确认 `Codex可见验证_` 测试任务残留数量为 0。
20. 最终再次执行 ESLint、生产构建、目标文件空白检查和本地开发服务访问检查全部通过`https://localhost:1997/` 返回 HTTP 200。
### 修改文件
- `src/views/ProductionManagement/DesignReportTask/Report/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Task/index.vue`
- `db_backups/update_design_report_task_notes_and_restart_20260715.sql`
- `gptlog-process/gpdlog.md`
### 结论
- 当前人员开始任务后,该任务行的开始按钮会立即在刷新后变灰并不可点击;其他任务仍可点击并提示未关闭任务。
- 三类说明列表保持单行省略,悬停可查看保留换行的完整内容,不再导致表格行高过高。
- 设计任务新增和编辑弹窗已支持“对齐可见”人员多选,并在列表显示选中人员。
- 设计报工页面只显示本人创建、对齐可见包含本人或指派对象包含本人的任务;设计任务维护页仍显示全部任务。
- 数据库字段和过程已发布到目标库,正式环境事务验证通过且无测试数据残留。
### 验证结果
- 两目标页面 ESLint 检查通过。
- 目标文件 `git diff --check` 通过。
- 最终 `npm run build` 生产构建通过。
- 隔离 LocalDB 的新增、编辑、创建人可见、对齐可见和指派可见场景通过。
- 目标数据库三类可见关系及维护页全量查询验证通过。
- 目标数据库回滚后测试任务数量为 0。
- `https://localhost:1997/` 返回 HTTP 200。
## 2026-07-15 修复及时齐套生产订单 7912 工艺路线颜色
### 用户提问
- 修改 `PlanManagement/TimelyKitTrackingResult/index`
- 搜索销售订单 `261079` 后展开子项,生产订单 `7912` 的工艺路线状态不正确。
- 第 4 序已经完成 5 个,应显示蓝色;第 5 序已经发料,应显示绿色。
- 要求参考“生产计划跟踪”页面搜索生产订单 `7912` 时的工艺路线。
### 执行过程
1. 检查 `src/views/PlanManagement/TimelyKitTrackingResult/index.vue`、参考页面 `src/views/ProductionManagement/ProductionPlanTrack/index.vue`、及时齐套查询脚本和原项目验收文档。
2. 对比两页的工艺路线前端算法,确认蓝色、绿色、红色判断和连续外协分组处理逻辑完全一致:
- 收检合格数大于 0、报工或辅助结束显示蓝色。
- 外协工序收料数大于收检合格数与不合格数之和时显示绿色。
- 连续且 `外协分组` 相同的工序统一采用该组最后一道工序的颜色。
3. 确认及时齐套页面不直接计算数据库状态,而是解析 `生产管理_及时齐套跟踪结果_查询` 返回的 `工艺路线明细` JSON 后着色。
4. 查询目标数据库过程参数和生产订单 `7912``View_生产订单_MES` 原始工序数据。首次查询误用了视图不存在的 `开始时间` 字段而失败,删除该字段后重新查询成功。
5. 原始数据确认:
- 第 4 序数铣,计划数 5、完成数 5、收料数 5、收检合格数 5任务状态为已完成应显示蓝色。
- 第 5 序调质,收料数 5、收检数 0、任务状态为已开工应显示绿色。
- 第 6 序喷砂尚未开始,应显示红色。
6. 执行参考过程 `生产管理_生产计划跟踪` 查询订单 `7912`,确认参考数据包含 `外协分组`
- 第 2 至第 4 序的外协分组为空,属于同一连续组,跟随第 4 序显示蓝色。
- 第 5 序外协分组为 2独立显示绿色。
- 第 6 序外协分组为 3独立显示红色。
7. 执行及时齐套查询过程查询销售订单 `261079`。首次命令同时使用了互斥的 `sqlcmd -W``-y` 选项而失败,修正选项后重新执行成功。
8. 检查及时齐套对生产订单 `7912` 的实际返回 JSON确认完成数、收料数、收检数均正确但每道工序都缺少 `外协分组` 字段。
9. 定位根因:前端把缺少分组字段的第 2 至第 6 序全部视为同一个连续外协组,最终全部跟随第 6 序显示红色;因此不是页面蓝绿基础判断错误,而是后端 JSON 字段缺失。
10. 修改当前最新及时齐套过程脚本 `db_backups/update_timely_kit_tracking_result_multi_detail_orders_20260630.sql`,在 `工艺路线明细` JSON 中增加 `p2.[外协分组]`
11. 发布前执行差异和空白检查,确认脚本只增加一个返回字段,不改变筛选、缺件匹配或其他统计口径;目标库当前过程定义检查结果为确实缺少该字段。
12. 使用用户此前提供的数据库凭据,将修改后的过程脚本发布到 `192.168.2.92 / YL_MESDB`;日志不记录明文密码。
13. 发布后重新执行销售订单 `261079` 的及时齐套查询,从实际过程输出中提取生产订单 `7912` 的工艺路线 JSON并按页面当前算法复算
- 第 4 序数铣:外协第一组,收检合格 5最终颜色为蓝色。
- 第 5 序调质:外协分组 2收料 5、收检 0最终颜色为绿色。
- 第 6 序喷砂:外协分组 3未收料未收检最终颜色为红色。
14. 检查目标数据库过程定义,确认 `p2.[外协分组]` 已发布。
15. 执行及时齐套页面 ESLint检查无错误仅保留页面原有 `v-html` 安全规则警告和项目依赖数据过期提示。
16. 执行数据库脚本 `git diff --check`,检查通过;访问本地开发服务 `https://localhost:1997/` 返回 HTTP 200。
17. 保留工作区中用户已有的设计报工和质量检验相关修改,本次未改动或回退这些无关文件。
### 修改文件
- `db_backups/update_timely_kit_tracking_result_multi_detail_orders_20260630.sql`
- `gptlog-process/gpdlog.md`
### 结论
- `TimelyKitTrackingResult/index.vue` 的现有颜色算法与生产计划跟踪一致,无需重复修改前端算法。
- 实际问题是及时齐套查询返回的工艺路线 JSON 漏掉 `外协分组`,导致多个不同外协组被错误合并并统一显示红色。
- 字段已补齐并发布到目标数据库;销售订单 `261079`、生产订单 `7912` 现在第 4 序显示蓝色,第 5 序显示绿色,第 6 序显示红色,与生产计划跟踪一致。

View File

@@ -98,16 +98,42 @@
<el-table-column align="center" label="预计结束" prop="预计结束时间" width="150" />
<el-table-column align="center" label="报工次数" prop="报工次数" width="90" />
<el-table-column align="center" label="未结束" prop="未结束报工数" width="80" />
<el-table-column align="left" label="未结束人员" prop="未结束报工人员" width="150" show-overflow-tooltip />
<el-table-column align="left" label="设计正在对应" prop="未结束报工人员" width="150" show-overflow-tooltip />
<el-table-column align="left" label="进度说明" prop="进度说明" width="240">
<template slot-scope="scope">
<el-tooltip :disabled="!scope.row.进度说明" effect="dark" placement="top" :open-delay="300">
<div slot="content" class="note-tooltip-content">{{ scope.row.进度说明 }}</div>
<div class="note-history">{{ scope.row.进度说明 }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="left" label="异常说明" prop="异常说明" width="240">
<template slot-scope="scope">
<el-tooltip :disabled="!scope.row.异常说明" effect="dark" placement="top" :open-delay="300">
<div slot="content" class="note-tooltip-content">{{ scope.row.异常说明 }}</div>
<div class="note-history">{{ scope.row.异常说明 }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="left" label="奇思妙想" prop="奇思妙想" width="240">
<template slot-scope="scope">
<el-tooltip :disabled="!scope.row.奇思妙想" effect="dark" placement="top" :open-delay="300">
<div slot="content" class="note-tooltip-content">{{ scope.row.奇思妙想 }}</div>
<div class="note-history">{{ scope.row.奇思妙想 }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" label="最后开始" prop="最后开始时间" width="150" />
<el-table-column align="center" label="最后结束" prop="最后结束时间" width="150" />
<el-table-column align="left" label="设计要求" prop="设计要求" width="220" show-overflow-tooltip />
<el-table-column align="center" fixed="right" label="操作" width="210">
<el-table-column align="center" fixed="right" label="操作" width="330">
<template slot-scope="scope">
<div class="design-action-buttons">
<el-button type="text" size="mini" :disabled="!canStart(scope.row)" @click="startTask(scope.row)">开始</el-button>
<el-button type="text" size="mini" :disabled="actionLoading || !canStart(scope.row)" @click="startTask(scope.row)">开始</el-button>
<el-button type="text" size="mini" :disabled="!canEnd(scope.row)" @click="endTask(scope.row)">结束</el-button>
<el-button type="text" size="mini" :disabled="!canComplete(scope.row)" @click="completeTask(scope.row)">完成</el-button>
<el-button type="text" size="mini" @click="openNoteDialog(scope.row, '异常说明')">异常说明</el-button>
<el-button type="text" size="mini" @click="openNoteDialog(scope.row, '奇思妙想')">奇思妙想</el-button>
</div>
</template>
</el-table-column>
@@ -150,6 +176,37 @@
<el-button type="primary" :loading="actionLoading" @click="confirmEndTask">确认</el-button>
</div>
</el-dialog>
<el-dialog
:visible.sync="noteDialogVisible"
:title="noteForm.说明类型"
width="620px"
center
:close-on-click-modal="false"
>
<el-form :model="noteForm" label-width="100px" size="small">
<el-form-item label="DID">
<el-input v-model="noteForm.DID" disabled />
</el-form-item>
<el-form-item label="任务描述">
<el-input v-model="noteForm.任务描述" type="textarea" :rows="2" disabled />
</el-form-item>
<el-form-item :label="noteForm.说明类型">
<el-input
v-model="noteForm.说明内容"
type="textarea"
:rows="5"
maxlength="2000"
show-word-limit
:placeholder="`请输入${noteForm.说明类型}`"
/>
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="noteDialogVisible = false">取消</el-button>
<el-button type="primary" :loading="actionLoading" @click="confirmNote">保存</el-button>
</div>
</el-dialog>
</div>
</template>
@@ -161,6 +218,7 @@ export default {
loading: false,
actionLoading: false,
endDialogVisible: false,
noteDialogVisible: false,
tableData: [],
projectOptions: [],
materialOptions: [],
@@ -172,6 +230,12 @@ export default {
任务描述: '',
进度说明: ''
},
noteForm: {
DID: '',
任务描述: '',
说明类型: '',
说明内容: ''
},
searchForm: {
did: '',
projectNo: '',
@@ -258,28 +322,26 @@ export default {
this.parentMaterialOptions = []
}
},
canStart(row) {
return row.单据状态 !== '已完成' && Number(row.当前用户未结束报工数 || 0) === 0
},
canEnd(row) {
return Number(row.当前用户未结束报工数 || 0) > 0
},
canStart(row) {
return Number(row.当前用户未结束报工数 || 0) === 0
},
canComplete(row) {
return row.单据状态 !== '已完成' && Number(row.报工次数 || 0) > 0
},
async startTask(row) {
const openTask = await this.getCurrentOpenTask()
if (openTask === false) return
if (openTask) {
const description = openTask.任务描述 ? `${openTask.任务描述}` : ''
this.$message.warning(`任务 DID ${openTask.DID}${description} 尚未关闭,请先结束该任务`)
return
}
const latest = await this.getLatestTask(row.DID)
if (!latest) return
Object.assign(row, latest)
if (latest.单据状态 === '已完成') {
this.$message.error('任务已完成,不能开始')
this.searchTable()
return
}
if (Number(latest.当前用户未结束报工数 || 0) > 0) {
this.$message.warning('当前人员已存在未结束的报工记录')
return
}
this.runAction('设计报工_任务_开始', [
['DID', latest.DID],
['操作人ID', this.currentUserId()],
@@ -316,6 +378,30 @@ export default {
this.endDialogVisible = false
}
},
openNoteDialog(row, type) {
this.noteForm = {
DID: row.DID,
任务描述: row.任务描述 || '',
说明类型: type,
说明内容: ''
}
this.noteDialogVisible = true
},
async confirmNote() {
const content = String(this.noteForm.说明内容 || '').trim()
if (!content) {
this.$message.warning(`请输入${this.noteForm.说明类型}`)
return
}
const success = await this.runAction('设计报工_任务说明_新增', [
['DID', this.noteForm.DID],
['说明类型', this.noteForm.说明类型],
['说明内容', content],
['操作人ID', this.currentUserId()],
['操作人', this.currentUserName()]
], '保存成功')
if (success) this.noteDialogVisible = false
},
async completeTask(row) {
const latest = await this.getLatestTask(row.DID)
if (!latest) return
@@ -375,6 +461,32 @@ export default {
return null
}
},
async getCurrentOpenTask() {
const params = [
['DID', 0],
['项目号', ''],
['物料编码', ''],
['图号', ''],
['类别', ''],
['关联父件物料编码', ''],
['预计开始时间_Start', ''],
['预计开始时间_End', ''],
['预计结束时间_Start', ''],
['预计结束时间_End', ''],
['单据状态', ''],
['当前操作人ID', this.currentUserId()],
['当前操作人', this.currentUserName()]
]
const data = this.CreateData('11', '设计报工_任务_查询', params)
try {
const response = await this.ExecDatabase(data)
return (response.data || []).find(item => Number(item.当前用户未结束报工数 || 0) > 0) || null
} catch (error) {
console.error('当前人员未结束任务查询失败:', error)
this.$message.error('开始前校验失败')
return false
}
},
async runAction(procedure, params, defaultMessage) {
if (this.actionLoading) return
this.actionLoading = true
@@ -458,4 +570,22 @@ export default {
.design-action-buttons ::v-deep .el-button + .el-button {
margin-left: 0;
}
.note-history {
width: 100%;
min-height: 20px;
line-height: 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.note-tooltip-content {
max-width: 520px;
max-height: 60vh;
line-height: 20px;
white-space: pre-line;
overflow-y: auto;
overflow-wrap: anywhere;
}
</style>

View File

@@ -130,11 +130,37 @@
<el-table-column align="left" label="设计要求" prop="设计要求" width="220" show-overflow-tooltip />
<el-table-column align="left" label="研发立项号" prop="研发立项号" width="130" show-overflow-tooltip />
<el-table-column align="left" label="研发目的" prop="研发目的" width="200" show-overflow-tooltip />
<el-table-column align="left" label="对其可见" prop="对齐可见" width="180" show-overflow-tooltip />
<el-table-column align="left" label="指派对象" prop="指派对象" width="180" show-overflow-tooltip />
<el-table-column align="center" label="预计开始" prop="预计开始时间" width="150" />
<el-table-column align="center" label="预计结束" prop="预计结束时间" width="150" />
<el-table-column align="center" label="报工次数" prop="报工次数" width="90" />
<el-table-column align="center" label="未结束" prop="未结束报工数" width="80" />
<el-table-column align="left" label="设计正在对应" prop="未结束报工人员" width="150" show-overflow-tooltip />
<el-table-column align="left" label="进度说明" prop="进度说明" width="240">
<template slot-scope="scope">
<el-tooltip :disabled="!scope.row.进度说明" effect="dark" placement="top" :open-delay="300">
<div slot="content" class="note-tooltip-content">{{ scope.row.进度说明 }}</div>
<div class="note-history">{{ scope.row.进度说明 }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="left" label="异常说明" prop="异常说明" width="240">
<template slot-scope="scope">
<el-tooltip :disabled="!scope.row.异常说明" effect="dark" placement="top" :open-delay="300">
<div slot="content" class="note-tooltip-content">{{ scope.row.异常说明 }}</div>
<div class="note-history">{{ scope.row.异常说明 }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="left" label="奇思妙想" prop="奇思妙想" width="240">
<template slot-scope="scope">
<el-tooltip :disabled="!scope.row.奇思妙想" effect="dark" placement="top" :open-delay="300">
<div slot="content" class="note-tooltip-content">{{ scope.row.奇思妙想 }}</div>
<div class="note-history">{{ scope.row.奇思妙想 }}</div>
</el-tooltip>
</template>
</el-table-column>
<el-table-column align="center" label="创建日期" prop="创建日期" width="150" />
<el-table-column align="left" label="创建人" prop="创建人" width="110" show-overflow-tooltip />
<el-table-column align="left" label="备注" prop="备注" width="180" show-overflow-tooltip />
@@ -168,6 +194,73 @@
<el-input v-model="formData.创建日期" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类别">
<el-input v-model="formData.类别" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="任务描述" prop="任务描述">
<el-input v-model="formData.任务描述" type="textarea" :rows="2" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="设计要求">
<el-input v-model="formData.设计要求" type="textarea" :rows="3" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="对其可见">
<el-select
v-model="formData.visibilityIds"
clearable
filterable
multiple
remote
:remote-method="queryVisibilityPersonnel"
style="width: 100%"
@change="handleVisibilityChange"
>
<el-option
v-for="item in visibilityPersonnelOptions"
:key="item.人员编号"
:label="formatPersonLabel(item)"
:value="item.人员编号"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="指派对象" prop="assigneeIds">
<el-select
v-model="formData.assigneeIds"
clearable
filterable
multiple
remote
:remote-method="queryPersonnel"
style="width: 100%"
@change="handleAssigneeChange"
>
<el-option
v-for="item in personnelOptions"
:key="item.人员编号"
:label="formatPersonLabel(item)"
:value="item.人员编号"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计开始时间">
<el-date-picker v-model="formData.预计开始时间" type="date" value-format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计结束时间">
<el-date-picker v-model="formData.预计结束时间" type="date" value-format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目号">
<el-select
@@ -215,16 +308,7 @@
<el-input v-model="formData.图号" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="类别">
<el-input v-model="formData.类别" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="任务描述" prop="任务描述">
<el-input v-model="formData.任务描述" type="textarea" :rows="2" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="父件物料编码">
<el-select
@@ -260,42 +344,7 @@
<el-input v-model="formData.研发目的" type="textarea" :rows="2"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="指派对象" prop="assigneeIds">
<el-select
v-model="formData.assigneeIds"
clearable
filterable
multiple
remote
:remote-method="queryPersonnel"
style="width: 100%"
@change="handleAssigneeChange"
>
<el-option
v-for="item in personnelOptions"
:key="item.人员编号"
:label="formatPersonLabel(item)"
:value="item.人员编号"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计开始时间">
<el-date-picker v-model="formData.预计开始时间" type="date" value-format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="预计结束时间">
<el-date-picker v-model="formData.预计结束时间" type="date" value-format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="设计要求">
<el-input v-model="formData.设计要求" type="textarea" :rows="3" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="formData.备注" type="textarea" :rows="2" />
@@ -325,6 +374,7 @@ export default {
materialOptions: [],
parentMaterialOptions: [],
personnelOptions: [],
visibilityPersonnelOptions: [],
searchForm: {
did: '',
projectNo: '',
@@ -347,6 +397,7 @@ export default {
created() {
this.loadDefaultProjectOptions()
this.queryPersonnel('')
this.queryVisibilityPersonnel('')
this.loadDefaultMaterialOptions()
this.searchTable()
},
@@ -365,6 +416,9 @@ export default {
设计要求: '',
研发立项号: '',
研发目的: '',
对齐可见ID: '',
对齐可见: '',
visibilityIds: [],
指派对象ID: '',
指派对象: '',
assigneeIds: [],
@@ -407,28 +461,24 @@ export default {
this.formData = this.getEmptyForm()
this.loadDefaultProjectOptions()
this.loadDefaultMaterialOptions()
this.queryVisibilityPersonnel('')
this.dialogVisible = true
this.$nextTick(() => this.$refs.taskForm && this.$refs.taskForm.clearValidate())
},
openEdit(row) {
this.isEdit = true
const assigneeIds = row.指派对象ID ? String(row.指派对象ID).split(',').filter(Boolean) : []
const visibilityIds = row.对齐可见ID ? String(row.对齐可见ID).split(',').filter(Boolean) : []
this.formData = {
...this.getEmptyForm(),
...row,
assigneeIds,
visibilityIds,
预计开始时间: this.toDate(row.预计开始时间),
预计结束时间: this.toDate(row.预计结束时间)
}
if (row.指派对象ID || row.指派对象) {
const ids = assigneeIds
const names = row.指派对象 ? String(row.指派对象).split(',') : []
ids.forEach((id, index) => {
if (!this.personnelOptions.some(item => item.人员编号 === id)) {
this.personnelOptions.push({ 人员编号: id, 人员姓名: names[index] || id })
}
})
}
this.ensurePersonnelOptions(this.personnelOptions, assigneeIds, row.指派对象)
this.ensurePersonnelOptions(this.visibilityPersonnelOptions, visibilityIds, row.对齐可见)
this.loadDefaultProjectOptions()
this.loadDefaultMaterialOptions()
this.dialogVisible = true
@@ -485,6 +535,8 @@ export default {
params.push(['设计要求', this.formData.设计要求 || ''])
params.push(['研发立项号', this.formData.研发立项号 || ''])
params.push(['研发目的', this.formData.研发目的 || ''])
params.push(['对齐可见ID', this.formData.对齐可见ID || ''])
params.push(['对齐可见', this.formData.对齐可见 || ''])
params.push(['指派对象ID', this.formData.指派对象ID || ''])
params.push(['指派对象', this.formData.指派对象 || ''])
params.push(['预计开始时间', this.formData.预计开始时间 || ''])
@@ -495,7 +547,7 @@ export default {
},
deleteTask(row) {
this.$confirm(`确定删除设计任务 DID ${row.DID} 吗?已有报工记录的任务不能删除。`, '提示', { type: 'warning' })
.then(async () => {
.then(async() => {
const latest = await this.getLatestTask(row.DID)
if (!latest) return
Object.assign(row, latest)
@@ -594,6 +646,15 @@ export default {
this.personnelOptions = []
}
},
async queryVisibilityPersonnel(query) {
const data = this.CreateData('11', '设计报工_人员查询', [['过滤', query || '']])
try {
const response = await this.ExecDatabase(data)
this.visibilityPersonnelOptions = response.data || []
} catch (error) {
this.visibilityPersonnelOptions = []
}
},
handleMaterialChange(value) {
const selected = this.materialOptions.find(item => item.物料编码 === value)
this.formData.物料名称 = selected ? selected.物料名称 : ''
@@ -607,6 +668,19 @@ export default {
this.formData.指派对象ID = values.join(',')
this.formData.指派对象 = selected.map(item => item.人员姓名).join(',')
},
handleVisibilityChange(values) {
const selected = this.visibilityPersonnelOptions.filter(item => values.includes(item.人员编号))
this.formData.对齐可见ID = values.join(',')
this.formData.对齐可见 = selected.map(item => item.人员姓名).join(',')
},
ensurePersonnelOptions(options, ids, namesValue) {
const names = namesValue ? String(namesValue).split(',') : []
ids.forEach((id, index) => {
if (!options.some(item => item.人员编号 === id)) {
options.push({ 人员编号: id, 人员姓名: names[index] || id })
}
})
},
formatMaterialLabel(item) {
return item.物料名称 ? `${item.物料编码} | ${item.物料名称}` : item.物料编码
},
@@ -680,4 +754,22 @@ export default {
.danger-action {
color: #f56c6c;
}
.note-history {
width: 100%;
min-height: 20px;
line-height: 20px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.note-tooltip-content {
max-width: 520px;
max-height: 60vh;
line-height: 20px;
white-space: pre-line;
overflow-y: auto;
overflow-wrap: anywhere;
}
</style>

View File

@@ -80,7 +80,16 @@
<br />
<br />
<span class="show-text">检测状态</span>
<el-select
v-model="checkstatus"
style="width: 150px; margin-right: 10px"
filterable
>
<el-option label="全部" value="2" />
<el-option label="已完成" value="1" />
<el-option label="未完成" value="0" />
</el-select>
<span class="show-text">检测结果</span>
<el-select
v-model="inspectionResult"
@@ -221,7 +230,7 @@
width="150"
prop="备注"
/>
<el-table-column label="操作" align="center" width="250">
<el-table-column label="操作" align="center" width="400">
<template slot-scope="scope">
<el-button
class="operation-btn"
@@ -230,6 +239,20 @@
@click="receiveCheck(scope.row)"
>入库检</el-button
>
<el-button
class="operation-btn"
type="primary"
size="mini"
@click="getitemdraw(scope.row)"
>零件图纸</el-button
>
<el-button
class="operation-btn"
type="primary"
size="mini"
@click="getitemdraw2(scope.row)"
>工艺图纸</el-button
>
</template>
</el-table-column>
</el-table>
@@ -376,7 +399,7 @@
<script>
// 引入xlsx库
import * as XLSX from "xlsx";
import { MESDownFile } from '@/utils/request'
export default {
data() {
return {
@@ -415,6 +438,9 @@ export default {
检测时间: "",
检测说明: "",
},
checkstatus:'0',
downPDF:MESDownFile,
};
},
created() {
@@ -474,6 +500,7 @@ export default {
this.inspectionDate ? this.inspectionDate[1] : "",
]);
param.push(["检测结果", this.inspectionResult]);
param.push(["状态", this.checkstatus]);
const selectedChecker = this.checkerList.find(
(item) => item.value === this.checker
);
@@ -504,7 +531,38 @@ export default {
this.$message.error("查询失败");
});
},
getitemdraw(row) {
var param = [];
param[0] = ['物料编号', row.物料编码];
var Data = this.CreateData('11', '工艺管理_图纸维护_查看图纸', param);
this.ExecDatabase(Data).then(response => {
console.log(response)
if (response.data.length > 0) {
var pdfSrc =""+this.downPDF+""+ response.data[0].uid+".pdf"
window.open(pdfSrc,'_blank')
}else {
this.$message.error('未上传图纸');
}
})
},
getitemdraw2(row) {
var param = [];
param[0] = ['物料编号', row.物料编码];
var Data = this.CreateData('11', '工艺管理_工艺维护_查看图纸', param);
this.ExecDatabase(Data).then(response => {
console.log(response)
if (response.data.length > 0) {
var pdfSrc =""+this.downPDF+""+ response.data[0].uid+".pdf"
window.open(pdfSrc,'_blank')
}else {
this.$message.error('未上传图纸');
}
})
},
receiveCheck(row) {
// 打开收检对话框并填充数据
this.receiveCheckVisible = true;
@@ -749,4 +807,4 @@ export default {
display: flex;
align-items: center;
}
</style>
</style>

View File

@@ -80,7 +80,16 @@
<br />
<br />
<span class="show-text">检测状态</span>
<el-select
v-model="checkstatus"
style="width: 150px; margin-right: 10px"
filterable
>
<el-option label="全部" value="2" />
<el-option label="已完成" value="1" />
<el-option label="未完成" value="0" />
</el-select>
<span class="show-text">检测结果</span>
<el-select
v-model="inspectionResult"
@@ -221,7 +230,7 @@
width="150"
prop="备注"
/>
<el-table-column label="操作" align="center" width="250">
<el-table-column label="操作" align="center" width="400">
<template slot-scope="scope">
<el-button
class="operation-btn"
@@ -230,6 +239,19 @@
@click="receiveCheck(scope.row)"
>退货检</el-button
>
<el-button
class="operation-btn"
type="primary"
size="mini"
@click="getitemdraw(scope.row)"
>零件图纸</el-button
>
<el-button
class="operation-btn"
type="primary"
size="mini"
@click="getitemdraw2(scope.row)"
>工艺图纸</el-button>
</template>
</el-table-column>
</el-table>
@@ -362,7 +384,7 @@
<script>
// 引入xlsx库
import * as XLSX from "xlsx";
import { MESDownFile } from '@/utils/request'
export default {
data() {
return {
@@ -401,6 +423,8 @@ export default {
检测时间: "",
检测说明: "",
},
checkstatus:'0',
downPDF:MESDownFile,
};
},
created() {
@@ -416,6 +440,38 @@ export default {
},
},
methods: {
getitemdraw(row) {
var param = [];
param[0] = ['物料编号', row.物料编码];
var Data = this.CreateData('11', '工艺管理_图纸维护_查看图纸', param);
this.ExecDatabase(Data).then(response => {
console.log(response)
if (response.data.length > 0) {
var pdfSrc =""+this.downPDF+""+ response.data[0].uid+".pdf"
window.open(pdfSrc,'_blank')
}else {
this.$message.error('未上传图纸');
}
})
},
getitemdraw2(row) {
var param = [];
param[0] = ['物料编号', row.物料编码];
var Data = this.CreateData('11', '工艺管理_工艺维护_查看图纸', param);
this.ExecDatabase(Data).then(response => {
console.log(response)
if (response.data.length > 0) {
var pdfSrc =""+this.downPDF+""+ response.data[0].uid+".pdf"
window.open(pdfSrc,'_blank')
}else {
this.$message.error('未上传图纸');
}
})
},
getTypeList() {
this.typeList = [];
var Data = this.CreateData("11", "查询字典");
@@ -467,7 +523,7 @@ export default {
(item) => item.value === this.checker
);
param.push(["检测人", selectedChecker ? selectedChecker.label : ""]);
param.push(["状态", this.checkstatus]);
// 调用封装方法生成请求数据 - 使用新的存储过程名称
var Data = this.CreateData(
"11",