feat: update production reporting workflows

This commit is contained in:
2026-07-07 17:30:12 +08:00
parent 1399b9a80a
commit c4a2f6e42e
24 changed files with 3713 additions and 35 deletions

View File

@@ -0,0 +1,773 @@
/*
设计报工任务模块
说明:
1. 新建独立设计报工表和独立存储过程。
2. 不写入现有生产报工表。
3. 不上传 SAP。
4. 不新增菜单权限,不写入菜单表和角色权限表。
*/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
IF OBJECT_ID(N'[dbo].[MES_设计报工_任务]', N'U') IS NULL
BEGIN
CREATE TABLE [dbo].[MES_设计报工_任务]
(
[DID] int IDENTITY(1,1) NOT NULL PRIMARY KEY,
[] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] nvarchar(200) NULL,
[] nvarchar(100) NULL,
[] nvarchar(500) NULL,
[] nvarchar(100) NULL,
[] nvarchar(200) NULL,
[] nvarchar(max) NULL,
[] nvarchar(100) NULL,
[] nvarchar(500) NULL,
[ID] nvarchar(1000) NULL,
[] nvarchar(1000) NULL,
[] datetime NULL,
[] datetime NULL,
[] nvarchar(50) NOT NULL CONSTRAINT [DF_MES_设计报工_任务_单据状态] DEFAULT (N'待开始'),
[] datetime NOT NULL CONSTRAINT [DF_MES_设计报工_任务_创建日期] DEFAULT (GETDATE()),
[] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] datetime NULL,
[] nvarchar(500) NULL
);
END
GO
IF OBJECT_ID(N'[dbo].[MES_设计报工_记录]', N'U') IS NULL
BEGIN
CREATE TABLE [dbo].[MES_设计报工_记录]
(
[RID] int IDENTITY(1,1) NOT NULL PRIMARY KEY,
[DID] int NOT NULL,
[ID] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] datetime NULL,
[] datetime NULL,
[] int NULL,
[] nvarchar(50) NOT NULL CONSTRAINT [DF_MES_设计报工_记录_报工状态] DEFAULT (N'执行中'),
[] bit NOT NULL CONSTRAINT [DF_MES_设计报工_记录_已校验] DEFAULT (0),
[ID] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] datetime NULL,
[] datetime NOT NULL CONSTRAINT [DF_MES_设计报工_记录_创建时间] DEFAULT (GETDATE()),
[] nvarchar(500) NULL,
CONSTRAINT [FK_MES_设计报工_记录_任务] FOREIGN KEY ([DID]) REFERENCES [dbo].[MES_设计报工_任务]([DID])
);
END
GO
IF OBJECT_ID(N'[dbo].[MES_设计报工_校验记录]', N'U') IS NULL
BEGIN
CREATE TABLE [dbo].[MES_设计报工_校验记录]
(
[VID] int IDENTITY(1,1) NOT NULL PRIMARY KEY,
[RID] int NOT NULL,
[DID] int NOT NULL,
[] datetime NULL,
[] datetime NULL,
[] datetime NULL,
[] datetime NULL,
[] int NULL,
[ID] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] datetime NOT NULL CONSTRAINT [DF_MES_设计报工_校验记录_校验时间] DEFAULT (GETDATE()),
[] nvarchar(500) NULL
);
END
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_MES_设计报工_任务_查询' AND object_id = OBJECT_ID(N'[dbo].[MES_设计报工_任务]'))
CREATE INDEX [IX_MES_设计报工_任务_查询] ON [dbo].[MES_设计报工_任务]([], [], [], [], []);
GO
IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'IX_MES_设计报工_记录_DID' AND object_id = OBJECT_ID(N'[dbo].[MES_设计报工_记录]'))
CREATE INDEX [IX_MES_设计报工_记录_DID] ON [dbo].[MES_设计报工_记录]([DID], [], [], []);
GO
CREATE OR ALTER PROCEDURE [dbo].[_物料查询]
@ nvarchar(200) = N''
AS
BEGIN
SET NOCOUNT ON;
SELECT TOP 100
CAST([] AS nvarchar(100)) AS [],
ISNULL(
NULLIF(CAST([] AS nvarchar(200)), N''),
CAST([] AS nvarchar(200))
) AS [],
CAST([] AS nvarchar(500)) AS [],
CAST([] AS nvarchar(200)) AS [],
CAST([] AS nvarchar(100)) AS []
FROM [SAP].[SBO_YL].[dbo].[UBT_OITM]
WHERE
ISNULL(@, N'') = N''
OR CAST([] AS nvarchar(100)) LIKE N'%' + @ + N'%'
OR CAST([] AS nvarchar(200)) LIKE N'%' + @ + N'%'
OR CAST([] AS nvarchar(500)) LIKE N'%' + @ + N'%'
ORDER BY CAST([] AS nvarchar(100));
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_人员查询]
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ table
(
[] int NULL,
[] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] nvarchar(100) NULL,
[] nvarchar(100) NULL
);
INSERT INTO @
EXEC [dbo].[_人员管理_所有有效人员查询];
SELECT TOP 200
CAST([] AS nvarchar(50)) AS [],
[],
[],
[],
[]
FROM @
WHERE
ISNULL(@, N'') = N''
OR CAST([] AS nvarchar(50)) LIKE N'%' + @ + N'%'
OR [] LIKE N'%' + @ + N'%'
OR [] LIKE N'%' + @ + N'%'
ORDER BY [];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_项目查询]
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
SELECT DISTINCT TOP 100
[]
FROM [dbo].[MES_设计报工_任务]
WHERE
ISNULL([], N'') <> N''
AND (ISNULL(@, N'') = N'' OR [] LIKE N'%' + @ + N'%')
ORDER BY [];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_查询]
@DID int = NULL,
@ 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''
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.[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 [],
CONVERT(varchar(19), r.[], 120) AS [],
CONVERT(varchar(19), r.[], 120) AS []
FROM [dbo].[MES_设计报工_任务] AS t
OUTER APPLY
(
SELECT
COUNT(1) AS [],
SUM(CASE WHEN rr.[] IS NULL THEN 1 ELSE 0 END) AS [],
MAX(rr.[]) AS [],
MAX(rr.[]) AS []
FROM [dbo].[MES_设计报工_记录] AS rr
WHERE rr.[DID] = t.[DID]
) AS r
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 @ = 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))
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(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''
AS
BEGIN
SET NOCOUNT ON;
INSERT INTO [dbo].[MES_设计报工_任务]
(
[], [], [], [], [],
[], [], [],
[], [], [ID], [],
[], [], [],
[], [], [], []
)
VALUES
(
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''),
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(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''
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''),
[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
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_记录] WHERE [DID] = @DID)
BEGIN
SELECT CAST(0 AS int) AS [result], N'该任务已有设计报工记录,不能删除' AS [message];
RETURN;
END
DELETE FROM [dbo].[MES_设计报工_任务]
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;
IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_任务] WHERE [DID] = @DID)
BEGIN
SELECT CAST(0 AS int) AS [result], N'任务不存在' AS [message];
RETURN;
END
IF EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_任务] WHERE [DID] = @DID AND [] = N'已完成')
BEGIN
SELECT CAST(0 AS int) AS [result], N'任务已完成,不能开始' AS [message];
RETURN;
END
IF EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_记录] WHERE [DID] = @DID AND [] IS NULL)
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''), GETDATE(), N'执行中');
UPDATE [dbo].[MES_设计报工_任务]
SET [] = N'执行中', [] = NULLIF(@, N''), [] = GETDATE()
WHERE [DID] = @DID;
SELECT CAST(1 AS int) AS [result], N'开始成功' AS [message], SCOPE_IDENTITY() AS [RID];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_结束]
@DID int,
@ID nvarchar(100) = N'',
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @RID int;
SELECT TOP 1 @RID = [RID]
FROM [dbo].[MES_设计报工_记录]
WHERE [DID] = @DID AND [] IS NULL
ORDER BY [] DESC, [RID] DESC;
IF @RID IS NULL
BEGIN
SELECT CAST(0 AS int) AS [result], N'没有未结束的报工记录' AS [message];
RETURN;
END
UPDATE [dbo].[MES_设计报工_记录]
SET
[] = GETDATE(),
[] = DATEDIFF(second, [], GETDATE()),
[] = N'已结束'
WHERE [RID] = @RID;
UPDATE [dbo].[MES_设计报工_任务]
SET [] = N'已结束', [] = NULLIF(@, N''), [] = GETDATE()
WHERE [DID] = @DID AND [] <> N'已完成';
SELECT CAST(1 AS int) AS [result], N'结束成功' AS [message], @RID AS [RID];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_任务_完成]
@DID int,
@ nvarchar(100) = 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
IF EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_记录] WHERE [DID] = @DID AND [] IS NULL)
BEGIN
SELECT CAST(0 AS int) AS [result], N'任务存在未结束报工,不能完成' AS [message];
RETURN;
END
IF NOT EXISTS (SELECT 1 FROM [dbo].[MES_设计报工_记录] WHERE [DID] = @DID AND [] IS NOT NULL)
BEGIN
SELECT CAST(0 AS int) AS [result], N'任务未产生已结束报工,不能完成' AS [message];
RETURN;
END
UPDATE [dbo].[MES_设计报工_任务]
SET [] = N'已完成', [] = NULLIF(@, N''), [] = GETDATE()
WHERE [DID] = @DID;
SELECT CAST(1 AS int) AS [result], N'完成成功' AS [message];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_记录_查询]
@DID int = NULL,
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(30) = N'',
@ nvarchar(30) = N'',
@ nvarchar(50) = N''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ datetime = TRY_CONVERT(datetime, NULLIF(@, N''));
DECLARE @ datetime = TRY_CONVERT(datetime, NULLIF(@, N''));
SELECT TOP 1000
r.[RID],
r.[DID],
t.[],
t.[],
t.[],
t.[],
t.[],
t.[],
r.[ID],
r.[],
CONVERT(varchar(19), r.[], 120) AS [],
CONVERT(varchar(19), r.[], 120) AS [],
r.[],
CAST(CAST(ISNULL(r.[], 0) / 3600.0 AS decimal(18, 2)) AS varchar(30)) AS [],
r.[],
r.[],
CASE WHEN r.[] = 1 THEN N'已校验' ELSE N'未校验' END AS [],
r.[],
CONVERT(varchar(19), r.[], 120) AS [],
r.[],
t.[]
FROM [dbo].[MES_设计报工_记录] AS r
INNER JOIN [dbo].[MES_设计报工_任务] AS t ON r.[DID] = t.[DID]
WHERE
(@DID IS NULL OR @DID = 0 OR r.[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 r.[] LIKE N'%' + @ + N'%')
AND (@ IS NULL OR r.[] >= @)
AND (@ IS NULL OR r.[] < DATEADD(day, 1, @))
AND (
ISNULL(@, N'') = N''
OR @ = N'全部'
OR (@ = N'已校验' AND r.[] = 1)
OR (@ = N'未校验' AND r.[] = 0)
)
ORDER BY r.[RID] DESC;
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_工时校验_查询]
@DID int = NULL,
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(30) = N'',
@ nvarchar(30) = N'',
@ nvarchar(50) = N'未校验'
AS
BEGIN
SET NOCOUNT ON;
EXEC [dbo].[_记录_查询]
@DID = @DID,
@ = @,
@ = @,
@ = @,
@ = @,
@ = @,
@ = @;
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_工时校验_保存]
@RID int,
@ nvarchar(30),
@ nvarchar(30),
@ID nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(500) = N''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ datetime = TRY_CONVERT(datetime, NULLIF(@, N''));
DECLARE @ datetime = TRY_CONVERT(datetime, NULLIF(@, N''));
DECLARE @DID int;
DECLARE @ datetime;
DECLARE @ datetime;
SELECT @DID = [DID], @ = [], @ = []
FROM [dbo].[MES_设计报工_记录]
WHERE [RID] = @RID;
IF @DID IS NULL
BEGIN
SELECT CAST(0 AS int) AS [result], N'报工记录不存在' AS [message];
RETURN;
END
IF @ IS NULL OR @ IS NULL OR @ <= @
BEGIN
SELECT CAST(0 AS int) AS [result], N'开始时间和结束时间不合法' AS [message];
RETURN;
END
INSERT INTO [dbo].[MES_设计报工_校验记录]
(
[RID], [DID], [], [],
[], [], [],
[ID], [], [], []
)
VALUES
(
@RID, @DID, @, @,
@, @, DATEDIFF(second, @, @),
NULLIF(@ID, N''), NULLIF(@, N''), GETDATE(), NULLIF(@, N'')
);
UPDATE [dbo].[MES_设计报工_记录]
SET
[] = @,
[] = @,
[] = DATEDIFF(second, @, @),
[] = N'已结束',
[] = 1,
[ID] = NULLIF(@ID, N''),
[] = NULLIF(@, N''),
[] = GETDATE(),
[] = NULLIF(@, N'')
WHERE [RID] = @RID;
SELECT CAST(1 AS int) AS [result], N'校验成功' AS [message];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_工时校验_批量保存]
@RIDs nvarchar(max),
@ID nvarchar(100) = N'',
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
DECLARE @RID表 table([RID] int PRIMARY KEY);
DECLARE @xml xml;
SET @xml = TRY_CONVERT(xml, N'<r><i>' + REPLACE(ISNULL(@RIDs, N''), N',', N'</i><i>') + N'</i></r>');
INSERT INTO @RID表([RID])
SELECT DISTINCT TRY_CONVERT(int, T.c.value(N'.', N'nvarchar(30)'))
FROM @xml.nodes(N'/r/i') AS T(c)
WHERE TRY_CONVERT(int, T.c.value(N'.', N'nvarchar(30)')) IS NOT NULL;
IF NOT EXISTS (SELECT 1 FROM @RID表)
BEGIN
SELECT CAST(0 AS int) AS [result], N'没有可校验记录' AS [message];
RETURN;
END
INSERT INTO [dbo].[MES_设计报工_校验记录]
(
[RID], [DID], [], [],
[], [], [],
[ID], [], [], []
)
SELECT
r.[RID], r.[DID], r.[], r.[],
r.[], r.[], r.[],
NULLIF(@ID, N''), NULLIF(@, N''), GETDATE(), N'批量校验'
FROM [dbo].[MES_设计报工_记录] AS r
INNER JOIN @RID表 AS ids ON r.[RID] = ids.[RID]
WHERE r.[] IS NOT NULL AND r.[] IS NOT NULL;
UPDATE r
SET
[] = 1,
[ID] = NULLIF(@ID, N''),
[] = NULLIF(@, N''),
[] = GETDATE()
FROM [dbo].[MES_设计报工_记录] AS r
INNER JOIN @RID表 AS ids ON r.[RID] = ids.[RID]
WHERE r.[] IS NOT NULL AND r.[] IS NOT NULL;
SELECT CAST(1 AS int) AS [result], N'批量校验成功' AS [message], @@ROWCOUNT AS [count];
END
GO
CREATE OR ALTER PROCEDURE [dbo].[_工时报表_作业者工时_查询]
@ nvarchar(30) = N'',
@ nvarchar(30) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@ nvarchar(100) = N'',
@DID int = NULL
AS
BEGIN
SET NOCOUNT ON;
DECLARE @ datetime = TRY_CONVERT(datetime, NULLIF(@, N''));
DECLARE @ datetime = TRY_CONVERT(datetime, NULLIF(@, N''));
;WITH base AS
(
SELECT
r.[RID],
r.[DID],
ISNULL(r.[], N'') AS [],
CONVERT(varchar(10), r.[], 120) AS [],
t.[],
t.[],
t.[],
t.[],
t.[],
r.[],
r.[],
ISNULL(r.[], 0) AS [],
r.[],
r.[]
FROM [dbo].[MES_设计报工_记录] AS r
INNER JOIN [dbo].[MES_设计报工_任务] AS t ON r.[DID] = t.[DID]
WHERE
r.[] IS NOT NULL
AND r.[] IS NOT NULL
AND (@ IS NULL OR r.[] >= @)
AND (@ IS NULL OR r.[] < DATEADD(day, 1, @))
AND (ISNULL(@, N'') = N'' OR r.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (ISNULL(@, N'') = N'' OR t.[] LIKE N'%' + @ + N'%')
AND (@DID IS NULL OR @DID = 0 OR r.[DID] = @DID)
),
result AS
(
SELECT
1 AS [Level],
N'p-' + [] AS [id],
CAST(N'' AS nvarchar(100)) AS [parentId],
[],
CAST(N'' AS nvarchar(20)) AS [],
CAST(NULL AS int) AS [RID],
CAST(NULL AS int) AS [DID],
CAST(N'' AS nvarchar(100)) AS [],
CAST(N'' AS nvarchar(100)) AS [],
CAST(N'' AS nvarchar(200)) AS [],
CAST(N'' AS nvarchar(100)) AS [],
CAST(N'' AS nvarchar(500)) AS [],
CAST(N'' AS varchar(19)) AS [],
CAST(N'' AS varchar(19)) AS [],
COUNT(1) AS [],
CAST(SUM([]) / 3600.0 AS decimal(18, 2)) AS [],
CAST(N'' AS nvarchar(20)) AS [],
CAST(N'' AS nvarchar(500)) AS []
FROM base
GROUP BY []
UNION ALL
SELECT
2 AS [Level],
N'd-' + [] + N'-' + [] AS [id],
N'p-' + [] AS [parentId],
[],
[],
CAST(NULL AS int) AS [RID],
CAST(NULL AS int) AS [DID],
CAST(N'' AS nvarchar(100)) AS [],
CAST(N'' AS nvarchar(100)) AS [],
CAST(N'' AS nvarchar(200)) AS [],
CAST(N'' AS nvarchar(100)) AS [],
CAST(N'' AS nvarchar(500)) AS [],
CAST(N'' AS varchar(19)) AS [],
CAST(N'' AS varchar(19)) AS [],
COUNT(1) AS [],
CAST(SUM([]) / 3600.0 AS decimal(18, 2)) AS [],
CAST(N'' AS nvarchar(20)) AS [],
CAST(N'' AS nvarchar(500)) AS []
FROM base
GROUP BY [], []
UNION ALL
SELECT
3 AS [Level],
N'r-' + CAST([RID] AS nvarchar(20)) AS [id],
N'd-' + [] + N'-' + [] AS [parentId],
[],
[],
[RID],
[DID],
ISNULL([], N'') AS [],
ISNULL([], N'') AS [],
ISNULL([], N'') AS [],
ISNULL([], N'') AS [],
ISNULL([], N'') AS [],
CONVERT(varchar(19), [], 120) AS [],
CONVERT(varchar(19), [], 120) AS [],
1 AS [],
CAST([] / 3600.0 AS decimal(18, 2)) AS [],
CASE WHEN [] = 1 THEN N'已校验' ELSE N'未校验' END AS [],
ISNULL([], N'') AS []
FROM base
)
SELECT *
FROM result
ORDER BY [], [], [Level], [RID];
END
GO

View File

@@ -0,0 +1,210 @@
USE [YL_MESDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[_生产订单关闭_查询全部订单]
@ nvarchar(100) = N'',
@ nvarchar(100) = N'', -- 可选值:'已关闭'、'未关闭'、'可关闭'
@ nvarchar(100) = N''
AS
BEGIN
SET NOCOUNT ON;
IF (@ = N'可关闭')
BEGIN
CREATE TABLE #工时订单
(
nvarchar(100) NOT NULL PRIMARY KEY
);
INSERT INTO #工时订单 (订单号)
SELECT DISTINCT CONVERT(nvarchar(100), )
FROM dbo.View_生产工时视图
WHERE IS NOT NULL;
;WITH AS
(
SELECT
CONVERT(nvarchar(100), t.) AS
FROM dbo.YL_加工中心_操作记录表 AS t
WHERE t. = N'开始加工'
AND t. IS NULL
AND t. LIKE N'%装配%'
AND t. IS NOT NULL
GROUP BY CONVERT(nvarchar(100), t.)
),
AS
(
SELECT
,
SUM(ISNULL(, 0)) AS ,
SUM(ISNULL(, 0)) AS
FROM dbo.YL_质量检验_质检记录
WHERE = N'收检'
GROUP BY
),
AS
(
SELECT
,
SUM(ISNULL(, 0)) AS ,
SUM(ISNULL(, 0)) AS
FROM dbo.YL_质量检验_质检记录
WHERE = N'终检'
GROUP BY
),
AS
(
SELECT
v. AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(.) AS ,
MAX(.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(.) AS ,
MIN(CASE WHEN v.Expr1 IS NULL THEN 0 ELSE 1 END) AS
FROM dbo.View_生产工时视图 AS v
LEFT JOIN ON v. = .
LEFT JOIN ON v. = .
WHERE v. IS NULL
AND (@ = N'' OR v. = @)
AND (
@ NOT IN (N'机加', N'装配')
OR (@ = N'机加' AND v. = N'机加件')
OR (@ = N'装配' AND v. LIKE N'%装配%')
)
GROUP BY v.
HAVING
MIN(CASE WHEN v.Expr1 IS NULL THEN 0 ELSE 1 END) = 1
AND (
MAX(.) + MAX(.) = MAX(v.)
OR MAX(v.) = MAX(v.)
OR MAX(.) = MAX(v.)
)
AND MAX(ISNULL(v., 0)) = MAX(ISNULL(., 0))
UNION ALL
SELECT
CONVERT(nvarchar(100), p.) AS ,
MAX(p.) AS ,
MAX(p.) AS ,
MAX(p.) AS ,
MAX(p.) AS ,
MAX(.) AS ,
MAX(.) AS ,
MAX(p.) AS ,
MAX(p.) AS ,
MAX(p.) AS ,
MAX(.) AS ,
1 AS
FROM dbo.MES_接口_生产计划 AS p
LEFT JOIN ON CONVERT(nvarchar(100), p.) = CONVERT(nvarchar(100), .)
LEFT JOIN ON CONVERT(nvarchar(100), p.) = CONVERT(nvarchar(100), .)
LEFT JOIN #工时订单 AS wh ON wh.订单号 = CONVERT(nvarchar(100), p.订单编号)
WHERE p. IS NULL
AND wh. IS NULL
AND (@ = N'' OR CONVERT(nvarchar(100), p.) = @)
AND (
@ NOT IN (N'机加', N'装配')
OR (@ = N'机加' AND p. = N'机加件')
OR (@ = N'装配' AND p. LIKE N'%装配%')
)
GROUP BY p.
HAVING
(
MAX(.) + MAX(.) = MAX(p.)
OR MAX(p.) = MAX(p.)
OR MAX(.) = MAX(p.)
)
AND MAX(ISNULL(p., 0)) = MAX(ISNULL(., 0))
)
SELECT
c.,
c.,
c.,
c.,
c.,
c.,
c.,
c.,
c.,
c.,
c.,
c.
FROM AS c
WHERE NOT EXISTS
(
SELECT 1
FROM AS u
WHERE u. = CONVERT(nvarchar(100), c.)
)
ORDER BY c.;
RETURN;
END
;WITH AS
(
SELECT
CONVERT(nvarchar(100), t.) AS
FROM dbo.YL_加工中心_操作记录表 AS t
WHERE t. = N'开始加工'
AND t. IS NULL
AND t. LIKE N'%装配%'
AND t. IS NOT NULL
GROUP BY CONVERT(nvarchar(100), t.)
)
SELECT TOP 100
v.,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(zj_终检数量.) AS ,
MAX(zj_终检数量.) AS ,
MAX(v.) AS ,
MAX(v.) AS ,
MAX(v.) AS
FROM dbo.MES_接口_生产计划 AS v
LEFT JOIN
(
SELECT
,
SUM(ISNULL(, 0)) AS ,
SUM(ISNULL(, 0)) AS
FROM dbo.YL_质量检验_质检记录
WHERE = N'终检'
GROUP BY
) AS zj_终检数量 ON v. = zj_终检数量.
WHERE 1 = 1
AND (@ = N'' OR CONVERT(nvarchar(100), v.) = @)
AND NOT EXISTS
(
SELECT 1
FROM AS u
WHERE u. = CONVERT(nvarchar(100), v.)
)
AND (
@ NOT IN (N'SAP未关闭', N'已关闭', N'未关闭')
OR (@ = N'SAP未关闭' AND v. = N'已关闭')
OR (@ = N'已关闭' AND (v. = N'已关闭' OR v. = N'已取消'))
OR (@ = N'未关闭' AND v. IS NULL)
)
AND (
@ NOT IN (N'机加', N'装配')
OR (@ = N'机加' AND v. = N'机加件')
OR (@ = N'装配' AND v. LIKE N'%装配%')
)
GROUP BY v.;
END
GO

View File

@@ -0,0 +1,280 @@
USE [YL_MESDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[_结算工时_查询]
@ NVARCHAR(50) = NULL,
@ NVARCHAR(100) = NULL,
@ NVARCHAR(50) = NULL,
@ NVARCHAR(50) = NULL,
@ DATE = NULL,
@ DATE = NULL,
@ INT = 100
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TopCount INT = CASE WHEN ISNULL(@, 0) <= 0 THEN 100 ELSE @ END;
CREATE TABLE #基础数据
(
RowID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
TaskAID BIGINT NULL,
DATETIME NULL,
NVARCHAR(1000) NULL,
NVARCHAR(100) NULL,
NVARCHAR(100) NULL,
INT NULL,
INT NULL,
NVARCHAR(100) NULL,
INT NOT NULL,
INT NULL,
NVARCHAR(1000) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(100) NULL,
NVARCHAR(100) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(1000) NULL
);
INSERT INTO #基础数据
(
TaskAID,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
)
SELECT TOP (@TopCount)
v.TaskAID,
v.,
v.,
v.,
v.,
v.,
v.,
v.,
q. AS ,
q.,
q. AS ,
q. AS ,
q.,
COALESCE(NULLIF(q., N''), v.) AS ,
p.,
p.
FROM dbo.MES_接口_生产计划 AS p
INNER JOIN dbo.MES_接口_生产计划_生产任务 AS q
ON q. = p.
AND q. = N'pit_Resource'
INNER JOIN dbo.View_生产工时视图 AS v
ON v.TaskAID = q.AID
WHERE p. IS NOT NULL
AND p. > 6000
AND (@ IS NULL OR @ = N'' OR v. >= @)
AND (@ IS NULL OR @ = N'' OR v. < DATEADD(DAY, 1, @))
AND (@ IS NULL OR @ = N'' OR v. LIKE N'%' + @ + N'%')
AND (@ IS NULL OR @ = N'' OR q. LIKE N'%' + @ + N'%')
AND (@ IS NULL OR @ = N'' OR CONVERT(NVARCHAR(50), q.) = @)
AND (@ IS NULL OR @ = N'' OR COALESCE(NULLIF(q., N''), v.) LIKE N'%' + @ + N'%')
ORDER BY q. DESC, q., v. DESC;
CREATE INDEX IX_基础数据_TaskStart ON #基础数据 (TaskAID, 开始时间);
CREATE TABLE #操作人拼接
(
TaskAID BIGINT NOT NULL,
VARCHAR(19) NOT NULL,
NVARCHAR(MAX) NULL,
PRIMARY KEY (TaskAID, )
);
INSERT INTO #操作人拼接 (TaskAID, 开始时间, 操作人)
SELECT
TaskAID,
,
STRING_AGG(CONVERT(NVARCHAR(MAX), ), N',') AS
FROM
(
SELECT DISTINCT
k.TaskAID,
k.,
LTRIM(RTRIM(s.value)) AS
FROM
(
SELECT DISTINCT
TaskAID,
CONVERT(VARCHAR(19), , 120) AS
FROM #基础数据
WHERE TaskAID IS NOT NULL
AND IS NOT NULL
) AS k
INNER JOIN dbo.View_生产工时视图全部 AS v2
ON v2.TaskAID = k.TaskAID
AND v2. >= CONVERT(DATETIME, k., 120)
AND v2. < DATEADD(SECOND, 1, CONVERT(DATETIME, k., 120))
CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(ISNULL(v2., N''), N'', N','), N'', N','), N',') AS s
WHERE ISNULL(v2., 0) <= 0
AND NULLIF(LTRIM(RTRIM(s.value)), N'') IS NOT NULL
) AS x
GROUP BY TaskAID, ;
;WITH AS
(
SELECT
ISNULL(b., b.) AS ,
ISNULL(b., b.) AS ,
b.,
b.,
b.TaskAID,
b.,
b.,
ISNULL(o., N'') AS ,
CASE
WHEN ISNULL(b., N'') LIKE N'%辅助%' OR ISNULL(b., N'') LIKE N'%辅助%' THEN N'辅助结束'
ELSE N'报工'
END AS ,
CAST(ISNULL(b., 0) / 60.0 / 60.0 AS DECIMAL(18, 4)) AS ,
ISNULL(b., 0) AS
FROM #基础数据 AS b
LEFT JOIN #操作人拼接 AS o
ON o.TaskAID = b.TaskAID
AND o. = CONVERT(VARCHAR(19), b., 120)
),
AS
(
SELECT
,
,
,
,
MAX() AS ,
AS ,
COUNT(*) AS ,
SUM(CASE WHEN = N'报工' THEN ELSE 0 END) AS ,
SUM(CASE WHEN = N'辅助结束' THEN ELSE 0 END) AS ,
SUM(CASE WHEN = N'报工' THEN ELSE 0 END) AS ,
SUM(CASE WHEN = N'辅助结束' THEN ELSE 0 END) AS ,
SUM() AS
FROM
GROUP BY , , , ,
),
AS
(
SELECT
,
,
ISNULL(, N'') AS ,
STRING_AGG(CONVERT(NVARCHAR(MAX), ), N',') AS
FROM
(
SELECT DISTINCT
j.,
j.,
ISNULL(j., N'') AS ,
LTRIM(RTRIM(s.value)) AS
FROM AS j
CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(ISNULL(j., N''), N'', N','), N'', N','), N',') AS s
WHERE NULLIF(LTRIM(RTRIM(s.value)), N'') IS NOT NULL
) AS x
GROUP BY , , ISNULL(, N'')
),
AS
(
SELECT
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
ISNULL(o., N'') AS
FROM AS b
LEFT JOIN AS o
ON o. = b.
AND o. = b.
AND o. = ISNULL(b., N'')
),
AS
(
SELECT
,
,
SUM() AS ,
SUM() AS ,
SUM() AS ,
SUM() AS ,
SUM() AS ,
SUM() AS
FROM
GROUP BY ,
)
SELECT
1 AS [Level],
AS materialCode,
AS materialDesc,
ISNULL(, N'') + N' ' + ISNULL(, N'') AS taskDescription,
CAST(0 AS INT) AS productionOrderNo,
N'' AS station,
CAST( AS VARCHAR(20)) AS reportWorkHours,
CAST( AS VARCHAR(20)) AS auxiliaryWorkHours,
CAST( AS VARCHAR(20)) AS reportFinishQty,
CAST( AS VARCHAR(20)) AS auxiliaryFinishQty,
CAST( AS VARCHAR(20)) AS totalWorkHours,
CAST(CASE WHEN > 0 THEN ( - 0 * ) / ELSE 0 END AS VARCHAR(20)) AS clampingTime,
CAST(0 AS VARCHAR(20)) AS programTime,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementReportPieceHours,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementAuxiliaryPieceHours,
N'' AS operatorNames,
CAST( AS VARCHAR(20)) AS recordCount,
CAST(0 AS INT) AS
FROM
UNION ALL
SELECT
2 AS [Level],
AS materialCode,
AS materialDesc,
ISNULL(, N'') + N' ' + ISNULL(, N'')
+ CASE WHEN NULLIF(ISNULL(, N''), N'') IS NULL THEN N'' ELSE N' ' + END
+ CASE WHEN IS NULL THEN N'' ELSE N'' + CAST( AS VARCHAR(20)) END AS taskDescription,
AS productionOrderNo,
ISNULL(, N'') AS station,
CAST( AS VARCHAR(20)) AS reportWorkHours,
CAST( AS VARCHAR(20)) AS auxiliaryWorkHours,
CAST( AS VARCHAR(20)) AS reportFinishQty,
CAST( AS VARCHAR(20)) AS auxiliaryFinishQty,
CAST( AS VARCHAR(20)) AS totalWorkHours,
CAST(CASE WHEN > 0 THEN ( - 0 * ) / ELSE 0 END AS VARCHAR(20)) AS clampingTime,
CAST(0 AS VARCHAR(20)) AS programTime,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementReportPieceHours,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementAuxiliaryPieceHours,
ISNULL(, N'') AS operatorNames,
CAST( AS VARCHAR(20)) AS recordCount,
FROM
ORDER BY productionOrderNo, , materialCode, [Level], station;
END
GO

View File

@@ -0,0 +1,378 @@
USE [YL_MESDB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[_结算工时_查询]
@ NVARCHAR(50) = NULL,
@ NVARCHAR(100) = NULL,
@ NVARCHAR(50) = NULL,
@ NVARCHAR(50) = NULL,
@ DATE = NULL,
@ DATE = NULL,
@ INT = 100
AS
BEGIN
SET NOCOUNT ON;
DECLARE @TopCount INT = CASE WHEN ISNULL(@, 0) <= 0 THEN 100 ELSE @ END;
CREATE TABLE #任务
(
TaskAID BIGINT NOT NULL PRIMARY KEY,
INT NOT NULL,
INT NULL,
NVARCHAR(1000) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(100) NULL,
NVARCHAR(100) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(100) NULL
);
INSERT INTO #任务
(
TaskAID,
,
,
,
,
,
,
,
,
)
SELECT TOP (@TopCount)
q.AID AS TaskAID,
q.,
q.,
q. AS ,
q. AS ,
q.,
q. AS ,
p.,
p.,
p.
FROM dbo.MES_接口_生产计划 AS p
INNER JOIN dbo.MES_接口_生产计划_生产任务 AS q
ON q. = p.
AND q. = N'pit_Resource'
WHERE p. IS NOT NULL
AND p. > 6000
AND (@ IS NULL OR @ = N'' OR p. LIKE N'%' + @ + N'%')
AND (@ IS NULL OR @ = N'' OR q. LIKE N'%' + @ + N'%')
AND (@ IS NULL OR @ = N'' OR CONVERT(NVARCHAR(50), q.) = @)
AND (@ IS NULL OR @ = N'' OR q. LIKE N'%' + @ + N'%')
ORDER BY q. DESC, q.;
CREATE TABLE #基础数据
(
TaskAID BIGINT NULL,
DATETIME NULL,
NVARCHAR(1000) NULL,
NVARCHAR(100) NULL,
NVARCHAR(100) NULL,
INT NULL,
INT NULL,
NVARCHAR(100) NULL,
INT NOT NULL,
INT NULL,
NVARCHAR(1000) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(100) NULL,
NVARCHAR(100) NULL,
NVARCHAR(1000) NULL,
NVARCHAR(1000) NULL
);
INSERT INTO #基础数据
(
TaskAID,
,
,
,
,
,
,
,
,
,
,
,
,
,
,
)
SELECT
t.TaskAID,
v.,
v.,
v.,
v.,
v.,
v.,
t. AS ,
t. AS ,
t.,
t.,
t.,
t.,
t.,
t.,
t.
FROM #任务 AS t
OUTER APPLY
(
SELECT
ISNULL(c., o.) AS ,
ISNULL(c., o.) AS ,
ISNULL(c., o.) AS ,
ISNULL(c., o.) AS ,
ISNULL(c., o.) AS ,
ISNULL(c., o.) AS ,
ISNULL(c., o.) AS
FROM dbo.YL_加工中心_操作记录表 AS o
LEFT JOIN dbo._工时校验_校验工时表 AS c
ON o.AID = c.id
WHERE o.TaskAID = t.TaskAID
AND o. <> N'外协'
AND (o. <> N'报工' OR ISNULL(c., o.) IS NOT NULL)
AND (c.AID IS NOT NULL OR o. <> N'收料')
AND (
c.AID IS NOT NULL
OR o. NOT IN (N'开始加工', N'辅助开始')
OR o. IS NOT NULL
OR NOT EXISTS
(
SELECT 1
FROM dbo.YL_加工中心_操作记录表 AS t2
WHERE t2. IN (N'报工', N'辅助结束')
AND t2.TaskAID = o.TaskAID
AND t2. = o.
)
)
AND (
o. NOT IN (N'辅助结束')
OR NOT EXISTS
(
SELECT 1
FROM dbo.YL_加工中心_操作记录表 AS p
WHERE p. = N'辅助结束'
AND p.TaskAID = o.TaskAID
AND p. IS NULL
)
)
AND (
o. NOT IN (N'开始加工', N'辅助开始')
OR NOT EXISTS
(
SELECT 1
FROM dbo.YL_加工中心_操作记录表 AS p
WHERE p. = N'暂停'
AND p.TaskAID = o.TaskAID
AND p. = o.
AND p. = o.
)
)
AND (
o. IS NOT NULL
OR (o. IN (N'开始加工', N'辅助开始') AND o. IS NULL)
OR o. <> N''
)
) AS v
WHERE (@ IS NULL OR @ = N'' OR v. >= @)
AND (@ IS NULL OR @ = N'' OR v. < DATEADD(DAY, 1, @));
CREATE INDEX IX_基础数据_TaskStart ON #基础数据 (TaskAID, 开始时间);
CREATE TABLE #操作人拼接
(
TaskAID BIGINT NOT NULL,
VARCHAR(19) NOT NULL,
NVARCHAR(MAX) NULL,
PRIMARY KEY (TaskAID, )
);
INSERT INTO #操作人拼接 (TaskAID, 开始时间, 操作人)
SELECT
TaskAID,
,
STRING_AGG(CONVERT(NVARCHAR(MAX), ), N',') AS
FROM
(
SELECT DISTINCT
k.TaskAID,
k.,
LTRIM(RTRIM(s.value)) AS
FROM
(
SELECT DISTINCT
TaskAID,
CONVERT(VARCHAR(19), , 120) AS
FROM #基础数据
WHERE TaskAID IS NOT NULL
AND IS NOT NULL
) AS k
INNER JOIN dbo.YL_加工中心_操作记录表 AS o
ON o.TaskAID = k.TaskAID
AND o. >= CONVERT(DATETIME, k., 120)
AND o. < DATEADD(SECOND, 1, CONVERT(DATETIME, k., 120))
LEFT JOIN dbo._工时校验_校验工时表 AS c
ON o.AID = c.id
CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(ISNULL(ISNULL(c., o.), N''), N'', N','), N'', N','), N',') AS s
WHERE ISNULL(ISNULL(c., o.), 0) <= 0
AND NULLIF(LTRIM(RTRIM(s.value)), N'') IS NOT NULL
) AS x
GROUP BY TaskAID, ;
;WITH AS
(
SELECT
ISNULL(b., b.) AS ,
ISNULL(b., b.) AS ,
b.,
b.,
b.TaskAID,
b.,
b.,
ISNULL(o., N'') AS ,
CASE
WHEN ISNULL(b., N'') LIKE N'%辅助%' OR ISNULL(b., N'') LIKE N'%辅助%' THEN N'辅助结束'
ELSE N'报工'
END AS ,
CAST(ISNULL(b., 0) / 60.0 / 60.0 AS DECIMAL(18, 4)) AS ,
ISNULL(b., 0) AS
FROM #基础数据 AS b
LEFT JOIN #操作人拼接 AS o
ON o.TaskAID = b.TaskAID
AND o. = CONVERT(VARCHAR(19), b., 120)
),
AS
(
SELECT
,
,
,
,
MAX() AS ,
AS ,
COUNT(*) AS ,
SUM(CASE WHEN = N'报工' THEN ELSE 0 END) AS ,
SUM(CASE WHEN = N'辅助结束' THEN ELSE 0 END) AS ,
SUM(CASE WHEN = N'报工' THEN ELSE 0 END) AS ,
SUM(CASE WHEN = N'辅助结束' THEN ELSE 0 END) AS ,
SUM() AS
FROM
GROUP BY , , , ,
),
AS
(
SELECT
,
,
ISNULL(, N'') AS ,
STRING_AGG(CONVERT(NVARCHAR(MAX), ), N',') AS
FROM
(
SELECT DISTINCT
j.,
j.,
ISNULL(j., N'') AS ,
LTRIM(RTRIM(s.value)) AS
FROM AS j
CROSS APPLY STRING_SPLIT(REPLACE(REPLACE(ISNULL(j., N''), N'', N','), N'', N','), N',') AS s
WHERE NULLIF(LTRIM(RTRIM(s.value)), N'') IS NOT NULL
) AS x
GROUP BY , , ISNULL(, N'')
),
AS
(
SELECT
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
b.,
ISNULL(o., N'') AS
FROM AS b
LEFT JOIN AS o
ON o. = b.
AND o. = b.
AND o. = ISNULL(b., N'')
),
AS
(
SELECT
,
,
SUM() AS ,
SUM() AS ,
SUM() AS ,
SUM() AS ,
SUM() AS ,
SUM() AS
FROM
GROUP BY ,
)
SELECT
1 AS [Level],
AS materialCode,
AS materialDesc,
ISNULL(, N'') + N' ' + ISNULL(, N'') AS taskDescription,
CAST(0 AS INT) AS productionOrderNo,
N'' AS station,
CAST( AS VARCHAR(20)) AS reportWorkHours,
CAST( AS VARCHAR(20)) AS auxiliaryWorkHours,
CAST( AS VARCHAR(20)) AS reportFinishQty,
CAST( AS VARCHAR(20)) AS auxiliaryFinishQty,
CAST( AS VARCHAR(20)) AS totalWorkHours,
CAST(CASE WHEN > 0 THEN ( - 0 * ) / ELSE 0 END AS VARCHAR(20)) AS clampingTime,
CAST(0 AS VARCHAR(20)) AS programTime,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementReportPieceHours,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementAuxiliaryPieceHours,
N'' AS operatorNames,
CAST( AS VARCHAR(20)) AS recordCount,
CAST(0 AS INT) AS
FROM
UNION ALL
SELECT
2 AS [Level],
AS materialCode,
AS materialDesc,
ISNULL(, N'') + N' ' + ISNULL(, N'')
+ CASE WHEN NULLIF(ISNULL(, N''), N'') IS NULL THEN N'' ELSE N' ' + END
+ CASE WHEN IS NULL THEN N'' ELSE N'' + CAST( AS VARCHAR(20)) END AS taskDescription,
AS productionOrderNo,
ISNULL(, N'') AS station,
CAST( AS VARCHAR(20)) AS reportWorkHours,
CAST( AS VARCHAR(20)) AS auxiliaryWorkHours,
CAST( AS VARCHAR(20)) AS reportFinishQty,
CAST( AS VARCHAR(20)) AS auxiliaryFinishQty,
CAST( AS VARCHAR(20)) AS totalWorkHours,
CAST(CASE WHEN > 0 THEN ( - 0 * ) / ELSE 0 END AS VARCHAR(20)) AS clampingTime,
CAST(0 AS VARCHAR(20)) AS programTime,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementReportPieceHours,
CAST(CASE WHEN > 0 THEN / ELSE 0 END AS VARCHAR(20)) AS settlementAuxiliaryPieceHours,
ISNULL(, N'') AS operatorNames,
CAST( AS VARCHAR(20)) AS recordCount,
FROM
ORDER BY productionOrderNo, , materialCode, [Level], station;
END
GO

View File

@@ -1617,3 +1617,116 @@ pm run build通过仅有既有警告。
- `work/ProductionManagement/DesignReportTask/04-任务矩阵.md` - `work/ProductionManagement/DesignReportTask/04-任务矩阵.md`
- `work/ProductionManagement/DesignReportTask/05-验收证据.md` - `work/ProductionManagement/DesignReportTask/05-验收证据.md`
- `work/ProductionManagement/DesignReportTask/06-决策记录.md` - `work/ProductionManagement/DesignReportTask/06-决策记录.md`
- `gptlog-process/gpdlog.md`
### 验证结果
- Word 文档已包含 `项目号:具体 SAP 视图和字段后续提供`
- Word 文档已包含 `未结束不能完成`
- Word 文档已包含 `已有设计报工记录不能删除`
- Word 文档已包含 `不上传 SAP``不参与现有生产工时报表`
- 任务矩阵中 `DRT-009 项目号来源` 状态为待确认,`DRT-010 数据库和页面开发` 状态为待开始。
## 2026-06-30 设计报工任务模块文档归档与菜单权限口径补充
### 用户反馈
- 根据修改后的文档,将文档复制到对应路径。
- 在对应路径下新增或修改 README、01-06 文档。
- 将完整执行过程追加到 `/gptlog-process/gpdlog.md`
- 不分配菜单权限。
### 执行过程
1. 确认修改后的源文档为 `doc/设计报工任务模块.docx`
2. 确认对应路径为 `work/ProductionManagement/DesignReportTask/`
3. 将源 Word 文档复制到 `work/ProductionManagement/DesignReportTask/设计报工任务模块.docx`
4. 更新 README 索引,增加复制后的 Word 文档说明,并写入“不分配菜单权限”。
5. 更新 `01-项目功能内容.md`,补充独立性要求和文档归档路径。
6. 更新 `02-项目程序开发详细步骤.md`,删除菜单权限分配动作,明确不写菜单表和角色权限表。
7. 更新 `03-推进台账.md`,记录本轮做了什么、改了哪些文件、验证了什么、下一步是什么。
8. 更新 `04-任务矩阵.md`,新增文档复制和菜单权限口径任务,并将开发验收标准调整为“不分配菜单权限”。
9. 更新 `05-验收证据.md`,记录工作目录归档路径和菜单权限口径。
10. 更新 `06-决策记录.md`,新增 DDR-006本阶段不分配菜单权限。
11. 追加仓库内总日志和绝对路径总日志。
### 修改文件
- `work/ProductionManagement/DesignReportTask/设计报工任务模块.docx`
- `work/ProductionManagement/DesignReportTask/README.md`
- `work/ProductionManagement/DesignReportTask/01-项目功能内容.md`
- `work/ProductionManagement/DesignReportTask/02-项目程序开发详细步骤.md`
- `work/ProductionManagement/DesignReportTask/03-推进台账.md`
- `work/ProductionManagement/DesignReportTask/04-任务矩阵.md`
- `work/ProductionManagement/DesignReportTask/05-验收证据.md`
- `work/ProductionManagement/DesignReportTask/06-决策记录.md`
- `gptlog-process/gpdlog.md`
### 验证结果
- `work/ProductionManagement/DesignReportTask/设计报工任务模块.docx` 已存在。
- README 已列出复制后的 Word 文档。
- `02-项目程序开发详细步骤.md` 已明确本阶段不分配菜单权限。
- `04-任务矩阵.md` 已新增 `DRT-011``DRT-012`
- `06-决策记录.md` 已新增 `DDR-006 本阶段不分配菜单权限`
## 2026-06-30 新建设计报工模块页面、数据表和功能
### 用户反馈
- 新建文档里面的页面、数据表、功能。
- 继续遵守“不分配菜单权限”的要求。
### 执行过程
1. 读取 `work/ProductionManagement/DesignReportTask/01-项目功能内容.md`,确认需要落地 4 个页面、3 张独立表和独立设计报工功能。
2. 读取现有页面和通用数据库调用方式,确认页面使用 `CreateData` / `ExecDatabase` 调用存储过程。
3. 查询数据库中现有物料查询和人员查询返回字段:
- 物料字段包含 `物料编码``物料名称``物料描述`
- 人员字段包含 `人员编号``人员姓名``账号``角色`
4. 新增数据库脚本 `db_backups/create_design_report_task_module_20260630.sql`
5. 第一次发布脚本时SAP 物料字段存在 `ntext``nvarchar` 比较问题,修正为显式 `CAST` 后重新发布。
6. 成功发布 3 张独立表:
- `dbo.MES_设计报工_任务`
- `dbo.MES_设计报工_记录`
- `dbo.MES_设计报工_校验记录`
7. 成功发布 15 个独立过程:
- `设计报工_物料查询`
- `设计报工_人员查询`
- `设计报工_项目查询`
- `设计报工_任务_查询`
- `设计报工_任务_新增`
- `设计报工_任务_编辑`
- `设计报工_任务_删除`
- `设计报工_任务_开始`
- `设计报工_任务_结束`
- `设计报工_任务_完成`
- `设计报工_记录_查询`
- `设计报工_工时校验_查询`
- `设计报工_工时校验_保存`
- `设计报工_工时校验_批量保存`
- `设计报工_工时报表_作业者工时_查询`
8. 事务内验证业务规则:
- 新增测试任务成功。
- 未开始直接完成返回“任务未产生已结束报工,不能完成”。
- 开始任务成功。
- 开始后未结束直接完成返回“任务存在未结束报工,不能完成”。
- 结束任务成功。
- 结束后完成成功。
- 事务回滚,测试数据未保留。
9. 新增 4 个前端页面:
- `src/views/ProductionManagement/DesignReportTask/Task/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Report/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Check/index.vue`
- `src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`
10. 执行 `npm run build`,构建通过,仅有项目既有 asset size、entrypoint size、browserslist warning。
11. 更新 `work/ProductionManagement/DesignReportTask/` 下 README 和 01-06 文档。
12. 本轮未新增菜单权限脚本,未写入菜单表和角色权限表。
### 修改文件
- `db_backups/create_design_report_task_module_20260630.sql`
- `src/views/ProductionManagement/DesignReportTask/Task/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Report/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Check/index.vue`
- `src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`
- `work/ProductionManagement/DesignReportTask/README.md`
- `work/ProductionManagement/DesignReportTask/01-项目功能内容.md`
- `work/ProductionManagement/DesignReportTask/02-项目程序开发详细步骤.md`
- `work/ProductionManagement/DesignReportTask/03-推进台账.md`
- `work/ProductionManagement/DesignReportTask/04-任务矩阵.md`
- `work/ProductionManagement/DesignReportTask/05-验收证据.md`
- `work/ProductionManagement/DesignReportTask/06-决策记录.md`
- `gptlog-process/gpdlog.md`

View File

@@ -197,6 +197,12 @@
@click="getitemdata(scope.row.订单号)">查看</el-button> @click="getitemdata(scope.row.订单号)">查看</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="历史工时" width="100">
<template slot-scope="scope">
<el-button type="text" size="mini"
@click="getWorkHour(scope.row.产品编码)">查看</el-button>
</template>
</el-table-column>
<el-table-column align="center" label="图纸" width="200"> <el-table-column align="center" label="图纸" width="200">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="scope.row.worker !=0" <el-button v-if="scope.row.worker !=0"
@@ -372,6 +378,95 @@
</el-table> </el-table>
</el-card> </el-card>
</el-dialog> </el-dialog>
<el-dialog :visible.sync="dialogcasual2" title="历史工时" center style="min-height: 300px;" width="1400px">
<el-card style="height: 550px">
<el-table
:data="itemdata"
:height="'55vh'"
border
size="mini"
style="margin-top: 20px; width: 95%;"
>
<el-table-column prop="taskDescription" label="任务描述" min-width="380" show-overflow-tooltip>
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level === 1 }">{{ scope.row.taskDescription || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="productionOrderNo" label="生产订单号" width="130" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.productionOrderNo || '' }}
</template>
</el-table-column>
<el-table-column prop="station" label="工位" width="110" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.station || '' }}
</template>
</el-table-column>
<el-table-column prop="reportWorkHours" label="报工工时" width="100" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.reportWorkHours || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="auxiliaryWorkHours" label="辅助工时" width="100" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.auxiliaryWorkHours || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="reportFinishQty" label="报工完成数" width="110" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.reportFinishQty || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="auxiliaryFinishQty" label="辅助完成数" width="110" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.auxiliaryFinishQty || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="totalWorkHours" label="合计工时" width="100" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.totalWorkHours || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="clampingTime" label="装夹时间" width="100" align="center">
<template slot-scope="scope">
{{ scope.row.clampingTime || '' }}
</template>
</el-table-column>
<el-table-column prop="programTime" label="程序时间" width="100" align="center">
<template slot-scope="scope">
{{ scope.row.programTime || '' }}
</template>
</el-table-column>
<el-table-column prop="settlementReportPieceHours" label="结算报工单件工时" width="140" align="center">
<template slot-scope="scope">
{{ scope.row.settlementReportPieceHours || '' }}
</template>
</el-table-column>
<el-table-column prop="settlementAuxiliaryPieceHours" label="结算辅助单件工时" width="140" align="center">
<template slot-scope="scope">
{{ scope.row.settlementAuxiliaryPieceHours || '' }}
</template>
</el-table-column>
<el-table-column prop="operatorNames" label="操作人" width="180" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.operatorNames || '' }}
</template>
</el-table-column>
</el-table>
</el-card>
</el-dialog>
<!-- 图纸弹框 --> <!-- 图纸弹框 -->
<el-dialog :visible.sync="seeVisible" title="图纸" center width="1200px" overflow="scroll" > <el-dialog :visible.sync="seeVisible" title="图纸" center width="1200px" overflow="scroll" >
<div id="el-dialog__body" style="min-height: 500px;"></div> <div id="el-dialog__body" style="min-height: 500px;"></div>
@@ -503,7 +598,8 @@ export default {
}, },
currentTime: "", currentTime: "",
itemdata:[], itemdata:[],
dialogcasual:false dialogcasual:false,
dialogcasual2:false
} }
}, },
computed: { computed: {
@@ -698,6 +794,25 @@ export default {
}) })
}) })
}, },
getWorkHour(item){
var param = []
this.dialogcasual2 = true
this.itemdata = []
param.push(["产品编码",item])
param.push(["合同号",''])
param.push(["订单号",''])
param.push(["工位",''])
param.push(["开始日期",''])
param.push(["结束日期",''])
param.push(["数据条数",100])
var Data = this.CreateData('11', '生产管理_结算工时_查询',param)
this.ExecDatabase(Data).then(response => {
response.data.forEach(element => {
if(element.Level == 2)
this.itemdata.push(element)
})
})
},
getCurrentTime() { getCurrentTime() {
const now = new Date(); const now = new Date();
const year = now.getFullYear(); const year = now.getFullYear();

View File

@@ -180,6 +180,12 @@
@click="getitemdata(scope.row.订单号)">查看</el-button> @click="getitemdata(scope.row.订单号)">查看</el-button>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column align="center" label="历史工时" width="100">
<template slot-scope="scope">
<el-button type="text" size="mini"
@click="getWorkHour(scope.row.产品编码)">查看</el-button>
</template>
</el-table-column>
<el-table-column align="center" prop="备注" label="备注" width="150" show-overflow-tooltip/> <el-table-column align="center" prop="备注" label="备注" width="150" show-overflow-tooltip/>
<el-table-column align="center" prop="行文本备注" label="工艺备注" width="120" /> <el-table-column align="center" prop="行文本备注" label="工艺备注" width="120" />
<el-table-column align="center" prop="任务概述" label="工艺说明" width="120" /> <el-table-column align="center" prop="任务概述" label="工艺说明" width="120" />
@@ -334,7 +340,95 @@
</el-table> </el-table>
</el-card> </el-card>
</el-dialog> </el-dialog>
<el-dialog :visible.sync="dialogcasual2" title="历史工时" center style="min-height: 300px;" width="1400px">
<el-card style="height: 550px">
<el-table
:data="itemdata"
:height="'55vh'"
border
size="mini"
style="margin-top: 20px; width: 95%;"
>
<el-table-column prop="taskDescription" label="任务描述" min-width="380" show-overflow-tooltip>
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level === 1 }">{{ scope.row.taskDescription || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="productionOrderNo" label="生产订单号" width="130" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.productionOrderNo || '' }}
</template>
</el-table-column>
<el-table-column prop="station" label="工位" width="110" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.station || '' }}
</template>
</el-table-column>
<el-table-column prop="reportWorkHours" label="报工工时" width="100" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.reportWorkHours || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="auxiliaryWorkHours" label="辅助工时" width="100" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.auxiliaryWorkHours || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="reportFinishQty" label="报工完成数" width="110" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.reportFinishQty || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="auxiliaryFinishQty" label="辅助完成数" width="110" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.auxiliaryFinishQty || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="totalWorkHours" label="合计工时" width="100" align="center">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.totalWorkHours || '' }}</span>
</template>
</el-table-column>
<el-table-column prop="clampingTime" label="装夹时间" width="100" align="center">
<template slot-scope="scope">
{{ scope.row.clampingTime || '' }}
</template>
</el-table-column>
<el-table-column prop="programTime" label="程序时间" width="100" align="center">
<template slot-scope="scope">
{{ scope.row.programTime || '' }}
</template>
</el-table-column>
<el-table-column prop="settlementReportPieceHours" label="结算报工单件工时" width="140" align="center">
<template slot-scope="scope">
{{ scope.row.settlementReportPieceHours || '' }}
</template>
</el-table-column>
<el-table-column prop="settlementAuxiliaryPieceHours" label="结算辅助单件工时" width="140" align="center">
<template slot-scope="scope">
{{ scope.row.settlementAuxiliaryPieceHours || '' }}
</template>
</el-table-column>
<el-table-column prop="operatorNames" label="操作人" width="180" align="center" show-overflow-tooltip>
<template slot-scope="scope">
{{ scope.row.operatorNames || '' }}
</template>
</el-table-column>
</el-table>
</el-card>
</el-dialog>
</div> </div>
</template> </template>
@@ -351,6 +445,7 @@ export default {
data() { data() {
return { return {
dialogcasual:false, dialogcasual:false,
dialogcasual2:false,
activeTab: 'form', activeTab: 'form',
doneactiveTab: 'form', doneactiveTab: 'form',
orderNo: '', orderNo: '',
@@ -613,6 +708,25 @@ export default {
}) })
}) })
}, },
getWorkHour(item){
var param = []
this.dialogcasual2 = true
this.itemdata = []
param.push(["产品编码",item])
param.push(["合同号",''])
param.push(["订单号",''])
param.push(["工位",''])
param.push(["开始日期",''])
param.push(["结束日期",''])
param.push(["数据条数",100])
var Data = this.CreateData('11', '生产管理_结算工时_查询',param)
this.ExecDatabase(Data).then(response => {
response.data.forEach(element => {
if(element.Level == 2)
this.itemdata.push(element)
})
})
},
getCurrentTime() { getCurrentTime() {
const now = new Date(); const now = new Date();
const year = now.getFullYear(); const year = now.getFullYear();

View File

@@ -396,7 +396,12 @@ export default {
return this.getProcessBaseClass(process) return this.getProcessBaseClass(process)
}, },
getRouteProcessName(process) { getRouteProcessName(process) {
return String(process.工序名称 || '') const name = String(process.工序名称 || '')
const assignee = String(process.指派对象 || '')
if (!assignee || name.includes(`(${assignee})`) || name.includes(`${assignee}`)) {
return name
}
return `${name}(${assignee})`
}, },
escapeProcessHtml(value) { escapeProcessHtml(value) {
return String(value == null ? '' : value) return String(value == null ? '' : value)

View File

@@ -0,0 +1,281 @@
<template>
<div class="app-container design-check-page">
<el-card>
<div class="search-container" @keyup.enter="searchTable">
<span class="show-text">任务ID:</span>
<el-input v-model="searchForm.did" clearable size="small" style="width: 90px; margin-right: 8px" />
<span class="show-text">项目号:</span>
<el-input v-model="searchForm.projectNo" clearable size="small" style="width: 130px; margin-right: 8px" />
<span class="show-text">物料编码:</span>
<el-input v-model="searchForm.itemCode" clearable size="small" style="width: 170px; margin-right: 8px" />
<span class="show-text">操作人:</span>
<el-input v-model="searchForm.operator" clearable size="small" style="width: 120px; margin-right: 8px" />
<span class="show-text">开始日期:</span>
<el-date-picker v-model="searchForm.startDate" clearable type="date" value-format="yyyy-MM-dd" size="small" style="width: 140px; margin-right: 8px" />
<span class="show-text">结束日期:</span>
<el-date-picker v-model="searchForm.endDate" clearable type="date" value-format="yyyy-MM-dd" size="small" style="width: 140px; margin-right: 8px" />
<span class="show-text">校验状态:</span>
<el-select v-model="searchForm.checkStatus" size="small" style="width: 110px; margin-right: 8px">
<el-option label="未校验" value="未校验" />
<el-option label="已校验" value="已校验" />
<el-option label="全部" value="全部" />
</el-select>
<el-button :loading="loading" icon="el-icon-search" plain size="small" type="primary" @click="searchTable">查询</el-button>
<el-button :disabled="!multipleSelection.length" icon="el-icon-check" plain size="small" type="success" @click="batchValidate">批量校验</el-button>
</div>
<el-table
v-loading="loading"
:data="tableData"
border
height="74vh"
highlight-current-row
size="mini"
style="width: 100%; margin-top: 12px"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="50" align="center" />
<el-table-column align="center" fixed label="RID" prop="RID" width="70" />
<el-table-column align="center" fixed label="DID" prop="DID" width="70" />
<el-table-column align="center" label="校验状态" width="90">
<template slot-scope="scope">
<el-tag :type="scope.row.已校验 ? 'success' : 'info'" size="mini">{{ scope.row.校验状态 }}</el-tag>
</template>
</el-table-column>
<el-table-column align="left" label="项目号" prop="项目号" width="120" show-overflow-tooltip />
<el-table-column align="left" label="物料编码" prop="物料编码" width="170" show-overflow-tooltip />
<el-table-column align="left" label="物料名称" prop="物料名称" width="180" show-overflow-tooltip />
<el-table-column align="left" label="图号" prop="图号" width="120" show-overflow-tooltip />
<el-table-column align="left" label="任务描述" prop="任务描述" width="220" show-overflow-tooltip />
<el-table-column align="left" label="操作人" prop="操作人" width="110" 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="right" label="工时(h)" prop="工时小时" width="90" />
<el-table-column align="left" label="校验人" prop="校验人" width="110" show-overflow-tooltip />
<el-table-column align="center" label="校验时间" prop="校验时间" width="150" />
<el-table-column align="left" label="备注" prop="备注" width="180" show-overflow-tooltip />
<el-table-column align="center" fixed="right" label="操作" width="90">
<template slot-scope="scope">
<el-button type="text" size="mini" :disabled="!!scope.row.已校验" @click="openValidate(scope.row)">
{{ scope.row.已校验 ? '已校验' : '校验' }}
</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog
:visible.sync="dialogVisible"
title="设计工时校验"
width="620px"
center
:close-on-click-modal="false"
>
<el-form ref="checkForm" :model="formData" :rules="rules" label-width="110px" size="small">
<el-form-item label="RID">
<el-input v-model="formData.RID" disabled />
</el-form-item>
<el-form-item label="任务">
<el-input :value="`${formData.DID || ''} ${formData.任务描述 || ''}`" disabled />
</el-form-item>
<el-form-item label="操作人">
<el-input v-model="formData.操作人" disabled />
</el-form-item>
<el-form-item label="开始时间" prop="开始时间">
<el-date-picker v-model="formData.开始时间" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
</el-form-item>
<el-form-item label="结束时间" prop="结束时间">
<el-date-picker v-model="formData.结束时间" type="datetime" value-format="yyyy-MM-dd HH:mm:ss" style="width: 100%" />
</el-form-item>
<el-form-item label="工时(h)">
<el-input :value="calculatedHours" disabled />
</el-form-item>
<el-form-item label="校验备注">
<el-input v-model="formData.备注" type="textarea" :rows="3" />
</el-form-item>
</el-form>
<div slot="footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="submitValidate">保存校验</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'DesignReportCheck',
data() {
return {
loading: false,
submitLoading: false,
dialogVisible: false,
tableData: [],
multipleSelection: [],
searchForm: {
did: '',
projectNo: '',
itemCode: '',
operator: '',
startDate: '',
endDate: '',
checkStatus: '未校验'
},
formData: {
RID: '',
DID: '',
任务描述: '',
操作人: '',
开始时间: '',
结束时间: '',
备注: ''
},
rules: {
开始时间: [{ required: true, message: '请选择开始时间', trigger: 'change' }],
结束时间: [{ required: true, message: '请选择结束时间', trigger: 'change' }]
}
}
},
computed: {
calculatedHours() {
if (!this.formData.开始时间 || !this.formData.结束时间) return ''
const start = new Date(this.formData.开始时间)
const end = new Date(this.formData.结束时间)
const diff = end.getTime() - start.getTime()
if (Number.isNaN(diff) || diff <= 0) return ''
return (diff / 3600000).toFixed(2)
}
},
created() {
this.searchTable()
},
methods: {
buildSearchParams() {
return [
['DID', this.searchForm.did || 0],
['项目号', this.searchForm.projectNo || ''],
['物料编码', this.searchForm.itemCode || ''],
['操作人', this.searchForm.operator || ''],
['开始日期', this.searchForm.startDate || ''],
['结束日期', this.searchForm.endDate || ''],
['校验状态', this.searchForm.checkStatus || '全部']
]
},
async searchTable() {
this.loading = true
const data = this.CreateData('11', '设计报工_工时校验_查询', this.buildSearchParams())
try {
const response = await this.ExecDatabase(data)
this.tableData = response.data || []
} catch (error) {
console.error('设计工时校验查询失败:', error)
this.$message.error('查询失败')
} finally {
this.loading = false
}
},
handleSelectionChange(selection) {
this.multipleSelection = selection
},
openValidate(row) {
this.formData = {
RID: row.RID,
DID: row.DID,
任务描述: row.任务描述,
操作人: row.操作人,
开始时间: row.开始时间 || '',
结束时间: row.结束时间 || '',
备注: row.备注 || ''
}
this.dialogVisible = true
this.$nextTick(() => this.$refs.checkForm && this.$refs.checkForm.clearValidate())
},
submitValidate() {
this.$refs.checkForm.validate(async valid => {
if (!valid) return
if (new Date(this.formData.结束时间) <= new Date(this.formData.开始时间)) {
this.$message.error('结束时间必须大于开始时间')
return
}
this.submitLoading = true
const params = [
['RID', this.formData.RID],
['开始时间', this.formData.开始时间],
['结束时间', this.formData.结束时间],
['校验人ID', this.currentUserId()],
['校验人', this.currentUserName()],
['校验备注', this.formData.备注 || '']
]
const data = this.CreateData('12', '设计报工_工时校验_保存', params)
try {
const response = await this.ExecDatabase(data)
const result = this.getResult(response)
if (String(result.result) === '1') {
this.$message.success(result.message || '校验成功')
this.dialogVisible = false
this.searchTable()
} else {
this.$message.error(result.message || '校验失败')
}
} catch (error) {
console.error('设计工时校验保存失败:', error)
this.$message.error('校验失败')
} finally {
this.submitLoading = false
}
})
},
batchValidate() {
const rows = this.multipleSelection.filter(row => !row.已校验 && row.开始时间 && row.结束时间)
if (!rows.length) {
this.$message.warning('请选择未校验且已有结束时间的记录')
return
}
this.$confirm(`确定批量校验 ${rows.length} 条设计报工记录吗?`, '提示', { type: 'warning' })
.then(async () => {
const params = [
['RIDs', rows.map(row => row.RID).join(',')],
['校验人ID', this.currentUserId()],
['校验人', this.currentUserName()]
]
const data = this.CreateData('12', '设计报工_工时校验_批量保存', params)
const response = await this.ExecDatabase(data)
const result = this.getResult(response)
if (String(result.result) === '1') {
this.$message.success(result.message || '批量校验成功')
this.searchTable()
} else {
this.$message.error(result.message || '批量校验失败')
}
})
.catch(() => {})
},
getResult(response) {
const data = response && response.data
if (Array.isArray(data)) return data[0] || {}
if (data && Array.isArray(data.result)) return data.result[0] || {}
return data || {}
},
currentUserId() {
return (this.$store && this.$store.getters && this.$store.getters.id) || ''
},
currentUserName() {
return (this.$store && this.$store.getters && this.$store.getters.name) || ''
}
}
}
</script>
<style scoped>
.design-check-page {
padding: 12px;
}
.search-container {
line-height: 34px;
}
.show-text {
margin-right: 4px;
}
</style>

View File

@@ -0,0 +1,192 @@
<template>
<div class="app-container design-hours-report-page">
<el-card>
<div class="search-container" @keyup.enter="searchTable">
<span class="show-text">开始日期:</span>
<el-date-picker
v-model="searchForm.startDate"
clearable
type="date"
value-format="yyyy-MM-dd"
size="small"
style="width: 140px; margin-right: 8px"
/>
<span class="show-text">结束日期:</span>
<el-date-picker
v-model="searchForm.endDate"
clearable
type="date"
value-format="yyyy-MM-dd"
size="small"
style="width: 140px; margin-right: 8px"
/>
<span class="show-text">操作人:</span>
<el-input v-model="searchForm.operator" clearable size="small" style="width: 120px; margin-right: 8px" />
<span class="show-text">项目号:</span>
<el-input v-model="searchForm.projectNo" clearable size="small" style="width: 130px; margin-right: 8px" />
<span class="show-text">物料编码:</span>
<el-input v-model="searchForm.itemCode" clearable size="small" style="width: 170px; margin-right: 8px" />
<span class="show-text">任务ID:</span>
<el-input v-model="searchForm.did" clearable size="small" style="width: 90px; margin-right: 8px" />
<el-button :loading="loading" icon="el-icon-search" plain size="small" type="primary" @click="searchTable">查询</el-button>
</div>
<el-table
v-loading="loading"
:data="tableData"
border
default-expand-all
height="74vh"
row-key="id"
:tree-props="{ children: 'children' }"
size="mini"
style="width: 100%; margin-top: 12px"
>
<el-table-column label="操作人 / 日期 / 任务" min-width="260" show-overflow-tooltip>
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.Level <= 2 }">{{ getTreeTitle(scope.row) }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="工作日期" prop="工作日期" width="110" />
<el-table-column align="center" label="RID" prop="RID" width="70" />
<el-table-column align="center" label="DID" prop="DID" width="70" />
<el-table-column align="left" label="项目号" prop="项目号" width="120" show-overflow-tooltip />
<el-table-column align="left" label="物料编码" prop="物料编码" width="170" show-overflow-tooltip />
<el-table-column align="left" label="物料名称" prop="物料名称" width="180" show-overflow-tooltip />
<el-table-column align="left" label="图号" prop="图号" width="120" show-overflow-tooltip />
<el-table-column align="center" label="报工次数" prop="报工次数" width="90" />
<el-table-column align="right" label="工时(h)" prop="工时小时" width="90">
<template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.Level <= 2 }">{{ formatHours(scope.row.工时小时) }}</span>
</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="center" label="校验状态" prop="校验状态" width="90" />
<el-table-column align="left" label="备注" prop="备注" min-width="160" show-overflow-tooltip />
</el-table>
<div class="summary-footer">
<span>总工时<strong>{{ totalHours }}</strong> 小时</span>
</div>
</el-card>
</div>
</template>
<script>
export default {
name: 'DesignReportHoursReport',
data() {
return {
loading: false,
tableData: [],
searchForm: {
startDate: '',
endDate: '',
operator: '',
projectNo: '',
itemCode: '',
did: ''
}
}
},
computed: {
totalHours() {
const total = this.tableData.reduce((sum, row) => sum + (Number(row.工时小时) || 0), 0)
return total.toFixed(2)
}
},
created() {
this.searchTable()
},
methods: {
buildSearchParams() {
return [
['开始日期', this.searchForm.startDate || ''],
['结束日期', this.searchForm.endDate || ''],
['操作人', this.searchForm.operator || ''],
['项目号', this.searchForm.projectNo || ''],
['物料编码', this.searchForm.itemCode || ''],
['DID', this.searchForm.did || 0]
]
},
async searchTable() {
this.loading = true
const data = this.CreateData('11', '设计报工_工时报表_作业者工时_查询', this.buildSearchParams())
try {
const response = await this.ExecDatabase(data)
this.tableData = this.buildTree(response.data || [])
} catch (error) {
console.error('设计工时报表查询失败:', error)
this.$message.error('查询失败')
} finally {
this.loading = false
}
},
buildTree(rows) {
const personMap = new Map()
const dateMap = new Map()
rows.forEach(row => {
if (row.Level === 1) {
personMap.set(row.id, { ...row, children: [] })
}
})
rows.forEach(row => {
if (row.Level === 2) {
const item = { ...row, children: [] }
dateMap.set(row.id, item)
const parent = personMap.get(row.parentId)
if (parent) parent.children.push(item)
}
})
rows.forEach(row => {
if (row.Level === 3) {
const parent = dateMap.get(row.parentId)
if (parent) parent.children.push({ ...row })
}
})
return Array.from(personMap.values())
},
getTreeTitle(row) {
if (row.Level === 1) return row.操作人 || '未填写操作人'
if (row.Level === 2) return row.工作日期 ? `日期 ${row.工作日期}` : '未填写日期'
return row.任务描述 || `${row.DID || ''}`
},
formatHours(value) {
if (value === null || value === undefined || value === '') return ''
const numberValue = Number(value)
if (Number.isNaN(numberValue)) return ''
return numberValue.toFixed(2)
}
}
}
</script>
<style scoped>
.design-hours-report-page {
padding: 12px;
}
.search-container {
line-height: 34px;
}
.show-text {
margin-right: 4px;
}
.bold-text {
font-weight: 600;
}
.summary-footer {
height: 36px;
line-height: 36px;
text-align: right;
color: #303133;
}
</style>

View File

@@ -0,0 +1,202 @@
<template>
<div class="app-container design-report-page">
<el-card>
<div class="search-container" @keyup.enter="searchTable">
<span class="show-text">任务ID:</span>
<el-input v-model="searchForm.did" clearable size="small" style="width: 90px; margin-right: 8px" />
<span class="show-text">项目号:</span>
<el-input v-model="searchForm.projectNo" clearable size="small" style="width: 130px; margin-right: 8px" />
<span class="show-text">物料编码:</span>
<el-input v-model="searchForm.itemCode" clearable size="small" style="width: 170px; margin-right: 8px" />
<span class="show-text">图号:</span>
<el-input v-model="searchForm.drawingNo" clearable size="small" style="width: 120px; margin-right: 8px" />
<span class="show-text">父件编码:</span>
<el-input v-model="searchForm.parentItemCode" clearable size="small" style="width: 170px; margin-right: 8px" />
<span class="show-text">状态:</span>
<el-select v-model="searchForm.status" clearable size="small" style="width: 110px; margin-right: 8px">
<el-option label="全部" value="全部" />
<el-option label="待开始" value="待开始" />
<el-option label="执行中" value="执行中" />
<el-option label="已结束" value="已结束" />
<el-option label="已完成" value="已完成" />
</el-select>
<el-button :loading="loading" icon="el-icon-search" plain size="small" type="primary" @click="searchTable">查询</el-button>
</div>
<el-table
v-loading="loading"
:data="tableData"
border
height="74vh"
highlight-current-row
size="mini"
style="width: 100%; margin-top: 12px"
>
<el-table-column align="center" fixed label="DID" prop="DID" width="70" />
<el-table-column align="center" fixed label="状态" prop="单据状态" width="90">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.单据状态)" size="mini">{{ scope.row.单据状态 }}</el-tag>
</template>
</el-table-column>
<el-table-column align="left" label="项目号" prop="项目号" width="120" show-overflow-tooltip />
<el-table-column align="left" label="物料编码" prop="物料编码" width="170" show-overflow-tooltip />
<el-table-column align="left" label="物料名称" prop="物料名称" width="180" show-overflow-tooltip />
<el-table-column align="left" label="图号" prop="图号" width="120" show-overflow-tooltip />
<el-table-column align="left" label="任务描述" prop="任务描述" width="220" 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="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="180">
<template slot-scope="scope">
<el-button type="text" size="mini" :disabled="!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>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
export default {
name: 'DesignReportWork',
data() {
return {
loading: false,
actionLoading: false,
tableData: [],
searchForm: {
did: '',
projectNo: '',
itemCode: '',
drawingNo: '',
parentItemCode: '',
status: ''
}
}
},
created() {
this.searchTable()
},
methods: {
buildSearchParams() {
return [
['DID', this.searchForm.did || 0],
['项目号', this.searchForm.projectNo || ''],
['物料编码', this.searchForm.itemCode || ''],
['图号', this.searchForm.drawingNo || ''],
['关联父件物料编码', this.searchForm.parentItemCode || ''],
['预计开始时间_Start', ''],
['预计开始时间_End', ''],
['预计结束时间_Start', ''],
['预计结束时间_End', ''],
['单据状态', this.searchForm.status || '']
]
},
async searchTable() {
this.loading = true
const data = this.CreateData('11', '设计报工_任务_查询', this.buildSearchParams())
try {
const response = await this.ExecDatabase(data)
this.tableData = response.data || []
} catch (error) {
console.error('设计报工任务查询失败:', error)
this.$message.error('查询失败')
} finally {
this.loading = false
}
},
canStart(row) {
return row.单据状态 !== '已完成' && Number(row.未结束报工数 || 0) === 0
},
canEnd(row) {
return row.单据状态 !== '已完成' && Number(row.未结束报工数 || 0) > 0
},
canComplete(row) {
return row.单据状态 !== '已完成' && Number(row.未结束报工数 || 0) === 0 && Number(row.报工次数 || 0) > 0
},
startTask(row) {
this.runAction('设计报工_任务_开始', [
['DID', row.DID],
['操作人ID', this.currentUserId()],
['操作人', this.currentUserName()]
], '开始成功')
},
endTask(row) {
this.runAction('设计报工_任务_结束', [
['DID', row.DID],
['操作人ID', this.currentUserId()],
['操作人', this.currentUserName()]
], '结束成功')
},
completeTask(row) {
this.$confirm(`确定完成设计任务 DID ${row.DID} 吗?`, '提示', { type: 'warning' })
.then(() => {
this.runAction('设计报工_任务_完成', [
['DID', row.DID],
['操作人', this.currentUserName()]
], '完成成功')
})
.catch(() => {})
},
async runAction(procedure, params, defaultMessage) {
if (this.actionLoading) return
this.actionLoading = true
const data = this.CreateData('12', procedure, params)
try {
const response = await this.ExecDatabase(data)
const result = this.getResult(response)
if (String(result.result) === '1') {
this.$message.success(result.message || defaultMessage)
this.searchTable()
} else {
this.$message.error(result.message || '操作失败')
}
} catch (error) {
console.error(`${procedure}失败:`, error)
this.$message.error('操作失败')
} finally {
this.actionLoading = false
}
},
getResult(response) {
const data = response && response.data
if (Array.isArray(data)) return data[0] || {}
if (data && Array.isArray(data.result)) return data.result[0] || {}
return data || {}
},
currentUserId() {
return (this.$store && this.$store.getters && this.$store.getters.id) || ''
},
currentUserName() {
return (this.$store && this.$store.getters && this.$store.getters.name) || ''
},
getStatusType(status) {
if (status === '已完成') return 'success'
if (status === '执行中') return 'warning'
if (status === '已结束') return 'primary'
return 'info'
}
}
}
</script>
<style scoped>
.design-report-page {
padding: 12px;
}
.search-container {
line-height: 34px;
}
.show-text {
margin-right: 4px;
}
</style>

View File

@@ -0,0 +1,578 @@
<template>
<div class="app-container design-task-page">
<el-card>
<div class="search-container" @keyup.enter="searchTable">
<span class="show-text">任务ID:</span>
<el-input v-model="searchForm.did" clearable size="small" style="width: 90px; margin-right: 8px" />
<span class="show-text">项目号:</span>
<el-select
v-model="searchForm.projectNo"
clearable
filterable
remote
:remote-method="queryProjects"
size="small"
style="width: 150px; margin-right: 8px"
>
<el-option v-for="item in projectOptions" :key="item.项目号" :label="item.项目号" :value="item.项目号" />
</el-select>
<span class="show-text">物料编码:</span>
<el-select
v-model="searchForm.itemCode"
clearable
filterable
remote
:remote-method="queryMaterialOptions"
size="small"
style="width: 190px; margin-right: 8px"
>
<el-option
v-for="item in materialOptions"
:key="item.物料编码"
:label="formatMaterialLabel(item)"
:value="item.物料编码"
/>
</el-select>
<span class="show-text">图号:</span>
<el-input v-model="searchForm.drawingNo" clearable size="small" style="width: 120px; margin-right: 8px" />
<span class="show-text">父件编码:</span>
<el-select
v-model="searchForm.parentItemCode"
clearable
filterable
remote
:remote-method="queryParentMaterialOptions"
size="small"
style="width: 190px; margin-right: 8px"
>
<el-option
v-for="item in parentMaterialOptions"
:key="item.物料编码"
:label="formatMaterialLabel(item)"
:value="item.物料编码"
/>
</el-select>
<span class="show-text">状态:</span>
<el-select v-model="searchForm.status" clearable size="small" style="width: 110px; margin-right: 8px">
<el-option label="全部" value="全部" />
<el-option label="待开始" value="待开始" />
<el-option label="执行中" value="执行中" />
<el-option label="已结束" value="已结束" />
<el-option label="已完成" value="已完成" />
</el-select>
<br>
<span class="show-text">预计开始:</span>
<el-date-picker
v-model="searchForm.planStartFrom"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
style="width: 140px; margin-right: 4px"
/>
<span class="date-separator"></span>
<el-date-picker
v-model="searchForm.planStartTo"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
style="width: 140px; margin-right: 8px"
/>
<span class="show-text">预计结束:</span>
<el-date-picker
v-model="searchForm.planEndFrom"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
style="width: 140px; margin-right: 4px"
/>
<span class="date-separator"></span>
<el-date-picker
v-model="searchForm.planEndTo"
clearable
size="small"
type="date"
value-format="yyyy-MM-dd"
style="width: 140px; margin-right: 8px"
/>
<el-button :loading="loading" icon="el-icon-search" plain size="small" type="primary" @click="searchTable">查询</el-button>
<el-button icon="el-icon-plus" plain size="small" type="success" @click="openAdd">新建</el-button>
</div>
<el-table
v-loading="loading"
:data="tableData"
border
height="70vh"
highlight-current-row
size="mini"
style="width: 100%; margin-top: 12px"
>
<el-table-column align="center" fixed label="DID" prop="DID" width="70" />
<el-table-column align="center" fixed label="状态" prop="单据状态" width="90">
<template slot-scope="scope">
<el-tag :type="getStatusType(scope.row.单据状态)" size="mini">{{ scope.row.单据状态 }}</el-tag>
</template>
</el-table-column>
<el-table-column align="left" label="项目号" prop="项目号" width="120" show-overflow-tooltip />
<el-table-column align="left" label="物料编码" prop="物料编码" width="170" show-overflow-tooltip />
<el-table-column align="left" label="物料名称" prop="物料名称" width="180" show-overflow-tooltip />
<el-table-column align="left" label="图号" prop="图号" width="130" show-overflow-tooltip />
<el-table-column align="left" label="任务描述" prop="任务描述" width="220" show-overflow-tooltip />
<el-table-column align="left" label="父件物料编码" prop="关联父件物料编码" width="160" show-overflow-tooltip />
<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="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="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 />
<el-table-column align="center" fixed="right" label="操作" width="130">
<template slot-scope="scope">
<el-button type="text" size="mini" @click="openEdit(scope.row)">编辑</el-button>
<el-button type="text" size="mini" class="danger-action" @click="deleteTask(scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<el-dialog
:visible.sync="dialogVisible"
:title="isEdit ? '编辑设计任务' : '新建设计任务'"
width="860px"
center
:close-on-click-modal="false"
>
<el-form ref="taskForm" :model="formData" :rules="rules" label-width="130px" size="small">
<el-row :gutter="12">
<el-col v-if="isEdit" :span="12">
<el-form-item label="DID">
<el-input v-model="formData.DID" disabled />
</el-form-item>
</el-col>
<el-col v-if="isEdit" :span="12">
<el-form-item label="创建日期">
<el-input v-model="formData.创建日期" disabled />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="项目号">
<el-select
v-model="formData.项目号"
allow-create
clearable
filterable
remote
default-first-option
:remote-method="queryProjects"
style="width: 100%"
>
<el-option v-for="item in projectOptions" :key="item.项目号" :label="item.项目号" :value="item.项目号" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="物料编码" prop="物料编码">
<el-select
v-model="formData.物料编码"
clearable
filterable
remote
:remote-method="queryMaterialOptions"
style="width: 100%"
@change="handleMaterialChange"
>
<el-option
v-for="item in materialOptions"
:key="item.物料编码"
:label="formatMaterialLabel(item)"
:value="item.物料编码"
/>
</el-select>
</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="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.任务描述" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="父件物料编码">
<el-select
v-model="formData.关联父件物料编码"
clearable
filterable
remote
:remote-method="queryParentMaterialOptions"
style="width: 100%"
@change="handleParentMaterialChange"
>
<el-option
v-for="item in parentMaterialOptions"
:key="item.物料编码"
:label="formatMaterialLabel(item)"
:value="item.物料编码"
/>
</el-select>
</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="12">
<el-form-item label="研发立项号">
<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="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" />
</el-form-item>
</el-col>
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" :loading="submitLoading" @click="submitForm">保存</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'DesignReportTask',
data() {
return {
loading: false,
submitLoading: false,
dialogVisible: false,
isEdit: false,
tableData: [],
projectOptions: [],
materialOptions: [],
parentMaterialOptions: [],
personnelOptions: [],
searchForm: {
did: '',
projectNo: '',
itemCode: '',
drawingNo: '',
parentItemCode: '',
planStartFrom: '',
planStartTo: '',
planEndFrom: '',
planEndTo: '',
status: ''
},
formData: this.getEmptyForm(),
rules: {
物料编码: [{ required: true, message: '请选择物料编码', trigger: 'change' }],
任务描述: [{ required: true, message: '请输入任务描述', trigger: 'blur' }],
assigneeIds: [{ type: 'array', required: true, message: '请选择指派对象', trigger: 'change' }]
}
}
},
created() {
this.queryProjects('')
this.queryPersonnel('')
this.searchTable()
},
methods: {
getEmptyForm() {
return {
DID: '',
项目号: '',
物料编码: '',
物料名称: '',
图号: '',
任务描述: '',
关联父件物料编码: '',
关联父件物料名称: '',
设计要求: '',
研发立项号: '',
研发目的: '',
指派对象ID: '',
指派对象: '',
assigneeIds: [],
预计开始时间: '',
预计结束时间: '',
创建日期: '',
备注: ''
}
},
buildSearchParams() {
return [
['DID', this.searchForm.did || 0],
['项目号', this.searchForm.projectNo || ''],
['物料编码', this.searchForm.itemCode || ''],
['图号', this.searchForm.drawingNo || ''],
['关联父件物料编码', this.searchForm.parentItemCode || ''],
['预计开始时间_Start', this.searchForm.planStartFrom || ''],
['预计开始时间_End', this.searchForm.planStartTo || ''],
['预计结束时间_Start', this.searchForm.planEndFrom || ''],
['预计结束时间_End', this.searchForm.planEndTo || ''],
['单据状态', this.searchForm.status || '']
]
},
async searchTable() {
this.loading = true
const data = this.CreateData('11', '设计报工_任务_查询', this.buildSearchParams())
try {
const response = await this.ExecDatabase(data)
this.tableData = response.data || []
} catch (error) {
console.error('设计任务查询失败:', error)
this.$message.error('查询失败')
} finally {
this.loading = false
}
},
openAdd() {
this.isEdit = false
this.formData = this.getEmptyForm()
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) : []
this.formData = {
...this.getEmptyForm(),
...row,
assigneeIds,
预计开始时间: 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.dialogVisible = true
this.$nextTick(() => this.$refs.taskForm && this.$refs.taskForm.clearValidate())
},
submitForm() {
this.$refs.taskForm.validate(async valid => {
if (!valid) return
this.submitLoading = true
const procedure = this.isEdit ? '设计报工_任务_编辑' : '设计报工_任务_新增'
const params = this.buildSaveParams()
const data = this.CreateData('12', procedure, params)
try {
const response = await this.ExecDatabase(data)
const result = this.getResult(response)
if (String(result.result) === '1') {
this.$message.success(result.message || '保存成功')
this.dialogVisible = false
this.searchTable()
} else {
this.$message.error(result.message || '保存失败')
}
} catch (error) {
console.error('设计任务保存失败:', error)
this.$message.error('保存失败')
} finally {
this.submitLoading = false
}
})
},
buildSaveParams() {
const params = []
if (this.isEdit) params.push(['DID', this.formData.DID || 0])
params.push(['项目号', this.formData.项目号 || ''])
params.push(['物料编码', this.formData.物料编码 || ''])
params.push(['物料名称', this.formData.物料名称 || ''])
params.push(['图号', this.formData.图号 || ''])
params.push(['任务描述', this.formData.任务描述 || ''])
params.push(['关联父件物料编码', this.formData.关联父件物料编码 || ''])
params.push(['关联父件物料名称', this.formData.关联父件物料名称 || ''])
params.push(['设计要求', this.formData.设计要求 || ''])
params.push(['研发立项号', this.formData.研发立项号 || ''])
params.push(['研发目的', this.formData.研发目的 || ''])
params.push(['指派对象ID', this.formData.指派对象ID || ''])
params.push(['指派对象', this.formData.指派对象 || ''])
params.push(['预计开始时间', this.formData.预计开始时间 || ''])
params.push(['预计结束时间', this.formData.预计结束时间 || ''])
params.push([this.isEdit ? '最后编辑人' : '创建人', this.currentUserName()])
params.push(['备注', this.formData.备注 || ''])
return params
},
deleteTask(row) {
this.$confirm(`确定删除设计任务 DID ${row.DID} 吗?已有报工记录的任务不能删除。`, '提示', { type: 'warning' })
.then(async () => {
const data = this.CreateData('12', '设计报工_任务_删除', [['DID', row.DID]])
const response = await this.ExecDatabase(data)
const result = this.getResult(response)
if (String(result.result) === '1') {
this.$message.success(result.message || '删除成功')
this.searchTable()
} else {
this.$message.error(result.message || '删除失败')
}
})
.catch(() => {})
},
async queryProjects(query) {
const data = this.CreateData('11', '设计报工_项目查询', [['过滤', query || '']])
try {
const response = await this.ExecDatabase(data)
this.projectOptions = response.data || []
} catch (error) {
this.projectOptions = []
}
},
async queryMaterialOptions(query) {
const data = this.CreateData('11', '设计报工_物料查询', [['过滤', query || '']])
try {
const response = await this.ExecDatabase(data)
this.materialOptions = response.data || []
} catch (error) {
this.materialOptions = []
}
},
async queryParentMaterialOptions(query) {
const data = this.CreateData('11', '设计报工_物料查询', [['过滤', query || '']])
try {
const response = await this.ExecDatabase(data)
this.parentMaterialOptions = response.data || []
} catch (error) {
this.parentMaterialOptions = []
}
},
async queryPersonnel(query) {
const data = this.CreateData('11', '设计报工_人员查询', [['过滤', query || '']])
try {
const response = await this.ExecDatabase(data)
this.personnelOptions = response.data || []
} catch (error) {
this.personnelOptions = []
}
},
handleMaterialChange(value) {
const selected = this.materialOptions.find(item => item.物料编码 === value)
this.formData.物料名称 = selected ? selected.物料名称 : ''
},
handleParentMaterialChange(value) {
const selected = this.parentMaterialOptions.find(item => item.物料编码 === value)
this.formData.关联父件物料名称 = selected ? selected.物料名称 : ''
},
handleAssigneeChange(values) {
const selected = this.personnelOptions.filter(item => values.includes(item.人员编号))
this.formData.指派对象ID = values.join(',')
this.formData.指派对象 = selected.map(item => item.人员姓名).join(',')
},
formatMaterialLabel(item) {
return item.物料名称 ? `${item.物料编码} | ${item.物料名称}` : item.物料编码
},
formatPersonLabel(item) {
return item.账号 ? `${item.人员姓名} | ${item.账号}` : item.人员姓名
},
getResult(response) {
const data = response && response.data
if (Array.isArray(data)) return data[0] || {}
if (data && Array.isArray(data.result)) return data.result[0] || {}
return data || {}
},
toDate(value) {
if (!value) return ''
return String(value).split(' ')[0]
},
currentUserName() {
return (this.$store && this.$store.getters && this.$store.getters.name) || ''
},
getStatusType(status) {
if (status === '已完成') return 'success'
if (status === '执行中') return 'warning'
if (status === '已结束') return 'primary'
return 'info'
}
}
}
</script>
<style scoped>
.design-task-page {
padding: 12px;
}
.search-container {
line-height: 34px;
}
.show-text {
margin-right: 4px;
}
.date-separator {
margin-right: 4px;
color: #606266;
}
.danger-action {
color: #f56c6c;
}
</style>

View File

@@ -119,13 +119,13 @@
</el-table-column> </el-table-column>
<el-table-column label="操作" align="center" width="400px" fixed="right"> <el-table-column label="操作" align="center" width="400px" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button v-if="scope.row.单据状态 != '已取消'"
type="text" type="text"
size="mini" size="mini"
style="margin-right: 5px; padding:0; width:auto" style="margin-right: 5px; padding:0; width:auto"
@click="receive(scope.row)">发料 @click="receive(scope.row)">发料
</el-button> </el-button>
<el-button <el-button v-if="scope.row.单据状态 != '已取消'"
type="text" type="text"
size="mini" size="mini"
style="margin-right: 5px; padding:0; width:auto" style="margin-right: 5px; padding:0; width:auto"

View File

@@ -82,6 +82,14 @@
type="primary" type="primary"
@click="searchTable" @click="searchTable"
>查询</el-button> >查询</el-button>
<el-button
:disabled="loading || tableData.length === 0"
icon="el-icon-download"
plain
size="small"
type="success"
@click="exportToExcel"
>导出</el-button>
</div> </div>
<el-table <el-table
@@ -146,6 +154,8 @@
</template> </template>
<script> <script>
import * as XLSX from 'xlsx'
export default { export default {
name: 'ProductPassRateWorkstation', name: 'ProductPassRateWorkstation',
data() { data() {
@@ -194,6 +204,97 @@ export default {
this.loading = false this.loading = false
} }
}, },
exportToExcel() {
if (this.tableData.length === 0) {
this.$message.warning('没有数据可导出')
return
}
try {
const columns = this.getExportColumns()
const exportRows = [
columns.map(column => column.label),
...this.buildExportRows(columns)
]
const wb = XLSX.utils.book_new()
const ws = XLSX.utils.aoa_to_sheet(exportRows)
ws['!cols'] = columns.map(column => ({ wch: column.width }))
XLSX.utils.book_append_sheet(wb, ws, '产品合格率工位')
XLSX.writeFile(wb, `产品合格率工位_${this.formatDateForFileName(new Date())}.xlsx`)
this.$message.success('导出成功')
} catch (error) {
console.error('产品合格率导出失败:', error)
this.$message.error('导出失败')
}
},
getExportColumns() {
return [
{ label: '层级', prop: '层级', width: 10 },
{ label: '关闭日期', prop: '关闭日期', width: 12 },
{ label: '生产订单号', prop: '生产订单号', width: 14 },
{ label: '物料名称', prop: '物料名称', width: 32 },
{ label: '物料编码', prop: '物料编码', width: 24 },
{ label: '计划数量', prop: '计划数量', width: 12 },
{ label: '完成数量', prop: '完成数量', width: 12 },
{ label: '不良数量', prop: '不良数量', width: 12 },
{ label: '合格率', prop: '合格率', width: 12 },
{ label: '工序', prop: '工序', width: 16 },
{ label: '工序号', prop: '工序号', width: 10 },
{ label: '工位(指派对象)', prop: '工位', width: 18 },
{ label: '明细完工数量', prop: '明细完成数量', width: 14 },
{ label: '明细不良数量', prop: '明细不良数量', width: 14 },
{ label: '明细合格率', prop: '明细合格率', width: 12 },
{ label: '检验说明', prop: '检测说明', width: 32 }
]
},
buildExportRows(columns) {
const rows = []
this.tableData.forEach(row => {
rows.push(this.formatExportRow(this.buildMainExportRow(row), columns))
if (Array.isArray(row.children)) {
row.children.forEach(child => {
rows.push(this.formatExportRow(this.buildDetailExportRow(row, child), columns))
})
}
})
return rows
},
buildMainExportRow(row) {
return {
层级: '主表',
关闭日期: this.formatDate(row.关闭日期),
生产订单号: row.生产订单号,
物料名称: row.物料名称,
物料编码: row.物料编码,
计划数量: row.计划数量,
完成数量: row.完成数量,
不良数量: row.不良数量,
合格率: this.formatRate(row.合格率)
}
},
buildDetailExportRow(row, child) {
return {
层级: '明细',
关闭日期: this.formatDate(row.关闭日期),
生产订单号: row.生产订单号,
物料名称: row.物料名称,
物料编码: row.物料编码,
工序: child.工序,
工序号: child.工序号,
工位: child.工位,
明细完成数量: child.完成数量,
明细不良数量: child.不良数量,
明细合格率: this.formatRate(child.合格率),
检测说明: child.检测说明
}
},
formatExportRow(row, columns) {
return columns.map(column => this.normalizeExportValue(row[column.prop]))
},
normalizeExportValue(value) {
if (value === null || value === undefined) return ''
return value
},
parseDetails(value) { parseDetails(value) {
if (!value) return [] if (!value) return []
try { try {
@@ -218,6 +319,10 @@ export default {
const day = String(date.getDate()).padStart(2, '0') const day = String(date.getDate()).padStart(2, '0')
return `${year}-${month}-${day}` return `${year}-${month}-${day}`
}, },
formatDateForFileName(date) {
const pad = value => String(value).padStart(2, '0')
return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}_${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`
},
formatDate(value) { formatDate(value) {
if (!value) return '' if (!value) return ''
return String(value).split('T')[0].split(' ')[0] return String(value).split('T')[0].split(' ')[0]

View File

@@ -17,7 +17,8 @@
placeholder="选择开始日期" placeholder="选择开始日期"
format="yyyy-MM-dd" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
style="width: 150px; margin-right: 10px" /> style="width: 150px; margin-right: 10px"
/>
<span class="show-text">结束日期:</span> <span class="show-text">结束日期:</span>
<el-date-picker <el-date-picker
v-model="searchForm.endDate" v-model="searchForm.endDate"
@@ -25,9 +26,11 @@
placeholder="选择结束日期" placeholder="选择结束日期"
format="yyyy-MM-dd" format="yyyy-MM-dd"
value-format="yyyy-MM-dd" value-format="yyyy-MM-dd"
style="width: 150px; margin-right: 10px" /> style="width: 150px; margin-right: 10px"
/>
<el-button :loading="loading" icon="el-icon-search" plain type="primary" @click="handleSearch">查询</el-button> <el-button :loading="loading" icon="el-icon-search" plain type="primary" @click="handleSearch">查询</el-button>
<el-button :disabled="loading || tableData.length === 0" icon="el-icon-download" plain type="success" @click="exportToExcel">导出</el-button>
</div> </div>
<el-table <el-table
@@ -41,7 +44,9 @@
default-expand-all default-expand-all
class="custom-tree-table" class="custom-tree-table"
:row-class-name="tableRowClassName" :row-class-name="tableRowClassName"
style="width: 100%"> style="width: 100%"
@expand-change="handleExpandChange"
>
<el-table-column prop="taskDescription" label="任务描述" min-width="380" show-overflow-tooltip> <el-table-column prop="taskDescription" label="任务描述" min-width="380" show-overflow-tooltip>
<template slot-scope="scope"> <template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level === 1 }">{{ scope.row.taskDescription || '' }}</span> <span :class="{ 'bold-text': scope.row.level === 1 }">{{ scope.row.taskDescription || '' }}</span>
@@ -66,7 +71,7 @@
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="auxiliaryWorkHours" label="辅工时" width="100" align="center"> <el-table-column prop="auxiliaryWorkHours" label="辅工时" width="100" align="center">
<template slot-scope="scope"> <template slot-scope="scope">
<span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.auxiliaryWorkHours || '' }}</span> <span :class="{ 'bold-text': scope.row.level <= 2 }">{{ scope.row.auxiliaryWorkHours || '' }}</span>
</template> </template>
@@ -129,6 +134,8 @@
</template> </template>
<script> <script>
import * as XLSX from 'xlsx'
export default { export default {
name: 'SettlementWorkhours', name: 'SettlementWorkhours',
data() { data() {
@@ -144,7 +151,8 @@ export default {
}, },
loading: false, loading: false,
tableHeight: '68vh', tableHeight: '68vh',
tableData: [] tableData: [],
collapsedRowIds: []
} }
}, },
computed: { computed: {
@@ -175,6 +183,73 @@ export default {
handleSearch() { handleSearch() {
this.loadData() this.loadData()
}, },
exportToExcel() {
if (this.tableData.length === 0) {
this.$message.warning('没有数据可导出')
return
}
try {
const columns = this.getExportColumns()
const exportRows = [
columns.map(column => column.label),
...this.buildExportRows(columns),
[],
[`报工工时:${this.totals.reportWorkHours} 小时 | 主辅工时:${this.totals.auxiliaryWorkHours} 小时 | 合计工时:${this.totals.totalWorkHours} 小时`]
]
const wb = XLSX.utils.book_new()
const ws = XLSX.utils.aoa_to_sheet(exportRows)
ws['!cols'] = columns.map(column => ({ wch: column.width }))
XLSX.utils.book_append_sheet(wb, ws, '结算工时')
XLSX.writeFile(wb, `结算工时_${this.formatDateForFileName(new Date())}.xlsx`)
this.$message.success('导出成功')
} catch (error) {
console.error('导出失败:', error)
this.$message.error('导出失败')
}
},
getExportColumns() {
return [
{ label: '任务描述', prop: 'taskDescription', width: 52 },
{ label: '生产订单号', prop: 'productionOrderNo', width: 14 },
{ label: '工位', prop: 'station', width: 12 },
{ label: '报工工时', prop: 'reportWorkHours', width: 12 },
{ label: '辅助工时', prop: 'auxiliaryWorkHours', width: 12 },
{ label: '报工完成数', prop: 'reportFinishQty', width: 12 },
{ label: '辅助完成数', prop: 'auxiliaryFinishQty', width: 12 },
{ label: '合计工时', prop: 'totalWorkHours', width: 12 },
{ label: '装夹时间', prop: 'clampingTime', width: 12 },
{ label: '程序时间', prop: 'programTime', width: 12 },
{ label: '结算报工单件工时', prop: 'settlementReportPieceHours', width: 18 },
{ label: '结算辅助单件工时', prop: 'settlementAuxiliaryPieceHours', width: 18 },
{ label: '操作人', prop: 'operatorNames', width: 24 }
]
},
buildExportRows(columns) {
const rows = []
this.tableData.forEach(row => {
rows.push(this.formatExportRow(row, columns))
if (Array.isArray(row.children) && this.isRowExpanded(row)) {
row.children.forEach(child => {
rows.push(this.formatExportRow(child, columns))
})
}
})
return rows
},
formatExportRow(row, columns) {
return columns.map(column => {
if (column.prop === 'taskDescription') {
const indent = row.level === 2 ? ' ' : ''
return `${indent}${row.taskDescription || ''}`
}
return row[column.prop] || ''
})
},
formatDateForFileName(date) {
const pad = value => String(value).padStart(2, '0')
return `${date.getFullYear()}${pad(date.getMonth() + 1)}${pad(date.getDate())}_${pad(date.getHours())}${pad(date.getMinutes())}${pad(date.getSeconds())}`
},
loadData() { loadData() {
this.loading = true this.loading = true
const param = [ const param = [
@@ -188,6 +263,7 @@ export default {
] ]
const Data = this.CreateData('11', '生产管理_结算工时_查询', param) const Data = this.CreateData('11', '生产管理_结算工时_查询', param)
this.ExecDatabase(Data).then(res => { this.ExecDatabase(Data).then(res => {
this.collapsedRowIds = []
this.tableData = this.buildTree(res.data || []) this.tableData = this.buildTree(res.data || [])
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
@@ -250,6 +326,22 @@ export default {
tableRowClassName({ row }) { tableRowClassName({ row }) {
if (row.level === 1) return 'material-row' if (row.level === 1) return 'material-row'
return '' return ''
},
handleExpandChange(row, expanded) {
if (row.level !== 1) return
const isExpanded = Array.isArray(expanded)
? expanded.some(item => item.id === row.id)
: expanded
if (isExpanded) {
this.collapsedRowIds = this.collapsedRowIds.filter(id => id !== row.id)
return
}
if (!this.collapsedRowIds.includes(row.id)) {
this.collapsedRowIds.push(row.id)
}
},
isRowExpanded(row) {
return !this.collapsedRowIds.includes(row.id)
} }
} }
} }

View File

@@ -833,7 +833,6 @@ export default {
"QueryPath": "$crossjoin(PurchaseOrders,PurchaseOrders/DocumentLines)", "QueryPath": "$crossjoin(PurchaseOrders,PurchaseOrders/DocumentLines)",
"QueryOption": "$expand=PurchaseOrders($select=DocEntry, DocNum,CardCode,CardName),PurchaseOrders/DocumentLines($select=ItemCode,LineNum,Price,U_WWOworID,U_WWOrstHS,LineStatus)&$filter=PurchaseOrders/DocEntry eq PurchaseOrders/DocumentLines/DocEntry and PurchaseOrders/DocumentLines/U_WWOworID eq "+this.receiveCheckData.计划号+"" "QueryOption": "$expand=PurchaseOrders($select=DocEntry, DocNum,CardCode,CardName),PurchaseOrders/DocumentLines($select=ItemCode,LineNum,Price,U_WWOworID,U_WWOrstHS,LineStatus)&$filter=PurchaseOrders/DocEntry eq PurchaseOrders/DocumentLines/DocEntry and PurchaseOrders/DocumentLines/U_WWOworID eq "+this.receiveCheckData.计划号+""
}) })
if (result.success) { if (result.success) {
if(result.data.value.length>0){ if(result.data.value.length>0){
let processed = false; let processed = false;
@@ -842,7 +841,7 @@ export default {
console.log(this.receiveCheckData.工序名称) console.log(this.receiveCheckData.工序名称)
console.log(element['PurchaseOrders/DocumentLines'].U_WWOrstHS) console.log(element['PurchaseOrders/DocumentLines'].U_WWOrstHS)
console.log(element['PurchaseOrders/DocumentLines'].LineStatus) console.log(element['PurchaseOrders/DocumentLines'].LineStatus)
console.log(this.receiveCheckData.工序名称 == element['PurchaseOrders/DocumentLines'].U_WWOrstHS & element['PurchaseOrders/DocumentLines'].LineStatus == 'O') // console.log(this.receiveCheckData.合格数 <= element['PurchaseOrders/DocumentLines'].RemainingOpenQuantity)
if( this.receiveCheckData.工序名称 == element['PurchaseOrders/DocumentLines'].U_WWOrstHS && element['PurchaseOrders/DocumentLines'].LineStatus == 'O'){ if( this.receiveCheckData.工序名称 == element['PurchaseOrders/DocumentLines'].U_WWOrstHS && element['PurchaseOrders/DocumentLines'].LineStatus == 'O'){
var CardCode = element.PurchaseOrders.CardCode var CardCode = element.PurchaseOrders.CardCode
@@ -927,6 +926,7 @@ export default {
this.$message.error("收检操作失败: " + (error.message || '未知错误')); this.$message.error("收检操作失败: " + (error.message || '未知错误'));
} finally { } finally {
// 无论成功或失败,都要重置提交状态 // 无论成功或失败,都要重置提交状态
console.log(111)
this.submitLoading = false; this.submitLoading = false;
} }
}, },

View File

@@ -108,6 +108,7 @@
- 创建人。 - 创建人。
- 最后编辑人。 - 最后编辑人。
- 最后编辑时间。 - 最后编辑时间。
- 备注。
### 2. `MES_设计报工_记录` ### 2. `MES_设计报工_记录`
@@ -152,3 +153,49 @@
- 不上传 SAP。 - 不上传 SAP。
- 不参与现有生产工时报表。 - 不参与现有生产工时报表。
- 不影响装配中心、机加工、自制件排产、生产订单关闭逻辑。 - 不影响装配中心、机加工、自制件排产、生产订单关闭逻辑。
- 本阶段不分配菜单权限,不新增菜单权限脚本,不写入菜单表和角色权限表。
## 五、文档归档
- 确认版 Word 文档已复制到本目录:`work/ProductionManagement/DesignReportTask/设计报工任务模块.docx`
- 后续开发以本目录 README、01-06 文档和复制后的 Word 文档作为同一套需求依据。
## 六、本轮已实现功能
### 1. 数据库
已新增脚本:`db_backups/create_design_report_task_module_20260630.sql`
已发布独立数据表:
- `dbo.MES_设计报工_任务`
- `dbo.MES_设计报工_记录`
- `dbo.MES_设计报工_校验记录`
已发布独立过程:
- `dbo.设计报工_物料查询`
- `dbo.设计报工_人员查询`
- `dbo.设计报工_项目查询`
- `dbo.设计报工_任务_查询`
- `dbo.设计报工_任务_新增`
- `dbo.设计报工_任务_编辑`
- `dbo.设计报工_任务_删除`
- `dbo.设计报工_任务_开始`
- `dbo.设计报工_任务_结束`
- `dbo.设计报工_任务_完成`
- `dbo.设计报工_记录_查询`
- `dbo.设计报工_工时校验_查询`
- `dbo.设计报工_工时校验_保存`
- `dbo.设计报工_工时校验_批量保存`
- `dbo.设计报工_工时报表_作业者工时_查询`
### 2. 前端页面
已新增页面:
- `src/views/ProductionManagement/DesignReportTask/Task/index.vue`:设计任务。
- `src/views/ProductionManagement/DesignReportTask/Report/index.vue`:设计报工。
- `src/views/ProductionManagement/DesignReportTask/Check/index.vue`:设计工时校验。
- `src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`:设计工时报表。
### 3. 菜单权限
本轮未分配菜单权限,未新增菜单脚本,未写入菜单表和角色权限表。

View File

@@ -2,39 +2,42 @@
## 一、数据库开发 ## 一、数据库开发
1. 新建独立数据表: 1. 新建独立数据表:
- `MES_设计报工_任务` - `MES_设计报工_任务`
- `MES_设计报工_记录` - `MES_设计报工_记录`
- 可选 `MES_设计报工_校验记录` - `MES_设计报工_校验记录`
2. 新建设计任务增删改查存储过程: 2. 新建设计任务增删改查存储过程:
- `设计报工_任务_查询` - `设计报工_任务_查询`
- `设计报工_任务_新增` - `设计报工_任务_新增`
- `设计报工_任务_编辑` - `设计报工_任务_编辑`
- `设计报工_任务_删除` - `设计报工_任务_删除`
3. 删除过程增加约束: 3. 已在删除过程增加约束:
- 存在 `MES_设计报工_记录` 时禁止删除。 - 存在 `MES_设计报工_记录` 时禁止删除。
4. 新建设计报工过程: 4. 新建设计报工过程:
- `设计报工_任务_开始` - `设计报工_任务_开始`
- `设计报工_任务_结束` - `设计报工_任务_结束`
- `设计报工_任务_完成` - `设计报工_任务_完成`
5. 完成过程增加约束: 5. 已在完成过程增加约束:
- 必须存在结束时间。 - 必须存在结束时间。
- 未结束不能完成。 - 未结束不能完成。
6. 新建设计工时校验过程: 6. 新建设计工时校验过程:
- `设计报工_工时校验_查询` - `设计报工_工时校验_查询`
- `设计报工_工时校验_保存` - `设计报工_工时校验_保存`
- `设计报工_工时校验_批量保存` - `设计报工_工时校验_批量保存`
7. 新建设计工时报表过程: 7. 新建设计工时报表过程:
- `设计报工_工时报表_作业者工时_查询` - `设计报工_工时报表_作业者工时_查询`
- 可按后续页面需要增加导出过程 8. 已新增辅助下拉过程
- `设计报工_物料查询`
- `设计报工_人员查询`
- `设计报工_项目查询`
## 二、前端开发 ## 二、前端开发
1. 新建设计任务页面。 1. 新建设计任务页面`src/views/ProductionManagement/DesignReportTask/Task/index.vue`
2. 新建设计报工页面。 2. 新建设计报工页面`src/views/ProductionManagement/DesignReportTask/Report/index.vue`
3. 新建设计工时校验页面。 3. 新建设计工时校验页面`src/views/ProductionManagement/DesignReportTask/Check/index.vue`
4. 新建设计工时报表页面。 4. 新建设计工时报表页面`src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`
5. 按系统菜单权限新增菜单记录 5. 本阶段不分配菜单权限,不新增菜单权限脚本,不写入菜单表和角色权限表
6. 物料编码、关联父件物料编码下拉查询参考 `ProcessManagement/PartDrawlook/index.vue` 6. 物料编码、关联父件物料编码下拉查询参考 `ProcessManagement/PartDrawlook/index.vue`
7. 指派对象多人员选择参考 `PlanManagement/SelfMakePlando/index.vue` 的二次派工。 7. 指派对象多人员选择参考 `PlanManagement/SelfMakePlando/index.vue` 的二次派工。
8. 工时校验布局参考 `ProductionManagement/WorkHoursCheck/index.vue`,但移除 SAP 上传相关逻辑。 8. 工时校验布局参考 `ProductionManagement/WorkHoursCheck/index.vue`,但移除 SAP 上传相关逻辑。
@@ -42,14 +45,16 @@
## 三、验证步骤 ## 三、验证步骤
1. 新建一条设计任务,确认 DID 和创建日期自动生成。 1. 已在事务内新建一条设计任务,确认 DID 和创建日期自动生成。
2. 编辑设计任务,确认 DID 和创建日期不可修改。 2. 编辑设计任务,确认 DID 和创建日期不可修改。
3. 未报工任务可删除。 3. 未报工任务可删除。
4. 已存在报工记录任务不可删除。 4. 已存在报工记录任务不可删除。
5. 点击开始后生成报工记录。 5. 已验证点击开始后生成报工记录。
6. 未结束时点击完成,应提示不能完成。 6. 已验证未结束时点击完成,返回“任务存在未结束报工,不能完成
7. 点击结束后生成结束时间和工时秒数。 7. 已验证点击结束后生成结束时间和工时秒数。
8. 已结束后点击完成,任务变为已完成。 8.验证已结束后点击完成,任务变为已完成。
9. 已完成任务不能再次开始或结束。 9. 已完成任务不能再次开始或结束。
10. 校验页面只更新设计报工数据,不触发 SAP 上传。 10. 校验页面只更新设计报工数据,不触发 SAP 上传。
11. 报表页面只展示设计报工工时,不混入现有生产报工数据。 11. 报表页面只展示设计报工工时,不混入现有生产报工数据。
12. 已确认本阶段未新增菜单权限脚本,未写入菜单表和角色权限表。
13. 已执行 `npm run build`,构建通过。

View File

@@ -34,3 +34,69 @@
### 下一步 ### 下一步
- 等待项目号 SAP 视图字段。 - 等待项目号 SAP 视图字段。
- 开始数据库脚本和页面开发。 - 开始数据库脚本和页面开发。
## 2026-06-30 文档归档和菜单权限口径补充
### 做了什么
- 将确认版 `doc/设计报工任务模块.docx` 复制到 `work/ProductionManagement/DesignReportTask/设计报工任务模块.docx`
- 按用户要求补充“不分配菜单权限”的口径。
- 更新 README、01-06 文档和总执行日志。
### 改了哪些文件
- `work/ProductionManagement/DesignReportTask/设计报工任务模块.docx`
- `work/ProductionManagement/DesignReportTask/README.md`
- `work/ProductionManagement/DesignReportTask/01-项目功能内容.md`
- `work/ProductionManagement/DesignReportTask/02-项目程序开发详细步骤.md`
- `work/ProductionManagement/DesignReportTask/03-推进台账.md`
- `work/ProductionManagement/DesignReportTask/04-任务矩阵.md`
- `work/ProductionManagement/DesignReportTask/05-验收证据.md`
- `work/ProductionManagement/DesignReportTask/06-决策记录.md`
- `gptlog-process/gpdlog.md`
- `C:\gptlog-process\gpdlog.md`
### 验证了什么
- 确认本目录存在复制后的 `设计报工任务模块.docx`
- 确认 README 和开发步骤中已写明本阶段不分配菜单权限。
### 下一步
- 等待项目号 SAP 视图字段后,再进入数据库和页面开发。
## 2026-06-30 新建设计报工模块表、过程和页面
### 做了什么
- 新增设计报工模块独立数据库脚本。
- 发布 3 张独立表和 15 个独立存储过程。
- 新增 4 个前端页面:
- 设计任务。
- 设计报工。
- 设计工时校验。
- 设计工时报表。
- 按要求未处理菜单权限,不新增菜单脚本。
### 改了哪些文件
- `db_backups/create_design_report_task_module_20260630.sql`
- `src/views/ProductionManagement/DesignReportTask/Task/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Report/index.vue`
- `src/views/ProductionManagement/DesignReportTask/Check/index.vue`
- `src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`
- `work/ProductionManagement/DesignReportTask/README.md`
- `work/ProductionManagement/DesignReportTask/01-项目功能内容.md`
- `work/ProductionManagement/DesignReportTask/02-项目程序开发详细步骤.md`
- `work/ProductionManagement/DesignReportTask/03-推进台账.md`
- `work/ProductionManagement/DesignReportTask/04-任务矩阵.md`
- `work/ProductionManagement/DesignReportTask/05-验收证据.md`
- `work/ProductionManagement/DesignReportTask/06-决策记录.md`
- `gptlog-process/gpdlog.md`
- `C:\gptlog-process\gpdlog.md`
### 验证了什么
- SQL 脚本发布成功。
- 表存在:`MES_设计报工_任务``MES_设计报工_记录``MES_设计报工_校验记录`
- 过程存在且修改时间为 `2026-06-30 18:01:39``2026-06-30 18:01:40`
- 物料查询和人员查询可返回数据。
- 事务内验证:未结束不能完成、开始后未结束不能完成、结束后可完成。
- `npm run build` 通过,仅有项目既有体积和 browserslist warning。
### 下一步
- 等待项目号 SAP 视图字段来源。
- 如后续需要访问页面,再单独做菜单权限分配;本轮不处理菜单权限。

View File

@@ -11,4 +11,13 @@
| DRT-007 | 确认删除规则 | 已完成 | 有报工记录不能删除 | | DRT-007 | 确认删除规则 | 已完成 | 有报工记录不能删除 |
| DRT-008 | 确认独立性 | 已完成 | 不参与现有任何生产/SAP/工时报表流程 | | DRT-008 | 确认独立性 | 已完成 | 不参与现有任何生产/SAP/工时报表流程 |
| DRT-009 | 确认项目号来源 | 待确认 | 业务提供 SAP 视图和字段 | | DRT-009 | 确认项目号来源 | 待确认 | 业务提供 SAP 视图和字段 |
| DRT-010 | 数据库和页面开发 | 待开始 | 表、过程、页面、菜单发布并验证 | | DRT-010 | 数据库和页面开发 | 已完成 | 表、过程、页面发布并验证,不分配菜单权限 |
| DRT-011 | 复制确认版 Word 文档到工作目录 | 已完成 | `work/ProductionManagement/DesignReportTask/设计报工任务模块.docx` 存在 |
| DRT-012 | 补充菜单权限口径 | 已完成 | README、开发步骤、决策记录明确本阶段不分配菜单权限 |
| DRT-013 | 发布独立数据表 | 已完成 | 3 张 `MES_设计报工_*` 表存在 |
| DRT-014 | 发布独立存储过程 | 已完成 | 15 个 `设计报工_*` 过程存在 |
| DRT-015 | 新增设计任务页面 | 已完成 | 页面文件 `Task/index.vue` 存在并构建通过 |
| DRT-016 | 新增设计报工页面 | 已完成 | 页面文件 `Report/index.vue` 存在并构建通过 |
| DRT-017 | 新增设计工时校验页面 | 已完成 | 页面文件 `Check/index.vue` 存在并构建通过 |
| DRT-018 | 新增设计工时报表页面 | 已完成 | 页面文件 `HoursReport/index.vue` 存在并构建通过 |
| DRT-019 | 验证完成/删除业务规则 | 已完成 | 未结束不能完成,已有报工记录不能删除由后端约束 |

View File

@@ -7,6 +7,11 @@
doc/设计报工任务模块.docx doc/设计报工任务模块.docx
``` ```
工作目录归档:
```text
work/ProductionManagement/DesignReportTask/设计报工任务模块.docx
```
读取结果摘要: 读取结果摘要:
```text ```text
新增设计任务页面。 新增设计任务页面。
@@ -36,6 +41,72 @@ src/views/ProductionManagement/Workhours/index.vue
## 验收结论 ## 验收结论
当前为方案文档阶段,尚未开发代码和数据库脚本 设计报工模块的独立数据表、独立过程和 4 个前端页面已新增
方案可进入开发,但需要先补齐项目号 SAP 视图字段来源。 项目号 SAP 视图字段来源仍待业务提供;当前项目号下拉临时从已存在设计任务项目号中取值,并允许前端手工录入。
## 菜单权限口径
```text
本阶段不分配菜单权限。
不新增菜单权限脚本。
不写入菜单表和角色权限表。
```
## 数据库发布
执行命令:
```powershell
sqlcmd -S 192.168.2.92 -U sa -P ****** -d YL_MESDB -C -l 30 -b -f 65001 -i .\db_backups\create_design_report_task_module_20260630.sql
```
发布结果:
```text
执行成功。
```
对象验证:
```text
MES_设计报工_任务
MES_设计报工_记录
MES_设计报工_校验记录
设计报工_物料查询
设计报工_人员查询
设计报工_项目查询
设计报工_任务_查询
设计报工_任务_新增
设计报工_任务_编辑
设计报工_任务_删除
设计报工_任务_开始
设计报工_任务_结束
设计报工_任务_完成
设计报工_记录_查询
设计报工_工时校验_查询
设计报工_工时校验_保存
设计报工_工时校验_批量保存
设计报工_工时报表_作业者工时_查询
```
业务规则事务验证:
```text
新增测试任务:成功。
未开始直接完成:返回“任务未产生已结束报工,不能完成”。
开始任务:成功。
开始后未结束直接完成:返回“任务存在未结束报工,不能完成”。
结束任务:成功。
结束后完成:成功。
事务回滚:测试数据未保留。
```
## 前端构建
执行命令:
```powershell
npm run build
```
结果:
```text
构建通过。
仅有项目既有 asset size、entrypoint size、browserslist warning。
```

View File

@@ -52,3 +52,34 @@
- 前端使用多选人员下拉。 - 前端使用多选人员下拉。
- 数据库建议同时保存人员ID列表和人员名称列表。 - 数据库建议同时保存人员ID列表和人员名称列表。
- 如果后续业务确认只允许单人,可收窄为单选,不影响表结构扩展。 - 如果后续业务确认只允许单人,可收窄为单选,不影响表结构扩展。
## DDR-006 本阶段不分配菜单权限
决策:本阶段不分配菜单权限,不新增菜单权限脚本,不写入菜单表和角色权限表。
原因:用户明确要求“不分配菜单权限”。
影响:
- 后续开发只准备页面、表和过程。
- 菜单挂载和角色权限分配暂不纳入本轮验收。
- 如果后续需要开放页面访问,再单独按权限方案处理。
## DDR-007 项目号来源未确认时的临时实现
决策:项目号下拉暂时查询 `MES_设计报工_任务` 中已存在项目号,并允许前端手工输入。
原因:用户确认项目号具体 SAP 视图字段后续提供,但本轮需要先落地页面、数据表和功能。
影响:
- 后续拿到 SAP 视图字段后,只需要调整 `设计报工_项目查询` 存储过程。
- 前端控件和任务表字段无需重做。
## DDR-008 前端页面独立放在 DesignReportTask 目录
决策4 个页面统一放在 `src/views/ProductionManagement/DesignReportTask/` 下。
原因:该模块是生产管理下的独立设计报工体系,目录集中后便于后续菜单挂载和维护。
影响:
- 菜单权限暂不分配。
- 后续如需开放菜单,可直接指向对应 `Task``Report``Check``HoursReport` 组件路径。

View File

@@ -8,10 +8,21 @@
- `04-任务矩阵.md`:记录任务编号、状态和验收标准。 - `04-任务矩阵.md`:记录任务编号、状态和验收标准。
- `05-验收证据.md`:记录文档读取、方案确认和后续开发验证证据。 - `05-验收证据.md`:记录文档读取、方案确认和后续开发验证证据。
- `06-决策记录.md`:记录已确认的关键设计决策。 - `06-决策记录.md`:记录已确认的关键设计决策。
- `设计报工任务模块.docx`:从 `doc/设计报工任务模块.docx` 复制过来的确认版需求文档。
## 当前状态 ## 当前状态
- 来源文档:`doc/设计报工任务模块.docx` - 来源文档:`doc/设计报工任务模块.docx`
- 当前阶段:方案梳理与文档修订。 - 当前阶段:方案梳理与文档修订。
- 核心原则设计报工任务、设计报工记录、设计工时校验、设计工时报表全部独立不参与现有生产报工、SAP 上传、生产工时校验和既有工时报表。 - 核心原则设计报工任务、设计报工记录、设计工时校验、设计工时报表全部独立不参与现有生产报工、SAP 上传、生产工时校验和既有工时报表。
- 菜单权限:本阶段不分配菜单权限,不写入菜单表和角色权限表。
- 待确认项:`项目号` 的 SAP 视图和字段来源由业务后续提供。 - 待确认项:`项目号` 的 SAP 视图和字段来源由业务后续提供。
## 已落地内容
- 数据库脚本:`db_backups/create_design_report_task_module_20260630.sql`
- 设计任务页面:`src/views/ProductionManagement/DesignReportTask/Task/index.vue`
- 设计报工页面:`src/views/ProductionManagement/DesignReportTask/Report/index.vue`
- 设计工时校验页面:`src/views/ProductionManagement/DesignReportTask/Check/index.vue`
- 设计工时报表页面:`src/views/ProductionManagement/DesignReportTask/HoursReport/index.vue`
- 数据表:`MES_设计报工_任务``MES_设计报工_记录``MES_设计报工_校验记录`