diff --git a/二期需求/dbo.sql b/二期需求/dbo.sql index b2965d9..6dbdbfb 100644 --- a/二期需求/dbo.sql +++ b/二期需求/dbo.sql @@ -34,6 +34,31 @@ BEGIN TRY EXEC @LockResult=sys.sp_getapplock @Resource=N'YD_Event_Phase2_Production_Deployment',@LockMode='Exclusive',@LockOwner='Transaction',@LockTimeout=10000; IF @LockResult<0 THROW 51002,N'无法取得二期部署排他锁,可能有另一个部署正在执行。',1; + /* 在任何 DDL 前阻断不兼容版本或错误基线。 */ + DECLARE @ProductMajorVersion INT=CONVERT(INT,SERVERPROPERTY('ProductMajorVersion')); + DECLARE @ProductBuild INT=TRY_CONVERT(INT,PARSENAME(CONVERT(NVARCHAR(128),SERVERPROPERTY('ProductVersion')),2)); + DECLARE @CompatibilityLevel INT=(SELECT compatibility_level FROM sys.databases WHERE name=DB_NAME()); + IF @ProductMajorVersion<13 OR (@ProductMajorVersion=13 AND ISNULL(@ProductBuild,0)<4001) + THROW 51000,N'二期脚本要求 SQL Server 2016 SP1 或更高版本。',1; + IF @CompatibilityLevel<130 THROW 51000,N'二期脚本要求数据库兼容级别不低于 130。',1; + IF EXISTS( + SELECT 1 FROM (VALUES + (N'AppUser'),(N'EventInfo'),(N'EventRegistrationLimit'),(N'EventRegistration'),(N'EventRegistrationItem'), + (N'Team'),(N'EventProject'),(N'Project'),(N'SysUser'),(N'EventResult'),(N'SysRole'),(N'SysMenu'),(N'SysRoleMenu')) required(Name) + WHERE OBJECT_ID(N'dbo.'+QUOTENAME(required.Name),N'U') IS NULL + ) THROW 51001,N'目标库缺少二期升级所需的一期基础表,禁止继续。',1; + IF EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code<>N'scoringunit') + THROW 51005,N'SysRole.Id=1003 已被其他角色占用。',1; + IF EXISTS( + SELECT 1 + FROM (VALUES + (1080,N'system:unit'),(1081,N'system:unit:add'),(1082,N'system:unit:edit'),(1083,N'system:unit:delete'), + (1084,N'system:unit:status'),(1085,N'system:unit:resetpwd'),(1086,N'scoring'),(1087,N'scoring:launcher'), + (1088,N'scoring:screen'),(1089,N'scoring:workbench'),(2010,N'referee')) expected(Id,Code) + JOIN dbo.SysMenu menu ON menu.Id=expected.Id + WHERE ISNULL(menu.Code,N'')<>expected.Code + ) THROW 51006,N'二期菜单固定 Id 已被其他业务占用。',1; + /* EventScoreCorrection:同时支持后台账号与裁判账号发起修正。 */ IF OBJECT_ID(N'dbo.EventScoreCorrection','U') IS NOT NULL AND COL_LENGTH(N'dbo.EventScoreCorrection', N'ApplyRefereeId') IS NULL ALTER TABLE dbo.EventScoreCorrection ADD ApplyRefereeId BIGINT NULL; @@ -67,9 +92,9 @@ BEGIN TRY [Status] INT NOT NULL CONSTRAINT [DF_RefereeApplication_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_RefereeApplication_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -99,9 +124,9 @@ BEGIN TRY [Status] INT NOT NULL CONSTRAINT [DF_CheckinTask_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_CheckinTask_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -118,12 +143,12 @@ BEGIN TRY [RegistrationPersonId] BIGINT NULL, -- 关联的报名人员Id;秩序册导入记录无报名人员时为空 [CheckerUserId] BIGINT NOT NULL, -- 执行检录的检录员用户Id [Checked] BIT NOT NULL CONSTRAINT [DF_CheckinRecord_Checked] DEFAULT (0), -- 是否已检录(取消检录置为0) - [CheckedTime] DATETIME2(3) NULL, -- 检录时间(取消检录时置空) + [CheckedTime] DATETIME2(7) NULL, -- 检录时间(取消检录时置空) [DeleteMark] BIT NOT NULL CONSTRAINT [DF_CheckinRecord_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -169,9 +194,9 @@ BEGIN TRY [Status] INT NOT NULL CONSTRAINT [DF_EventReferee_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_EventReferee_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -185,7 +210,7 @@ BEGIN TRY [EventRefereeId] BIGINT NOT NULL, -- 关联赛事裁判记录Id(EventReferee.Id) [RefereeId] BIGINT NOT NULL, -- 关联裁判档案Id(兼容历史查询的冗余字段) [JudgeUserId] BIGINT NULL, -- 关联小程序用户Id(裁判未注册小程序时为空) - [JudgeRole] NVARCHAR(32) NOT NULL, -- 裁判席位编码(取自计分规则席位配置,如T、DP1、P) + [JudgeRole] VARCHAR(32) NOT NULL, -- 与测试库一致:裁判席位编码(ASCII) [JudgeRoleType] NVARCHAR(16) NULL, -- 裁判角色类别编码(如DP、DM、DR、P、T) [AssignmentStatus] INT NOT NULL CONSTRAINT [DF_EventJudgeAssignment_AssignmentStatus] DEFAULT (0), -- 分配状态:0-草稿,1-已提交,2-已替换,9-已停用 [SubmittedTime] DATETIME2(3) NULL, -- 提交时间 @@ -240,7 +265,7 @@ BEGIN TRY CREATE TABLE dbo.[EventVenue] ( [Id] BIGINT NOT NULL CONSTRAINT [PK_EventVenue] PRIMARY KEY, -- 主键Id(雪花Id) [EventId] BIGINT NOT NULL, -- 关联赛事Id - [VenueCode] NVARCHAR(32) NOT NULL, -- 场地编码(同一赛事未删除数据中唯一,如V01) + [VenueCode] VARCHAR(32) NOT NULL, -- 与测试库一致:场地编码(ASCII) [VenueName] NVARCHAR(128) NOT NULL, -- 场地名称 [Status] INT NOT NULL CONSTRAINT [DF_EventVenue_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [Sort] INT NOT NULL CONSTRAINT [DF_EventVenue_Sort] DEFAULT (0), -- 排序 @@ -262,7 +287,7 @@ BEGIN TRY [EventProjectGroupId] BIGINT NULL, -- 关联赛事项目组别Id(多组别混合时为空) [VenueId] BIGINT NOT NULL, -- 关联比赛场地Id(EventVenue.Id) [ScoreRuleId] BIGINT NOT NULL, -- 关联计分规则Id(取自项目配置) - [SessionNo] NVARCHAR(32) NOT NULL, -- 场次编号(同一赛事未删除数据中唯一) + [SessionNo] VARCHAR(32) NOT NULL, -- 与测试库一致:场次编号(ASCII) [SessionName] NVARCHAR(128) NULL, -- 场次名称 [StartTime] DATETIME2(3) NULL, -- 场次开始时间 [EndTime] DATETIME2(3) NULL, -- 场次结束时间 @@ -287,7 +312,7 @@ BEGIN TRY [ParticipationRecordId] BIGINT NULL, -- 关联赛事参赛记录Id(未匹配到参赛记录时为空) [RegistrationItemId] BIGINT NULL, -- 关联报名项目明细Id [SourceType] INT NOT NULL CONSTRAINT [DF_EventSessionEntry_SourceType] DEFAULT (0), -- 出场数据来源:0-报名平台编排,1-秩序册导入 - [EntryNo] NVARCHAR(32) NOT NULL, -- 出场编号(项目序号+场地序号+出场顺序) + [EntryNo] VARCHAR(32) NOT NULL, -- 与测试库一致:出场编号(ASCII) [PlayOrder] INT NOT NULL, -- 出场顺序(同一场次未删除数据中唯一) [EntryStatus] INT NOT NULL CONSTRAINT [DF_EventSessionEntry_EntryStatus] DEFAULT (0), -- 出场状态:0-待出场,10-已检录,20-已叫号,30-进行中,40-已完成,80-退赛,90-取消比赛资格 [CallTime] DATETIME2(3) NULL, -- 叫号时间 @@ -363,7 +388,7 @@ BEGIN TRY BEGIN CREATE TABLE dbo.[ScoreRule] ( [Id] BIGINT NOT NULL CONSTRAINT [PK_ScoreRule] PRIMARY KEY, -- 主键Id(雪花Id) - [RuleCode] NVARCHAR(64) NOT NULL, -- 规则编码(未删除数据中唯一,如ROPE_PRESCRIBED/ROPE_PRESCRIBED_SINGLE) + [RuleCode] VARCHAR(64) NOT NULL, -- 与测试库一致:规则编码(ASCII) [RuleName] NVARCHAR(128) NOT NULL, -- 规则名称 [JudgeRoleSchemaJson] NVARCHAR(2000) NOT NULL, -- 裁判席位配置(JSON,按裁判组描述所需角色席位) [RuleConfigJson] NVARCHAR(4000) NULL, -- 计分参数配置(JSON,扣分项/权重等扩展参数) @@ -372,7 +397,7 @@ BEGIN TRY [Sort] INT NOT NULL CONSTRAINT [DF_ScoreRule_Sort] DEFAULT (0), -- 排序 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_ScoreRule_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(3) NOT NULL CONSTRAINT [DF_ScoreRule_Created] DEFAULT (SYSDATETIME()), -- 创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) ); @@ -511,20 +536,20 @@ BEGIN TRY [EventResultId] BIGINT NOT NULL, -- 关联赛事成绩Id(EventResult.Id) [EventId] BIGINT NOT NULL, -- 关联赛事Id [SessionEntryId] BIGINT NOT NULL, -- 关联场次出场记录Id - [ResultVersion] INT NOT NULL, -- 成绩版本号 - [DifficultyScore] DECIMAL(18,4) NOT NULL, -- 难度分 - [PerformanceScore] DECIMAL(18,4) NOT NULL, -- 表现分 - [RequiredScore] DECIMAL(18,4) NOT NULL, -- 规定分 - [DeductionScore] DECIMAL(18,4) NOT NULL, -- 扣分 - [TotalScore] DECIMAL(18,4) NOT NULL, -- 正式总分 + [ResultVersion] INT NOT NULL CONSTRAINT [DF_EventResultVersion_Version] DEFAULT (1), -- 成绩版本号 + [DifficultyScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_DifficultyScore] DEFAULT (0), -- 难度分 + [PerformanceScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_PerformanceScore] DEFAULT (0), -- 表现分 + [RequiredScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_RequiredScore] DEFAULT (0), -- 规定分 + [DeductionScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_DeductionScore] DEFAULT (0), -- 扣分 + [TotalScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_TotalScore] DEFAULT (0), -- 正式总分 [Rank] INT NULL, -- 名次 - [IsDisqualified] BIT NOT NULL, -- 是否取消比赛资格 + [IsDisqualified] BIT NOT NULL CONSTRAINT [DF_EventResultVersion_IsDisqualified] DEFAULT (0), -- 是否取消比赛资格 [DisqualifyReasonCode] NVARCHAR(64) NULL, -- 取消比赛资格原因编码 - [ResultStatus] INT NOT NULL, -- 成绩状态:0-计算中,10-待复核,20-已确认,30-已投屏,40-已更正,90-已作废 - [SourceType] INT NOT NULL, -- 版本来源:0-正常聚合,1-成绩修正,2-重赛 + [ResultStatus] INT NOT NULL CONSTRAINT [DF_EventResultVersion_Status] DEFAULT (0), -- 成绩状态:0-计算中,10-待复核,20-已确认,30-已投屏,40-已更正,90-已作废 + [SourceType] INT NOT NULL CONSTRAINT [DF_EventResultVersion_SourceType] DEFAULT (0), -- 版本来源:0-正常聚合,1-成绩修正,2-重赛 [ScoreCorrectionId] BIGINT NULL, -- 关联成绩修正申请Id [ScoreRuleId] BIGINT NOT NULL, -- 关联计分规则Id - [RuleVersion] INT NOT NULL, -- 计分规则版本号 + [RuleVersion] INT NOT NULL CONSTRAINT [DF_EventResultVersion_RuleVersion] DEFAULT (1), -- 计分规则版本号 [CalculationJson] NVARCHAR(MAX) NULL, -- 聚合计算明细(JSON) [Remark] NVARCHAR(512) NULL, -- 版本说明 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_EventResultVersion_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 @@ -639,41 +664,43 @@ BEGIN TRY IF COL_LENGTH(N'dbo.EventRegistrationItem', N'TeamId') IS NULL ALTER TABLE dbo.EventRegistrationItem ADD TeamId BIGINT NULL; IF COL_LENGTH(N'dbo.EventRegistrationItem', N'TeamName') IS NULL ALTER TABLE dbo.EventRegistrationItem ADD TeamName NVARCHAR(64) NULL; IF COL_LENGTH(N'dbo.EventRegistrationItem', N'TeamIndex') IS NULL ALTER TABLE dbo.EventRegistrationItem ADD TeamIndex INT NULL; + /* 新增列必须通过动态 SQL 引用,避免首次上线时整批预编译报 Invalid column name。 */ + EXEC sys.sp_executesql N' ;WITH TeamCandidates AS ( SELECT item.Id AS RegistrationItemId,team.Id AS TeamId, - COUNT_BIG(1) OVER(PARTITION BY item.Id) AS CandidateCount + COUNT_BIG(1) OVER(PARTITION BY item.Id) AS CandidateCount FROM dbo.EventRegistrationItem item - INNER JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId - INNER JOIN dbo.Team team - ON LTRIM(RTRIM(team.Name))=LTRIM(RTRIM(registration.TeamName)) - AND ((registration.MerchantCertificationId IS NOT NULL AND team.MerchantCertificationId=registration.MerchantCertificationId) - OR team.CreatedUserId=registration.CreatedUserId) + JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId + JOIN dbo.Team team + ON LTRIM(RTRIM(team.Name))=LTRIM(RTRIM(registration.TeamName)) + AND ((registration.MerchantCertificationId IS NOT NULL AND team.MerchantCertificationId=registration.MerchantCertificationId) + OR team.CreatedUserId=registration.CreatedUserId) WHERE item.TeamId IS NULL AND registration.RegistrationMode=2 - AND NULLIF(LTRIM(RTRIM(registration.TeamName)),N'') IS NOT NULL + AND NULLIF(LTRIM(RTRIM(registration.TeamName)),N'''') IS NOT NULL ) UPDATE item SET TeamId=candidate.TeamId FROM dbo.EventRegistrationItem item - INNER JOIN TeamCandidates candidate ON candidate.RegistrationItemId=item.Id AND candidate.CandidateCount=1; - UPDATE item SET TeamName=LEFT(COALESCE(NULLIF(LTRIM(RTRIM(registration.TeamName)),N''),team.Name),64) + JOIN TeamCandidates candidate ON candidate.RegistrationItemId=item.Id AND candidate.CandidateCount=1; + UPDATE item SET TeamName=LEFT(COALESCE(NULLIF(LTRIM(RTRIM(registration.TeamName)),N''''),team.Name),64) FROM dbo.EventRegistrationItem item - INNER JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId + JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId LEFT JOIN dbo.Team team ON team.Id=item.TeamId WHERE item.TeamName IS NULL - AND (NULLIF(LTRIM(RTRIM(registration.TeamName)),N'') IS NOT NULL OR team.Id IS NOT NULL); + AND (NULLIF(LTRIM(RTRIM(registration.TeamName)),N'''') IS NOT NULL OR team.Id IS NOT NULL); ;WITH OrderedTeamItems AS ( SELECT item.Id,ROW_NUMBER() OVER(PARTITION BY item.RegistrationId,item.ProjectId, ISNULL(item.EventProjectGroupId,0),ISNULL(item.TeamId,0) ORDER BY item.CreatedTime,item.Id) AS RepairedTeamIndex FROM dbo.EventRegistrationItem item LEFT JOIN dbo.EventProject eventProject ON eventProject.Id=item.ProjectId LEFT JOIN dbo.Project project ON project.Id=eventProject.ProjectId - WHERE item.TeamIndex IS NULL AND (project.ProjectType IN(1005,1006) OR item.ProjectTypeName LIKE N'%团队%') + WHERE item.TeamIndex IS NULL AND (project.ProjectType IN(1005,1006) OR item.ProjectTypeName LIKE N''%团队%'') ) UPDATE item SET TeamIndex=ordered.RepairedTeamIndex - FROM dbo.EventRegistrationItem item INNER JOIN OrderedTeamItems ordered ON ordered.Id=item.Id; + FROM dbo.EventRegistrationItem item JOIN OrderedTeamItems ordered ON ordered.Id=item.Id;'; /* Project 项目:绑定计分规则 ScoreRuleId -> ScoreRule.Id */ IF COL_LENGTH('dbo.Project','ScoreRuleId') IS NULL ALTER TABLE dbo.Project ADD ScoreRuleId BIGINT NULL; -- 项目绑定的计分规则Id(ScoreRule.Id) /* SysUser 扩展为“单位账号”:UnitName 单位名称;UnitPlatform 所属平台 0-系统用户 1-报名平台 2-打分系统,默认0 */ - IF COL_LENGTH('dbo.SysUser','UnitName') IS NULL ALTER TABLE dbo.SysUser ADD UnitName NVARCHAR(128) NULL; -- 单位名称(单位账号扩展) + IF COL_LENGTH('dbo.SysUser','UnitName') IS NULL ALTER TABLE dbo.SysUser ADD UnitName VARCHAR(128) NULL; -- 与测试库一致:单位名称 IF COL_LENGTH('dbo.SysUser','UnitPlatform') IS NULL ALTER TABLE dbo.SysUser ADD UnitPlatform INT NOT NULL CONSTRAINT DF_SysUser_UnitPlatform DEFAULT(0) WITH VALUES; -- 所属平台:0-赛事系统用户,1-报名平台,2-打分系统,默认0 /* EventResult 成绩表:关联场次/出场 SessionId、SessionEntryId */ IF COL_LENGTH('dbo.EventResult','SessionId') IS NULL ALTER TABLE dbo.EventResult ADD SessionId BIGINT NULL; -- 关联比赛场次Id(EventSession.Id) @@ -701,24 +728,20 @@ BEGIN TRY ==================================================================================== */ PRINT N'[3/9] 改表结构:创建校验约束、外键与索引'; /* 3.1 CHECK 域值约束:限定枚举取值(含一期新增列 MiniProgramRole/UnitPlatform 与二期新表) */ - IF OBJECT_ID('CK_AppUser_MiniProgramRole','C') IS NULL ALTER TABLE dbo.AppUser WITH CHECK ADD CONSTRAINT CK_AppUser_MiniProgramRole CHECK(MiniProgramRole IN(1,2,3)); - IF OBJECT_ID('CK_SysUser_UnitPlatform','C') IS NULL ALTER TABLE dbo.SysUser WITH CHECK ADD CONSTRAINT CK_SysUser_UnitPlatform CHECK(UnitPlatform IN(0,1,2)); + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_AppUser_MiniProgramRole'',N''C'') IS NULL ALTER TABLE dbo.AppUser WITH CHECK ADD CONSTRAINT CK_AppUser_MiniProgramRole CHECK(MiniProgramRole IN(1,2,3));'; + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_SysUser_UnitPlatform'',N''C'') IS NULL ALTER TABLE dbo.SysUser WITH CHECK ADD CONSTRAINT CK_SysUser_UnitPlatform CHECK(UnitPlatform IN(0,1,2));'; IF OBJECT_ID('CK_CheckinTask_CheckinNo','C') IS NULL ALTER TABLE dbo.CheckinTask WITH CHECK ADD CONSTRAINT CK_CheckinTask_CheckinNo CHECK(CheckinNo BETWEEN 1 AND 3 AND TotalRounds BETWEEN 1 AND 3 AND CurrentRound BETWEEN 1 AND 3); IF OBJECT_ID('CK_EventSession_Time','C') IS NULL ALTER TABLE dbo.EventSession WITH CHECK ADD CONSTRAINT CK_EventSession_Time CHECK(EndTime IS NULL OR StartTime IS NULL OR EndTime>=StartTime); IF OBJECT_ID('CK_ScoreRule_Version','C') IS NULL ALTER TABLE dbo.ScoreRule WITH CHECK ADD CONSTRAINT CK_ScoreRule_Version CHECK(RuleVersion>=1); IF OBJECT_ID('CK_EventJudgeScoreSheet_Version','C') IS NULL ALTER TABLE dbo.EventJudgeScoreSheet WITH CHECK ADD CONSTRAINT CK_EventJudgeScoreSheet_Version CHECK(RuleVersion>=1 AND SheetVersion>=1); - IF OBJECT_ID('CK_EventScoreCorrection_Applicant','C') IS NULL ALTER TABLE dbo.EventScoreCorrection WITH CHECK ADD CONSTRAINT CK_EventScoreCorrection_Applicant CHECK((ApplyUserId IS NOT NULL AND ApplyRefereeId IS NULL) OR (ApplyUserId IS NULL AND ApplyRefereeId IS NOT NULL)); - IF OBJECT_ID(N'dbo.CK_EventRegistrationItem_TeamIndex',N'C') IS NULL ALTER TABLE dbo.EventRegistrationItem WITH CHECK ADD CONSTRAINT CK_EventRegistrationItem_TeamIndex CHECK(TeamIndex IS NULL OR TeamIndex>0); - IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem item LEFT JOIN dbo.Team team ON team.Id=item.TeamId WHERE item.TeamId IS NOT NULL AND team.Id IS NULL) THROW 51024,N'EventRegistrationItem 存在无效 TeamId,停止升级。',1; + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_EventScoreCorrection_Applicant'',N''C'') IS NULL ALTER TABLE dbo.EventScoreCorrection WITH CHECK ADD CONSTRAINT CK_EventScoreCorrection_Applicant CHECK((ApplyUserId IS NOT NULL AND ApplyRefereeId IS NULL) OR (ApplyUserId IS NULL AND ApplyRefereeId IS NOT NULL));'; + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_EventRegistrationItem_TeamIndex'',N''C'') IS NULL ALTER TABLE dbo.EventRegistrationItem WITH CHECK ADD CONSTRAINT CK_EventRegistrationItem_TeamIndex CHECK(TeamIndex IS NULL OR TeamIndex>0); IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem item LEFT JOIN dbo.Team team ON team.Id=item.TeamId WHERE item.TeamId IS NOT NULL AND team.Id IS NULL) THROW 51024,N''EventRegistrationItem 存在无效 TeamId,停止升级。'',1;'; /* 3.2 外键:二期表引用一期表主键、以及二期表之间的引用关系 */ IF OBJECT_ID(N'dbo.[FK_RefereeApplication_Event]','F') IS NULL ALTER TABLE dbo.[RefereeApplication] WITH CHECK ADD CONSTRAINT [FK_RefereeApplication_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); IF OBJECT_ID(N'dbo.[FK_RefereeApplication_AppUser]','F') IS NULL ALTER TABLE dbo.[RefereeApplication] WITH CHECK ADD CONSTRAINT [FK_RefereeApplication_AppUser] FOREIGN KEY([RefereeUserId]) REFERENCES dbo.[AppUser]([Id]); IF OBJECT_ID(N'dbo.[FK_CheckinTask_Event]','F') IS NULL ALTER TABLE dbo.[CheckinTask] WITH CHECK ADD CONSTRAINT [FK_CheckinTask_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); IF OBJECT_ID(N'dbo.[FK_CheckinRecord_Task]','F') IS NULL ALTER TABLE dbo.[CheckinRecord] WITH CHECK ADD CONSTRAINT [FK_CheckinRecord_Task] FOREIGN KEY([TaskId]) REFERENCES dbo.[CheckinTask]([Id]); - IF OBJECT_ID(N'dbo.[FK_EventRegistrationItem_Team]','F') IS NULL ALTER TABLE dbo.[EventRegistrationItem] WITH CHECK ADD CONSTRAINT [FK_EventRegistrationItem_Team] FOREIGN KEY([TeamId]) REFERENCES dbo.[Team]([Id]); - IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventRegistrationItem]') AND name=N'IX_EventRegistrationItem_RegistrationId_TeamId') CREATE NONCLUSTERED INDEX [IX_EventRegistrationItem_RegistrationId_TeamId] ON dbo.[EventRegistrationItem]([RegistrationId],[TeamId]) INCLUDE([EventProjectGroupId],[TeamIndex]) WHERE [TeamId] IS NOT NULL; - IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0 GROUP BY RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex HAVING COUNT_BIG(1)>1) THROW 51025,N'EventRegistrationItem 存在重复的来源团队队伍序号,停止创建唯一索引。',1; - IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventRegistrationItem]') AND name=N'UX_EventRegistrationItem_SourceTeamSquad_Active') CREATE UNIQUE NONCLUSTERED INDEX [UX_EventRegistrationItem_SourceTeamSquad_Active] ON dbo.[EventRegistrationItem]([RegistrationId],[ProjectId],[EventProjectGroupId],[TeamId],[TeamIndex]) WHERE [TeamId] IS NOT NULL AND [TeamIndex] IS NOT NULL AND [DeleteMark]=0; + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.FK_EventRegistrationItem_Team'',N''F'') IS NULL ALTER TABLE dbo.EventRegistrationItem WITH CHECK ADD CONSTRAINT FK_EventRegistrationItem_Team FOREIGN KEY(TeamId) REFERENCES dbo.Team(Id); IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N''dbo.EventRegistrationItem'') AND name=N''IX_EventRegistrationItem_RegistrationId_TeamId'') CREATE NONCLUSTERED INDEX IX_EventRegistrationItem_RegistrationId_TeamId ON dbo.EventRegistrationItem(RegistrationId,TeamId) INCLUDE(EventProjectGroupId,TeamIndex) WHERE TeamId IS NOT NULL; IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0 GROUP BY RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex HAVING COUNT_BIG(1)>1) THROW 51025,N''EventRegistrationItem 存在重复的来源团队队伍序号,停止创建唯一索引。'',1; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N''dbo.EventRegistrationItem'') AND name=N''UX_EventRegistrationItem_SourceTeamSquad_Active'') CREATE UNIQUE NONCLUSTERED INDEX UX_EventRegistrationItem_SourceTeamSquad_Active ON dbo.EventRegistrationItem(RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex) WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0;'; IF OBJECT_ID(N'dbo.[FK_Referee_AppUser]','F') IS NULL ALTER TABLE dbo.[Referee] WITH CHECK ADD CONSTRAINT [FK_Referee_AppUser] FOREIGN KEY([AppUserId]) REFERENCES dbo.[AppUser]([Id]); IF OBJECT_ID(N'dbo.[FK_EventReferee_Event]','F') IS NULL ALTER TABLE dbo.[EventReferee] WITH CHECK ADD CONSTRAINT [FK_EventReferee_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); IF OBJECT_ID(N'dbo.[FK_EventReferee_Referee]','F') IS NULL ALTER TABLE dbo.[EventReferee] WITH CHECK ADD CONSTRAINT [FK_EventReferee_Referee] FOREIGN KEY([RefereeId]) REFERENCES dbo.[Referee]([Id]); @@ -742,7 +765,7 @@ BEGIN TRY IF OBJECT_ID(N'dbo.[FK_EventResultVersion_Rule]','F') IS NULL ALTER TABLE dbo.[EventResultVersion] WITH CHECK ADD CONSTRAINT [FK_EventResultVersion_Rule] FOREIGN KEY([ScoreRuleId]) REFERENCES dbo.[ScoreRule]([Id]); IF OBJECT_ID(N'dbo.[FK_EventScoreCorrection_Entry]','F') IS NULL ALTER TABLE dbo.[EventScoreCorrection] WITH CHECK ADD CONSTRAINT [FK_EventScoreCorrection_Entry] FOREIGN KEY([SessionEntryId]) REFERENCES dbo.[EventSessionEntry]([Id]); IF OBJECT_ID(N'dbo.[FK_EventScoreCorrection_OriginalSheet]','F') IS NULL ALTER TABLE dbo.[EventScoreCorrection] WITH CHECK ADD CONSTRAINT [FK_EventScoreCorrection_OriginalSheet] FOREIGN KEY([OriginalScoreSheetId]) REFERENCES dbo.[EventJudgeScoreSheet]([Id]); - IF OBJECT_ID(N'dbo.[FK_EventScoreCorrection_ApplyReferee]','F') IS NULL ALTER TABLE dbo.[EventScoreCorrection] WITH CHECK ADD CONSTRAINT [FK_EventScoreCorrection_ApplyReferee] FOREIGN KEY([ApplyRefereeId]) REFERENCES dbo.[Referee]([Id]); + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.FK_EventScoreCorrection_ApplyReferee'',N''F'') IS NULL ALTER TABLE dbo.EventScoreCorrection WITH CHECK ADD CONSTRAINT FK_EventScoreCorrection_ApplyReferee FOREIGN KEY(ApplyRefereeId) REFERENCES dbo.Referee(Id);'; IF OBJECT_ID(N'dbo.[FK_EventResultScreenCast_Event]','F') IS NULL ALTER TABLE dbo.[EventResultScreenCast] WITH CHECK ADD CONSTRAINT [FK_EventResultScreenCast_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); /* 3.3 索引:UX_ 唯一索引 / IX_ 非聚集索引;WHERE DeleteMark=0 的过滤索引仅约束有效数据 */ IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[Referee]') AND name=N'UX_Referee_Mobile_Active') CREATE UNIQUE NONCLUSTERED INDEX [UX_Referee_Mobile_Active] ON dbo.[Referee]([Mobile]) WHERE [DeleteMark]=0; @@ -777,8 +800,7 @@ BEGIN TRY AND (INDEX_COL(N'dbo.EventResult',N'UX_EventResult_SessionEntry_Active',1)<>N'SessionEntryId' OR ISNULL(INDEX_COL(N'dbo.EventResult',N'UX_EventResult_SessionEntry_Active',2),N'')<>N'RegistrationPersonId')) DROP INDEX [UX_EventResult_SessionEntry_Active] ON dbo.[EventResult]; - IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResult]') AND name=N'UX_EventResult_SessionEntry_Active') - CREATE UNIQUE NONCLUSTERED INDEX [UX_EventResult_SessionEntry_Active] ON dbo.[EventResult]([SessionEntryId],[RegistrationPersonId]) WHERE [SessionEntryId] IS NOT NULL AND [DeleteMark]=0; + EXEC sys.sp_executesql N'IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N''dbo.EventResult'') AND name=N''UX_EventResult_SessionEntry_Active'') CREATE UNIQUE NONCLUSTERED INDEX UX_EventResult_SessionEntry_Active ON dbo.EventResult(SessionEntryId,RegistrationPersonId) WHERE SessionEntryId IS NOT NULL AND DeleteMark=0;'; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResultVersion]') AND name=N'UX_EventResultVersion_Result_Version') CREATE UNIQUE NONCLUSTERED INDEX [UX_EventResultVersion_Result_Version] ON dbo.[EventResultVersion]([EventResultId],[ResultVersion]) WHERE [DeleteMark]=0; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventJudgeMessage]') AND name=N'IX_EventJudgeMessage_Receiver_Unread') CREATE NONCLUSTERED INDEX [IX_EventJudgeMessage_Receiver_Unread] ON dbo.[EventJudgeMessage]([ReceiverUserId],[IsRead],[CreatedTime]) WHERE [DeleteMark]=0; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResultScreenCast]') AND name=N'IX_EventResultScreenCast_Event_Time') CREATE NONCLUSTERED INDEX [IX_EventResultScreenCast_Event_Time] ON dbo.[EventResultScreenCast]([EventId],[CastTime]) WHERE [DeleteMark]=0; @@ -798,22 +820,16 @@ BEGIN TRY PRINT N'[4/9] 插入数据:初始化计分规则、规则明细、角色与菜单'; /* 4.1 八条计分规则(固定Id:3000规定赛/3100个人花样/3200两人同步花样/3300四人同步花样/3400两人车轮跳花样/3500三人交互绳花样/3600四人交互绳花样/3700表演赛):先按 RuleCode 更新,再插入缺失,Id冲突则报错 */ CREATE TABLE #RuleSeed(SourceId BIGINT PRIMARY KEY,RuleCode NVARCHAR(64),RuleName NVARCHAR(128),JudgeRoleSchemaJson NVARCHAR(2000),RuleConfigJson NVARCHAR(4000),RuleVersion INT,Status INT,Sort INT,DeleteMark BIT,CreatedUserId BIGINT,CreatedTime DATETIME2(3)); - INSERT #RuleSeed VALUES (3000,N'ROPE_PRESCRIBED',N'规定赛',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判","min":1,"max":1}]},{"title":"创意编排裁判","slots":[{"code":"CJ","name":"创意编排裁判","min":1,"max":3}]},{"title":"完成质量裁判","slots":[{"code":"CQ","name":"完成质量裁判","min":1,"max":3}]}]',N'{"ruleType":"PRESCRIBED","baseScore":100,"scoreDecimals":2,"deductionUnit":5,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"CJ","symbol":"T1","label":"创意分","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1},{"roleType":"CQ","symbol":"T2","label":"完成分","sourceField":"RequiredScore","targetField":"RequiredScore","aggregate":"avg","sign":1},{"roleType":"T","symbol":"T3","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1}],"tieBreakers":["TotalScore","RequiredScore","PerformanceScore"]}',1,0,1,0,1000,N'2026-08-19T00:00:00'), - (3100,N'ROPE_FREESTYLE_SINGLE',N'个人花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_SINGLE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,2,0,1000,N'2026-08-19T00:00:00'), - (3200,N'ROPE_FREESTYLE_DOUBLE_SYNC',N'两人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_DOUBLE_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,3,0,1000,N'2026-08-19T00:00:00'), - (3300,N'ROPE_FREESTYLE_QUAD_SYNC',N'四人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_QUAD_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,4,0,1000,N'2026-08-19T00:00:00'), - (3400,N'ROPE_FREESTYLE_WHEEL_PAIR',N'两人车轮跳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DA","name":"难度裁判-DA(运动员A难度裁判)","min":1,"max":2},{"code":"DB","name":"难度裁判-DB(运动员B难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WHEEL","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DA","symbol":"dA","label":"运动员A难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DB","symbol":"dB","label":"运动员B难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,5,0,1000,N'2026-08-19T00:00:00'), - (3500,N'ROPE_FREESTYLE_WIRE_TRIPLE',N'三人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',1,0,6,0,1000,N'2026-08-19T00:00:00'), - (3600,N'ROPE_FREESTYLE_WIRE_QUAD',N'四人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',1,0,7,0,1000,N'2026-08-19T00:00:00'), - (3700,N'ROPE_SHOWCASE',N'表演赛(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (长绳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}]',N'{"ruleType":"SHOWCASE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DGA","symbol":"A","label":"A组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DGB","symbol":"B","label":"B组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,8,0,1000,N'2026-08-19T00:00:00'); + INSERT #RuleSeed VALUES (3000,N'ROPE_PRESCRIBED',N'规定赛',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判","min":1,"max":1}]},{"title":"创意编排裁判","slots":[{"code":"CJ","name":"创意编排裁判","min":1,"max":3}]},{"title":"完成质量裁判","slots":[{"code":"CQ","name":"完成质量裁判","min":1,"max":3}]}]',N'{"ruleType":"PRESCRIBED","baseScore":100,"scoreDecimals":2,"deductionUnit":5,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"CJ","symbol":"T1","label":"创意分","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1},{"roleType":"CQ","symbol":"T2","label":"完成分","sourceField":"RequiredScore","targetField":"RequiredScore","aggregate":"avg","sign":1},{"roleType":"T","symbol":"T3","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1}],"tieBreakers":["TotalScore","RequiredScore","PerformanceScore"]}',5,0,1,0,1000,N'2026-08-19T00:00:00'), + (3100,N'ROPE_FREESTYLE_SINGLE',N'个人花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_SINGLE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',6,0,2,0,1000,N'2026-08-19T00:00:00'), + (3200,N'ROPE_FREESTYLE_DOUBLE_SYNC',N'两人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_DOUBLE_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1},{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","sign":1,"factor":"Q","factorWeight":0.025}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',6,0,3,0,1000,N'2026-08-19T00:00:00'), + (3300,N'ROPE_FREESTYLE_QUAD_SYNC',N'四人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_QUAD_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1},{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","sign":1,"factor":"Q","factorWeight":0.025}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',6,0,4,0,1000,N'2026-08-19T00:00:00'), + (3400,N'ROPE_FREESTYLE_WHEEL_PAIR',N'两人车轮跳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DA","name":"难度裁判-DA(运动员A难度裁判)","min":1,"max":2},{"code":"DB","name":"难度裁判-DB(运动员B难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WHEEL","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DA","symbol":"dA","label":"运动员A难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DB","symbol":"dB","label":"运动员B难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',5,0,5,0,1000,N'2026-08-19T00:00:00'), + (3500,N'ROPE_FREESTYLE_WIRE_TRIPLE',N'三人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',5,0,6,0,1000,N'2026-08-19T00:00:00'), + (3600,N'ROPE_FREESTYLE_WIRE_QUAD',N'四人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',5,0,7,0,1000,N'2026-08-19T00:00:00'), + (3700,N'ROPE_SHOWCASE',N'表演赛(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (长绳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}]',N'{"ruleType":"SHOWCASE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DGA","symbol":"A","label":"A组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DGB","symbol":"B","label":"B组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',5,0,8,0,1000,N'2026-08-19T00:00:00'); - -- 两人/四人同步花样由主裁录入互动配合,缺失数 qI 与 DP/DM/DR 一同参与 Q。 - UPDATE #RuleSeed - SET RuleConfigJson=JSON_MODIFY( - RuleConfigJson, - N'append $.roleAggregations', - JSON_QUERY(N'{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","sign":1,"factor":"Q","factorWeight":0.025}')) - WHERE RuleCode IN (N'ROPE_FREESTYLE_DOUBLE_SYNC',N'ROPE_FREESTYLE_QUAD_SYNC'); + /* 规则版本和互动配合聚合已直接固化在种子行,避免上线时二次改写临时表。 */ UPDATE r SET RuleName=s.RuleName,JudgeRoleSchemaJson=s.JudgeRoleSchemaJson,RuleConfigJson=s.RuleConfigJson, RuleVersion=s.RuleVersion,Status=s.Status,Sort=s.Sort,DeleteMark=0,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() @@ -1129,33 +1145,33 @@ BEGIN TRY (3518,3500,N'DT',N'DIFF_LEVEL_1',N'1 级',1,NULL,1.5000,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',18,0,1000,N'2026-08-19T00:00:00'), (3519,3500,N'DT',N'DIFF_LEVEL_1_PLUS',N'1+ 级',1,NULL,1.8371,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',19,0,1000,N'2026-08-19T00:00:00'), (3520,3500,N'DT',N'DIFF_LEVEL_2_MINUS',N'2- 级',1,NULL,2.0331,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',20,0,1000,N'2026-08-19T00:00:00'), - (3521,3500,N'P',N'MUSIC_PLUS',N'音乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":1}',21,0,1000,N'2026-08-19T00:00:00'), - (3522,3500,N'P',N'MUSIC_MINUS',N'音乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":-1}',22,0,1000,N'2026-08-19T00:00:00'), - (3523,3500,N'P',N'MUSIC_SCORE',N'音乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"MUSIC","dimensionWeight":0.20,"baseValue":12.0}',23,0,1000,N'2026-08-19T00:00:00'), - (3524,3500,N'P',N'QUALITY_PLUS',N'完成质量(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":1}',24,0,1000,N'2026-08-19T00:00:00'), - (3525,3500,N'P',N'QUALITY_MINUS',N'完成质量(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":-1}',25,0,1000,N'2026-08-19T00:00:00'), - (3526,3500,N'P',N'QUALITY_SCORE',N'完成质量',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"QUALITY","dimensionWeight":0.25,"baseValue":12.0}',26,0,1000,N'2026-08-19T00:00:00'), - (3527,3500,N'P',N'ENTERTAINMENT_PLUS',N'娱乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":1}',27,0,1000,N'2026-08-19T00:00:00'), - (3528,3500,N'P',N'ENTERTAINMENT_MINUS',N'娱乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":-1}',28,0,1000,N'2026-08-19T00:00:00'), - (3529,3500,N'P',N'ENTERTAINMENT_SCORE',N'娱乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"ENTERTAINMENT","dimensionWeight":0.25,"baseValue":12.0}',29,0,1000,N'2026-08-19T00:00:00'), - (3530,3500,N'P',N'CREATIVITY_PLUS',N'创意(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":1}',30,0,1000,N'2026-08-19T00:00:00'), - (3531,3500,N'P',N'CREATIVITY_MINUS',N'创意(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":-1}',31,0,1000,N'2026-08-19T00:00:00'), - (3532,3500,N'P',N'CREATIVITY_SCORE',N'创意',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"CREATIVITY","dimensionWeight":0.15,"baseValue":12.0}',32,0,1000,N'2026-08-19T00:00:00'), - (3533,3500,N'P',N'VARIETY_PLUS',N'多样性(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":1}',33,0,1000,N'2026-08-19T00:00:00'), - (3534,3500,N'P',N'VARIETY_MINUS',N'多样性(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":-1}',34,0,1000,N'2026-08-19T00:00:00'), - (3535,3500,N'P',N'VARIETY_SCORE',N'多样性',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"VARIETY","dimensionWeight":0.15,"baseValue":12.0}',35,0,1000,N'2026-08-19T00:00:00'), - (3536,3500,N'P',N'FAILURE_COUNT',N'失误次数',3,NULL,1,0,50,1,0,0,0,0,N'{"inputMode":"count","unitLabel":"次","isFailureCount":true,"remark":"表现裁判记一次失误,其对应的表现五个方面(音乐,完成质量,创意,娱乐和多样性)减数量+1"}',36,0,1000,N'2026-08-19T00:00:00'), - (3537,3500,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次","stepDeductions":[0.05,0.075,0.1],"remark":"第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',37,0,1000,N'2026-08-19T00:00:00'), - (3538,3500,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',38,0,1000,N'2026-08-19T00:00:00'), - (3539,3500,N'T',N'T_SPACE_VIOLATION',N'空间违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',39,0,1000,N'2026-08-19T00:00:00'), - (3540,3500,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,40,0,1000,N'2026-08-19T00:00:00'), - (3541,3500,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,41,0,1000,N'2026-08-19T00:00:00'), - (3542,3500,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,42,0,1000,N'2026-08-19T00:00:00'), - (3543,3500,N'T',N'DQ_EXTERNAL_AID',N'使用外部助力器材',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,43,0,1000,N'2026-08-19T00:00:00'), - (3544,3500,N'T',N'DQ_UNCIVILIZED',N'比赛中嚼口香糖/不文明用语等',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,44,0,1000,N'2026-08-19T00:00:00'), - (3545,3500,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,45,0,1000,N'2026-08-19T00:00:00'), - (3546,3500,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,46,0,1000,N'2026-08-19T00:00:00'), - (3547,3500,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,47,0,1000,N'2026-08-19T00:00:00'), + (3521,3500,N'P',N'MUSIC_PLUS',N'音乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":1}',32,0,1000,N'2026-08-19T00:00:00'), + (3522,3500,N'P',N'MUSIC_MINUS',N'音乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":-1}',33,0,1000,N'2026-08-19T00:00:00'), + (3523,3500,N'P',N'MUSIC_SCORE',N'音乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"MUSIC","dimensionWeight":0.20,"baseValue":12.0}',34,0,1000,N'2026-08-19T00:00:00'), + (3524,3500,N'P',N'QUALITY_PLUS',N'完成质量(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":1}',35,0,1000,N'2026-08-19T00:00:00'), + (3525,3500,N'P',N'QUALITY_MINUS',N'完成质量(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":-1}',36,0,1000,N'2026-08-19T00:00:00'), + (3526,3500,N'P',N'QUALITY_SCORE',N'完成质量',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"QUALITY","dimensionWeight":0.25,"baseValue":12.0}',37,0,1000,N'2026-08-19T00:00:00'), + (3527,3500,N'P',N'ENTERTAINMENT_PLUS',N'娱乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":1}',38,0,1000,N'2026-08-19T00:00:00'), + (3528,3500,N'P',N'ENTERTAINMENT_MINUS',N'娱乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":-1}',39,0,1000,N'2026-08-19T00:00:00'), + (3529,3500,N'P',N'ENTERTAINMENT_SCORE',N'娱乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"ENTERTAINMENT","dimensionWeight":0.25,"baseValue":12.0}',40,0,1000,N'2026-08-19T00:00:00'), + (3530,3500,N'P',N'CREATIVITY_PLUS',N'创意(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":1}',41,0,1000,N'2026-08-19T00:00:00'), + (3531,3500,N'P',N'CREATIVITY_MINUS',N'创意(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":-1}',42,0,1000,N'2026-08-19T00:00:00'), + (3532,3500,N'P',N'CREATIVITY_SCORE',N'创意',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"CREATIVITY","dimensionWeight":0.15,"baseValue":12.0}',43,0,1000,N'2026-08-19T00:00:00'), + (3533,3500,N'P',N'VARIETY_PLUS',N'多样性(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":1}',44,0,1000,N'2026-08-19T00:00:00'), + (3534,3500,N'P',N'VARIETY_MINUS',N'多样性(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":-1}',45,0,1000,N'2026-08-19T00:00:00'), + (3535,3500,N'P',N'VARIETY_SCORE',N'多样性',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"VARIETY","dimensionWeight":0.15,"baseValue":12.0}',46,0,1000,N'2026-08-19T00:00:00'), + (3536,3500,N'P',N'FAILURE_COUNT',N'失误次数',3,NULL,1,0,50,1,0,0,0,0,N'{"inputMode":"count","unitLabel":"次","isFailureCount":true,"remark":"表现裁判记一次失误,其对应的表现五个方面(音乐,完成质量,创意,娱乐和多样性)减数量+1"}',47,0,1000,N'2026-08-19T00:00:00'), + (3537,3500,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次","stepDeductions":[0.05,0.075,0.1],"remark":"第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',50,0,1000,N'2026-08-19T00:00:00'), + (3538,3500,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',48,0,1000,N'2026-08-19T00:00:00'), + (3539,3500,N'T',N'T_SPACE_VIOLATION',N'空间违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',49,0,1000,N'2026-08-19T00:00:00'), + (3540,3500,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,51,0,1000,N'2026-08-19T00:00:00'), + (3541,3500,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,52,0,1000,N'2026-08-19T00:00:00'), + (3542,3500,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,53,0,1000,N'2026-08-19T00:00:00'), + (3543,3500,N'T',N'DQ_EXTERNAL_AID',N'使用外部助力器材',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,54,0,1000,N'2026-08-19T00:00:00'), + (3544,3500,N'T',N'DQ_UNCIVILIZED',N'比赛中嚼口香糖/不文明用语等',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,55,0,1000,N'2026-08-19T00:00:00'), + (3545,3500,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,56,0,1000,N'2026-08-19T00:00:00'), + (3546,3500,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,57,0,1000,N'2026-08-19T00:00:00'), + (3547,3500,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,58,0,1000,N'2026-08-19T00:00:00'), (3548,3500,N'DT',N'DIFF_LEVEL_2',N'2 级',1,NULL,2.2500,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',21,0,1000,N'2026-08-19T00:00:00'), (3549,3500,N'DT',N'DIFF_LEVEL_2_PLUS',N'2+ 级',1,NULL,2.7557,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',22,0,1000,N'2026-08-19T00:00:00'), (3550,3500,N'DT',N'DIFF_LEVEL_3_MINUS',N'3- 级',1,NULL,3.0497,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',23,0,1000,N'2026-08-19T00:00:00'), @@ -1339,6 +1355,8 @@ BEGIN TRY (3812,3700,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,112,0,1000,N'2026-08-19T00:00:00'); + /* 三人交互绳评分项顺序已直接固化为测试库基线 32-58。 */ + UPDATE i SET ItemName=s.ItemName,ItemType=s.ItemType,ParentItemCode=s.ParentItemCode,UnitValue=s.UnitValue,MinValue=s.MinValue, MaxValue=s.MaxValue,StepValue=s.StepValue,DefaultValue=s.DefaultValue,CalcMode=s.CalcMode,ScoreDimension=s.ScoreDimension, IsRequired=s.IsRequired,ExtensionJson=s.ExtensionJson,Sort=s.Sort,DeleteMark=s.DeleteMark,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() @@ -1373,14 +1391,48 @@ BEGIN TRY AND i.ItemType=1 AND NOT EXISTS(SELECT 1 FROM #ItemSeed s WHERE s.SourceRuleId=m.SourceId AND s.JudgeRoleType=i.JudgeRoleType AND s.ItemCode=i.ItemCode); - /* 4.2.1 交互绳基础项目必须绑定交互绳规则,避免新编排场次继承到无评分项的旧规则。 */ - DECLARE @WireRuleId BIGINT = (SELECT TOP 1 Id FROM dbo.ScoreRule WHERE RuleCode LIKE N'ROPE_FREESTYLE_WIRE_%' AND DeleteMark=0 ORDER BY Id); - IF @WireRuleId IS NULL THROW 51012,N'未找到交互绳花样计分规则(ROPE_FREESTYLE_WIRE_*)。',1; - UPDATE dbo.Project - SET ScoreRuleId=@WireRuleId,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() - WHERE Name IN (N'2人交互绳',N'3人交互绳') - AND DeleteMark=0 - AND ISNULL(ScoreRuleId,0)<>@WireRuleId; + /* 将脚本范围内未定义但仍启用的旧评分项软删除,保证有效项与测试库种子完全一致。 */ + UPDATE item + SET DeleteMark=1,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() + FROM dbo.ScoreRuleItem item + JOIN #RuleMap map ON map.TargetId=item.ScoreRuleId + WHERE item.DeleteMark=0 + AND NOT EXISTS( + SELECT 1 + FROM #ItemSeed seed + WHERE seed.SourceRuleId=map.SourceId + AND seed.JudgeRoleType=item.JudgeRoleType + AND seed.ItemCode=item.ItemCode + AND seed.DeleteMark=0 + ); + + /* 4.2.1 标准项目及已确认历史名称绑定计分规则(名称 + 项目类型共同定位,避免同名项目误绑)。 */ + DECLARE @ProjectRuleSeed TABLE(ProjectName NVARCHAR(128),ProjectType INT,RuleCode NVARCHAR(64),PRIMARY KEY(ProjectName,ProjectType)); + INSERT @ProjectRuleSeed(ProjectName,ProjectType,RuleCode) VALUES + (N'个人花样',1004,N'ROPE_FREESTYLE_SINGLE'), + (N'规定赛',1004,N'ROPE_PRESCRIBED'), + (N'两人同步花样',1004,N'ROPE_FREESTYLE_DOUBLE_SYNC'), + (N'四人同步花样',1004,N'ROPE_FREESTYLE_QUAD_SYNC'), + (N'两人车轮跳花样',1004,N'ROPE_FREESTYLE_WHEEL_PAIR'), + (N'三人交互绳花样',1004,N'ROPE_FREESTYLE_WIRE_TRIPLE'), + (N'四人交互绳花样',1004,N'ROPE_FREESTYLE_WIRE_QUAD'), + (N'表演赛',1006,N'ROPE_SHOWCASE'), + (N'2人交互绳',1006,N'ROPE_FREESTYLE_WIRE_TRIPLE'), + (N'3人交互绳',1006,N'ROPE_FREESTYLE_WIRE_TRIPLE'); + UPDATE project + SET ScoreRuleId=rule.Id,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() + FROM dbo.Project project + JOIN @ProjectRuleSeed seed ON seed.ProjectName=project.Name AND seed.ProjectType=project.ProjectType + JOIN dbo.ScoreRule rule ON rule.RuleCode=seed.RuleCode AND rule.DeleteMark=0 + WHERE project.DeleteMark=0 + AND ISNULL(project.ScoreRuleId,0)<>rule.Id; + IF EXISTS( + SELECT 1 + FROM dbo.Project project + JOIN @ProjectRuleSeed seed ON seed.ProjectName=project.Name AND seed.ProjectType=project.ProjectType + LEFT JOIN dbo.ScoreRule rule ON rule.RuleCode=seed.RuleCode AND rule.DeleteMark=0 + WHERE project.DeleteMark=0 AND (rule.Id IS NULL OR ISNULL(project.ScoreRuleId,0)<>rule.Id) + ) THROW 51012,N'标准项目计分规则绑定未完整同步。',1; /* 4.3 角色:Id=1003 “打分系统单位(scoringunit)”;若该Id被其他编码占用则报错终止 */ IF EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code<>N'scoringunit') THROW 51005,N'SysRole.Id=1003 已被其他角色占用。',1; @@ -1402,13 +1454,15 @@ BEGIN TRY (1083,N'打分账号-删除',2,N'system:unit:delete',1080,N'btn_system_unit_delete',N'',N'',N'',N'',0,N'',0,1,0,0,3,N'单位管理:账号删除',0,1000,N'2023-06-01'), (1084,N'打分账号-启用禁用',2,N'system:unit:status',1080,N'btn_system_unit_status',N'',N'',N'',N'',0,N'',0,1,0,0,4,N'单位管理:账号状态',0,1000,N'2023-06-01'), (1085,N'打分账号-重置密码',2,N'system:unit:resetpwd',1080,N'btn_system_unit_resetpwd',N'',N'',N'',N'',0,N'',0,1,0,0,5,N'单位管理:重置密码',0,1000,N'2023-06-01'), - (1086,N'打分系统工作台',0,N'scoring',NULL,N'scoring',N'/scoring',N'Layout',N'/scoring/launcher',N'ele-Trophy',0,N'',1,1,0,0,190,N'打分系统工作台',0,1000,N'2023-06-01'), - (1087,N'工作台',1,N'scoring:launcher',1086,N'scoringLauncher',N'/scoring/launcher',N'scoring/launcher/index',N'',N'ele-Monitor',0,N'',1,1,0,0,1,N'选择计分模式和赛事',0,1000,N'2023-06-01'), - (1088,N'秩序册',1,N'scoring:orderbook',1086,N'scoringOrderBook',N'/scoring/orderbook',N'scoring/orderbook/index',N'',N'ele-Notebook',0,N'',1,1,0,0,2,N'秩序册导入',0,1000,N'2023-06-01'), + (1086,N'打分系统工作台',0,N'scoring',NULL,N'scoring',N'/scoring',N'Layout',N'',N'ele-Trophy',0,N'',1,1,0,0,190,N'打分系统工作台',0,1000,N'2023-06-01'), + (1087,N'秩序册',1,N'scoring:launcher',1086,N'scoringLauncher',N'/scoring/launcher',N'scoring/launcher/index',N'',N'ele-Notebook',0,N'',1,1,0,0,1,N'秩序册',0,1000,N'2023-06-01'), + (1088,N'成绩投屏',1,N'scoring:screen',1086,N'scoringScreen',N'/scoring/screen',N'scoring/screen/index',N'',N'ele-DataLine',0,N'',1,1,0,0,2,N'成绩投屏',0,1000,N'2023-06-01'), (1089,N'成绩管理',1,N'scoring:workbench',1086,N'scoringWorkbench',N'/scoring/workbench',N'scoring/workbench/index',N'',N'ele-Management',0,N'',1,1,0,0,3,N'成绩管理',0,1000,N'2023-06-01'), - (1090,N'成绩投屏',1,N'scoring:cast',1086,N'scoringCast',N'/scoring/cast',N'scoring/workbench/index',N'',N'ele-DataLine',0,N'',1,1,0,0,4,N'成绩投屏操作台',0,1000,N'2023-06-01'), (2010,N'裁判管理',1,N'referee',NULL,N'referee',N'/referee',N'match/referee/index',N'',N'ele-UserFilled',0,N'',1,1,0,0,245,N'裁判库管理',0,1000,N'2023-06-01'); - IF EXISTS(SELECT 1 FROM #MenuSeed s JOIN dbo.SysMenu m ON m.Id=s.Id WHERE ISNULL(m.Code,N'')<>ISNULL(s.Code,N'')) THROW 51006,N'二期菜单ID已被其他菜单占用。',1; + IF EXISTS( + SELECT 1 FROM #MenuSeed s JOIN dbo.SysMenu m ON m.Id=s.Id + WHERE ISNULL(m.Code,N'')<>ISNULL(s.Code,N'') + ) THROW 51006,N'二期菜单ID已被其他菜单占用。',1; UPDATE m SET Name=s.Name,Type=s.Type,Code=s.Code,ParentId=s.ParentId,RouteName=s.RouteName,Path=s.Path,Component=s.Component,Redirect=s.Redirect,Icon=s.Icon,IsIframe=s.IsIframe,Link=s.Link,IsVisible=s.IsVisible,IsKeepAlive=s.IsKeepAlive,IsFixed=s.IsFixed,Status=s.Status,Sort=s.Sort,Remark=s.Remark,DeleteMark=0,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() FROM dbo.SysMenu m JOIN #MenuSeed s ON s.Id=m.Id WHERE EXISTS(SELECT m.Name,m.Type,m.Code,m.ParentId,m.RouteName,m.Path,m.Component,m.Redirect,m.Icon,m.IsIframe,m.Link,m.IsVisible,m.IsKeepAlive,m.IsFixed,m.Status,m.Sort,m.Remark,m.DeleteMark @@ -1419,9 +1473,9 @@ BEGIN TRY /* 4.5 角色-菜单授权:按角色和菜单匹配已有关系,缺失关系自动生成新Id */ DECLARE @RoleMenuSeed TABLE(Id BIGINT NULL,RoleId BIGINT,MenuId BIGINT,SeedOrder INT IDENTITY(1,1),PRIMARY KEY(RoleId,MenuId)); INSERT @RoleMenuSeed(RoleId,MenuId) VALUES - (1000,1080),(1000,1081),(1000,1082),(1000,1083),(1000,1084),(1000,1085),(1000,1086),(1000,1087),(1000,1088),(1000,1089),(1000,1090),(1000,2010), - (1003,1086),(1003,1087),(1003,1088),(1003,1089),(1003,1090), - (1001,1086),(1001,1089),(1001,1090); + (1000,1080),(1000,1081),(1000,1082),(1000,1083),(1000,1084),(1000,1085),(1000,1086),(1000,1087),(1000,1088),(1000,1089),(1000,2010), + (1003,1087),(1003,1088),(1003,1089), + (1001,1088),(1001,1089); DECLARE @RoleMenuNextId BIGINT; SELECT @RoleMenuNextId=ISNULL(MAX(Id),0) FROM dbo.SysRoleMenu WITH (UPDLOCK,HOLDLOCK); UPDATE s SET Id=rm.Id @@ -1567,16 +1621,19 @@ SELECT r.RuleCode,COUNT(i.Id) AS ItemCount FROM dbo.ScoreRule r LEFT JOIN dbo.Sc (N'INDEX',N'二期索引',CASE WHEN (SELECT COUNT(*) FROM sys.indexes WHERE name IN(N'UX_Referee_Mobile_Active',N'UX_EventReferee_Event_Referee_Active',N'UX_EventVenue_Event_Code_Active',N'UX_EventSession_Event_No_Active',N'UX_EventJudgeScoreSheet_Idempotency',N'UX_EventResultVersion_Result_Version'))=6 THEN 1 ELSE 0 END,N'6个关键索引'), (N'CONSTRAINT',N'二期外键',CASE WHEN (SELECT COUNT(*) FROM sys.foreign_keys WHERE name LIKE 'FK[_]%' AND parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables))>=20 THEN 1 ELSE 0 END,CONVERT(NVARCHAR(20),(SELECT COUNT(*) FROM sys.foreign_keys WHERE name LIKE 'FK[_]%' AND parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables)))), (N'SEED',N'计分规则',CASE WHEN (SELECT COUNT(DISTINCT r.RuleCode) FROM dbo.ScoreRule r JOIN #RuleSeed s ON s.RuleCode=r.RuleCode WHERE r.DeleteMark=0)=8 THEN 1 ELSE 0 END,N'期望8条'), - (N'SEED',N'计分规则明细',CASE WHEN (SELECT COUNT(*) FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId JOIN dbo.ScoreRuleItem i ON i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=0 WHERE s.DeleteMark=0)=(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0) THEN 1 ELSE 0 END,CONCAT(N'期望',(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0),N'条启用评分项')), + (N'SEED',N'计分规则明细',CASE WHEN (SELECT COUNT(*) FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId JOIN dbo.ScoreRuleItem i ON i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=0 WHERE s.DeleteMark=0)=(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0) + AND (SELECT COUNT(*) FROM dbo.ScoreRuleItem i JOIN #RuleMap m ON m.TargetId=i.ScoreRuleId WHERE i.DeleteMark=0)=(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0) + THEN 1 ELSE 0 END,CONCAT(N'期望且仅允许',(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0),N'条启用评分项')), + (N'SEED',N'标准项目规则绑定',CASE WHEN NOT EXISTS(SELECT 1 FROM dbo.Project project JOIN @ProjectRuleSeed seed ON seed.ProjectName=project.Name AND seed.ProjectType=project.ProjectType LEFT JOIN dbo.ScoreRule rule ON rule.RuleCode=seed.RuleCode AND rule.DeleteMark=0 WHERE project.DeleteMark=0 AND (rule.Id IS NULL OR ISNULL(project.ScoreRuleId,0)<>rule.Id)) THEN 1 ELSE 0 END,N'按项目名称和项目类型核对10条映射'), (N'SEED',N'角色与菜单',CASE WHEN EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code='scoringunit' AND DeleteMark=0) - AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,2010) AND DeleteMark=0)=12 + AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,2010) AND DeleteMark=0)=11 AND EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1080 AND Code='system:unit' AND ParentId=1070 AND DeleteMark=0) AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1081,1082,1083,1084,1085) AND ParentId=1080 AND DeleteMark=0)=5 AND EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1086 AND Code='scoring' AND DeleteMark=0) - AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1087,1088,1089,1090) AND ParentId=1086 AND DeleteMark=0)=4 - AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1000 AND MenuId IN(1080,1086,1087,1088,1089,1090) AND DeleteMark=0)=6 - AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1003 AND MenuId IN(1086,1087,1088,1089,1090) AND DeleteMark=0)=5 - AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1001 AND MenuId IN(1086,1089,1090) AND DeleteMark=0)=3 + AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1087,1088,1089) AND ParentId=1086 AND DeleteMark=0)=3 + AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1000 AND MenuId IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,2010) AND DeleteMark=0)=11 + AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1003 AND MenuId IN(1087,1088,1089) AND DeleteMark=0)=3 + AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1001 AND MenuId IN(1088,1089) AND DeleteMark=0)=2 THEN 1 ELSE 0 END,N'单位管理、工作台及三个业务模块、三类角色菜单授权'), (N'PERMISSION',N'最小权限角色',CASE WHEN (SELECT COUNT(*) FROM sys.database_principals WHERE name IN('yd_phase2_app_rw','yd_phase2_app_ro','yd_phase2_executor') AND type='R')=3 THEN 1 ELSE 0 END,N'期望3个数据库角色'); diff --git a/二期需求/上线/dbo_add.sql b/二期需求/上线/dbo_add.sql index 72e0082..f77a368 100644 --- a/二期需求/上线/dbo_add.sql +++ b/二期需求/上线/dbo_add.sql @@ -11,6 +11,31 @@ BEGIN TRY EXEC @LockResult=sys.sp_getapplock @Resource=N'YD_Event_Phase2_Production_Deployment',@LockMode='Exclusive',@LockOwner='Transaction',@LockTimeout=10000; IF @LockResult<0 THROW 51002,N'无法取得二期部署排他锁,可能有另一个部署正在执行。',1; + /* 在任何 DDL 前阻断不兼容版本或错误基线,避免三段脚本只完成一部分。 */ + DECLARE @ProductMajorVersion INT=CONVERT(INT,SERVERPROPERTY('ProductMajorVersion')); + DECLARE @ProductBuild INT=TRY_CONVERT(INT,PARSENAME(CONVERT(NVARCHAR(128),SERVERPROPERTY('ProductVersion')),2)); + DECLARE @CompatibilityLevel INT=(SELECT compatibility_level FROM sys.databases WHERE name=DB_NAME()); + IF @ProductMajorVersion<13 OR (@ProductMajorVersion=13 AND ISNULL(@ProductBuild,0)<4001) + THROW 51000,N'二期脚本要求 SQL Server 2016 SP1 或更高版本。',1; + IF @CompatibilityLevel<130 THROW 51000,N'二期脚本要求数据库兼容级别不低于 130。',1; + IF EXISTS( + SELECT 1 FROM (VALUES + (N'AppUser'),(N'EventInfo'),(N'EventRegistrationLimit'),(N'EventRegistration'),(N'EventRegistrationItem'), + (N'Team'),(N'EventProject'),(N'Project'),(N'SysUser'),(N'EventResult'),(N'SysRole'),(N'SysMenu'),(N'SysRoleMenu')) required(Name) + WHERE OBJECT_ID(N'dbo.'+QUOTENAME(required.Name),N'U') IS NULL + ) THROW 51001,N'目标库缺少二期升级所需的一期基础表,禁止继续。',1; + IF EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code<>N'scoringunit') + THROW 51005,N'SysRole.Id=1003 已被其他角色占用。',1; + IF EXISTS( + SELECT 1 + FROM (VALUES + (1080,N'system:unit'),(1081,N'system:unit:add'),(1082,N'system:unit:edit'),(1083,N'system:unit:delete'), + (1084,N'system:unit:status'),(1085,N'system:unit:resetpwd'),(1086,N'scoring'),(1087,N'scoring:launcher'), + (1088,N'scoring:screen'),(1089,N'scoring:workbench'),(2010,N'referee')) expected(Id,Code) + JOIN dbo.SysMenu menu ON menu.Id=expected.Id + WHERE ISNULL(menu.Code,N'')<>expected.Code + ) THROW 51006,N'二期菜单固定 Id 已被其他业务占用。',1; + /* 20 张二期业务表:存在则跳过。 */ PRINT N'[ADD] 创建二期业务表'; /* RefereeApplication:裁判通过小程序报名执裁及审核状态。 */ @@ -25,9 +50,9 @@ BEGIN TRY [Status] INT NOT NULL CONSTRAINT [DF_RefereeApplication_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_RefereeApplication_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -57,9 +82,9 @@ BEGIN TRY [Status] INT NOT NULL CONSTRAINT [DF_CheckinTask_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_CheckinTask_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -73,15 +98,15 @@ BEGIN TRY [SessionKey] NVARCHAR(64) NULL, -- 秩序册列标识 [SessionOrder] INT NOT NULL CONSTRAINT [DF_CheckinRecord_SessionOrder] DEFAULT (0), -- 秩序册列的出场顺序 [GroupId] BIGINT NULL, -- 参赛组别Id(不限定组别时为空) - [RegistrationPersonId] BIGINT NOT NULL, -- 关联的报名人员Id + [RegistrationPersonId] BIGINT NULL, -- 与测试库一致:非人员级检录记录允许为空 [CheckerUserId] BIGINT NOT NULL, -- 执行检录的检录员用户Id [Checked] BIT NOT NULL CONSTRAINT [DF_CheckinRecord_Checked] DEFAULT (0), -- 是否已检录(取消检录置为0) - [CheckedTime] DATETIME2(3) NULL, -- 检录时间(取消检录时置空) + [CheckedTime] DATETIME2(7) NULL, -- 检录时间(取消检录时置空) [DeleteMark] BIT NOT NULL CONSTRAINT [DF_CheckinRecord_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -127,9 +152,9 @@ BEGIN TRY [Status] INT NOT NULL CONSTRAINT [DF_EventReferee_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_EventReferee_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(7) NOT NULL, -- 与测试库一致:创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) - [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) + [UpdatedTime] DATETIME2(7) NULL -- 最后更新时间(UTC,未更新过为空) ); END; @@ -143,7 +168,7 @@ BEGIN TRY [EventRefereeId] BIGINT NOT NULL, -- 关联赛事裁判记录Id(EventReferee.Id) [RefereeId] BIGINT NOT NULL, -- 关联裁判档案Id(兼容历史查询的冗余字段) [JudgeUserId] BIGINT NULL, -- 关联小程序用户Id(裁判未注册小程序时为空) - [JudgeRole] NVARCHAR(32) NOT NULL, -- 裁判席位编码(取自计分规则席位配置,如T、DP1、P) + [JudgeRole] VARCHAR(32) NOT NULL, -- 与测试库一致:裁判席位编码(ASCII) [JudgeRoleType] NVARCHAR(16) NULL, -- 裁判角色类别编码(如DP、DM、DR、P、T) [AssignmentStatus] INT NOT NULL CONSTRAINT [DF_EventJudgeAssignment_AssignmentStatus] DEFAULT (0), -- 分配状态:0-草稿,1-已提交,2-已替换,9-已停用 [SubmittedTime] DATETIME2(3) NULL, -- 提交时间 @@ -198,7 +223,7 @@ BEGIN TRY CREATE TABLE dbo.[EventVenue] ( [Id] BIGINT NOT NULL CONSTRAINT [PK_EventVenue] PRIMARY KEY, -- 主键Id(雪花Id) [EventId] BIGINT NOT NULL, -- 关联赛事Id - [VenueCode] NVARCHAR(32) NOT NULL, -- 场地编码(同一赛事未删除数据中唯一,如V01) + [VenueCode] VARCHAR(32) NOT NULL, -- 与测试库一致:场地编码(ASCII) [VenueName] NVARCHAR(128) NOT NULL, -- 场地名称 [Status] INT NOT NULL CONSTRAINT [DF_EventVenue_Status] DEFAULT (0), -- 可用状态:0-启用,1-禁用 [Sort] INT NOT NULL CONSTRAINT [DF_EventVenue_Sort] DEFAULT (0), -- 排序 @@ -220,7 +245,7 @@ BEGIN TRY [EventProjectGroupId] BIGINT NULL, -- 关联赛事项目组别Id(多组别混合时为空) [VenueId] BIGINT NOT NULL, -- 关联比赛场地Id(EventVenue.Id) [ScoreRuleId] BIGINT NOT NULL, -- 关联计分规则Id(取自项目配置) - [SessionNo] NVARCHAR(32) NOT NULL, -- 场次编号(同一赛事未删除数据中唯一) + [SessionNo] VARCHAR(32) NOT NULL, -- 与测试库一致:场次编号(ASCII) [SessionName] NVARCHAR(128) NULL, -- 场次名称 [StartTime] DATETIME2(3) NULL, -- 场次开始时间 [EndTime] DATETIME2(3) NULL, -- 场次结束时间 @@ -245,7 +270,7 @@ BEGIN TRY [ParticipationRecordId] BIGINT NULL, -- 关联赛事参赛记录Id(未匹配到参赛记录时为空) [RegistrationItemId] BIGINT NULL, -- 关联报名项目明细Id [SourceType] INT NOT NULL CONSTRAINT [DF_EventSessionEntry_SourceType] DEFAULT (0), -- 出场数据来源:0-报名平台编排,1-秩序册导入 - [EntryNo] NVARCHAR(32) NOT NULL, -- 出场编号(项目序号+场地序号+出场顺序) + [EntryNo] VARCHAR(32) NOT NULL, -- 与测试库一致:出场编号(ASCII) [PlayOrder] INT NOT NULL, -- 出场顺序(同一场次未删除数据中唯一) [EntryStatus] INT NOT NULL CONSTRAINT [DF_EventSessionEntry_EntryStatus] DEFAULT (0), -- 出场状态:0-待出场,10-已检录,20-已叫号,30-进行中,40-已完成,80-退赛,90-取消比赛资格 [CallTime] DATETIME2(3) NULL, -- 叫号时间 @@ -321,7 +346,7 @@ BEGIN TRY BEGIN CREATE TABLE dbo.[ScoreRule] ( [Id] BIGINT NOT NULL CONSTRAINT [PK_ScoreRule] PRIMARY KEY, -- 主键Id(雪花Id) - [RuleCode] NVARCHAR(64) NOT NULL, -- 规则编码(未删除数据中唯一,如ROPE_PRESCRIBED/ROPE_PRESCRIBED_SINGLE) + [RuleCode] VARCHAR(64) NOT NULL, -- 与测试库一致:规则编码(ASCII) [RuleName] NVARCHAR(128) NOT NULL, -- 规则名称 [JudgeRoleSchemaJson] NVARCHAR(2000) NOT NULL, -- 裁判席位配置(JSON,按裁判组描述所需角色席位) [RuleConfigJson] NVARCHAR(4000) NULL, -- 计分参数配置(JSON,扣分项/权重等扩展参数) @@ -330,7 +355,7 @@ BEGIN TRY [Sort] INT NOT NULL CONSTRAINT [DF_ScoreRule_Sort] DEFAULT (0), -- 排序 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_ScoreRule_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 [CreatedUserId] BIGINT NOT NULL, -- 创建人用户Id - [CreatedTime] DATETIME2(3) NOT NULL, -- 创建时间(UTC) + [CreatedTime] DATETIME2(3) NOT NULL CONSTRAINT [DF_ScoreRule_Created] DEFAULT (SYSDATETIME()), -- 创建时间(UTC) [UpdatedUserId] BIGINT NULL, -- 最后更新人用户Id(未更新过为空) [UpdatedTime] DATETIME2(3) NULL -- 最后更新时间(UTC,未更新过为空) ); @@ -469,20 +494,20 @@ BEGIN TRY [EventResultId] BIGINT NOT NULL, -- 关联赛事成绩Id(EventResult.Id) [EventId] BIGINT NOT NULL, -- 关联赛事Id [SessionEntryId] BIGINT NOT NULL, -- 关联场次出场记录Id - [ResultVersion] INT NOT NULL, -- 成绩版本号 - [DifficultyScore] DECIMAL(18,4) NOT NULL, -- 难度分 - [PerformanceScore] DECIMAL(18,4) NOT NULL, -- 表现分 - [RequiredScore] DECIMAL(18,4) NOT NULL, -- 规定分 - [DeductionScore] DECIMAL(18,4) NOT NULL, -- 扣分 - [TotalScore] DECIMAL(18,4) NOT NULL, -- 正式总分 + [ResultVersion] INT NOT NULL CONSTRAINT [DF_EventResultVersion_Version] DEFAULT (1), -- 成绩版本号 + [DifficultyScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_DifficultyScore] DEFAULT (0), -- 难度分 + [PerformanceScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_PerformanceScore] DEFAULT (0), -- 表现分 + [RequiredScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_RequiredScore] DEFAULT (0), -- 规定分 + [DeductionScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_DeductionScore] DEFAULT (0), -- 扣分 + [TotalScore] DECIMAL(18,4) NOT NULL CONSTRAINT [DF_EventResultVersion_TotalScore] DEFAULT (0), -- 正式总分 [Rank] INT NULL, -- 名次 - [IsDisqualified] BIT NOT NULL, -- 是否取消比赛资格 + [IsDisqualified] BIT NOT NULL CONSTRAINT [DF_EventResultVersion_IsDisqualified] DEFAULT (0), -- 是否取消比赛资格 [DisqualifyReasonCode] NVARCHAR(64) NULL, -- 取消比赛资格原因编码 - [ResultStatus] INT NOT NULL, -- 成绩状态:0-计算中,10-待复核,20-已确认,30-已投屏,40-已更正,90-已作废 - [SourceType] INT NOT NULL, -- 版本来源:0-正常聚合,1-成绩修正,2-重赛 + [ResultStatus] INT NOT NULL CONSTRAINT [DF_EventResultVersion_Status] DEFAULT (0), -- 成绩状态:0-计算中,10-待复核,20-已确认,30-已投屏,40-已更正,90-已作废 + [SourceType] INT NOT NULL CONSTRAINT [DF_EventResultVersion_SourceType] DEFAULT (0), -- 版本来源:0-正常聚合,1-成绩修正,2-重赛 [ScoreCorrectionId] BIGINT NULL, -- 关联成绩修正申请Id [ScoreRuleId] BIGINT NOT NULL, -- 关联计分规则Id - [RuleVersion] INT NOT NULL, -- 计分规则版本号 + [RuleVersion] INT NOT NULL CONSTRAINT [DF_EventResultVersion_RuleVersion] DEFAULT (1), -- 计分规则版本号 [CalculationJson] NVARCHAR(MAX) NULL, -- 聚合计算明细(JSON) [Remark] NVARCHAR(512) NULL, -- 版本说明 [DeleteMark] BIT NOT NULL CONSTRAINT [DF_EventResultVersion_DeleteMark] DEFAULT (0), -- 软删除标记:0-正常,1-已删除 diff --git a/二期需求/上线/dbo_alter.sql b/二期需求/上线/dbo_alter.sql index 949be01..0d7b906 100644 --- a/二期需求/上线/dbo_alter.sql +++ b/二期需求/上线/dbo_alter.sql @@ -63,67 +63,50 @@ BEGIN TRY IF COL_LENGTH(N'dbo.EventRegistrationItem', N'TeamName') IS NULL ALTER TABLE dbo.EventRegistrationItem ADD TeamName NVARCHAR(64) NULL; IF COL_LENGTH(N'dbo.EventRegistrationItem', N'TeamIndex') IS NULL ALTER TABLE dbo.EventRegistrationItem ADD TeamIndex INT NULL; - /* 历史 TeamId 仅在单位/创建账号 + 团队名称唯一匹配时回填,歧义数据保持 NULL。 */ + /* 新增列必须通过动态 SQL 引用,避免首次上线时整批预编译报 Invalid column name。 */ + EXEC sys.sp_executesql N' ;WITH TeamCandidates AS ( - SELECT - item.Id AS RegistrationItemId, - team.Id AS TeamId, - COUNT_BIG(1) OVER (PARTITION BY item.Id) AS CandidateCount - FROM dbo.EventRegistrationItem AS item - INNER JOIN dbo.EventRegistration AS registration ON registration.Id = item.RegistrationId - INNER JOIN dbo.Team AS team - ON LTRIM(RTRIM(team.Name)) = LTRIM(RTRIM(registration.TeamName)) - AND ( - (registration.MerchantCertificationId IS NOT NULL - AND team.MerchantCertificationId = registration.MerchantCertificationId) - OR team.CreatedUserId = registration.CreatedUserId - ) - WHERE item.TeamId IS NULL - AND registration.RegistrationMode = 2 - AND NULLIF(LTRIM(RTRIM(registration.TeamName)), N'') IS NOT NULL + SELECT item.Id AS RegistrationItemId,team.Id AS TeamId, + COUNT_BIG(1) OVER (PARTITION BY item.Id) AS CandidateCount + FROM dbo.EventRegistrationItem item + JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId + JOIN dbo.Team team + ON LTRIM(RTRIM(team.Name))=LTRIM(RTRIM(registration.TeamName)) + AND ((registration.MerchantCertificationId IS NOT NULL AND team.MerchantCertificationId=registration.MerchantCertificationId) + OR team.CreatedUserId=registration.CreatedUserId) + WHERE item.TeamId IS NULL AND registration.RegistrationMode=2 + AND NULLIF(LTRIM(RTRIM(registration.TeamName)),N'''') IS NOT NULL ) - UPDATE item - SET item.TeamId = candidate.TeamId - FROM dbo.EventRegistrationItem AS item - INNER JOIN TeamCandidates AS candidate - ON candidate.RegistrationItemId = item.Id - AND candidate.CandidateCount = 1; + UPDATE item SET TeamId=candidate.TeamId + FROM dbo.EventRegistrationItem item + JOIN TeamCandidates candidate ON candidate.RegistrationItemId=item.Id AND candidate.CandidateCount=1; - /* 团队名称为报名快照,优先保留报名主表历史名称。 */ UPDATE item - SET item.TeamName = LEFT(COALESCE( - NULLIF(LTRIM(RTRIM(registration.TeamName)), N''), - team.Name - ), 64) - FROM dbo.EventRegistrationItem AS item - INNER JOIN dbo.EventRegistration AS registration ON registration.Id = item.RegistrationId - LEFT JOIN dbo.Team AS team ON team.Id = item.TeamId - WHERE item.TeamName IS NULL - AND (NULLIF(LTRIM(RTRIM(registration.TeamName)), N'') IS NOT NULL OR team.Id IS NOT NULL); + SET TeamName=LEFT(COALESCE(NULLIF(LTRIM(RTRIM(registration.TeamName)),N''''),team.Name),64) + FROM dbo.EventRegistrationItem item + JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId + LEFT JOIN dbo.Team team ON team.Id=item.TeamId + WHERE item.TeamName IS NULL + AND (NULLIF(LTRIM(RTRIM(registration.TeamName)),N'''') IS NOT NULL OR team.Id IS NOT NULL); - /* 1005=团队速度、1006=团队花样;按原明细创建顺序重建一队、二队序号。 */ ;WITH OrderedTeamItems AS ( - SELECT - item.Id, - ROW_NUMBER() OVER ( - PARTITION BY item.RegistrationId, item.ProjectId, - ISNULL(item.EventProjectGroupId, 0), ISNULL(item.TeamId, 0) - ORDER BY item.CreatedTime, item.Id - ) AS RepairedTeamIndex - FROM dbo.EventRegistrationItem AS item - LEFT JOIN dbo.EventProject AS eventProject ON eventProject.Id = item.ProjectId - LEFT JOIN dbo.Project AS project ON project.Id = eventProject.ProjectId + SELECT item.Id, + ROW_NUMBER() OVER(PARTITION BY item.RegistrationId,item.ProjectId, + ISNULL(item.EventProjectGroupId,0),ISNULL(item.TeamId,0) + ORDER BY item.CreatedTime,item.Id) AS RepairedTeamIndex + FROM dbo.EventRegistrationItem item + LEFT JOIN dbo.EventProject eventProject ON eventProject.Id=item.ProjectId + LEFT JOIN dbo.Project project ON project.Id=eventProject.ProjectId WHERE item.TeamIndex IS NULL - AND (project.ProjectType IN (1005, 1006) OR item.ProjectTypeName LIKE N'%团队%') + AND (project.ProjectType IN(1005,1006) OR item.ProjectTypeName LIKE N''%团队%'') ) - UPDATE item - SET item.TeamIndex = ordered.RepairedTeamIndex - FROM dbo.EventRegistrationItem AS item - INNER JOIN OrderedTeamItems AS ordered ON ordered.Id = item.Id; + UPDATE item SET TeamIndex=ordered.RepairedTeamIndex + FROM dbo.EventRegistrationItem item + JOIN OrderedTeamItems ordered ON ordered.Id=item.Id;'; /* Project 项目:绑定计分规则 ScoreRuleId -> ScoreRule.Id */ IF COL_LENGTH('dbo.Project','ScoreRuleId') IS NULL ALTER TABLE dbo.Project ADD ScoreRuleId BIGINT NULL; -- 项目绑定的计分规则Id(ScoreRule.Id) /* SysUser 扩展为“单位账号”:UnitName 单位名称;UnitPlatform 所属平台 0-系统用户 1-报名平台 2-打分系统,默认0 */ - IF COL_LENGTH('dbo.SysUser','UnitName') IS NULL ALTER TABLE dbo.SysUser ADD UnitName NVARCHAR(128) NULL; -- 单位名称(单位账号扩展) + IF COL_LENGTH('dbo.SysUser','UnitName') IS NULL ALTER TABLE dbo.SysUser ADD UnitName VARCHAR(128) NULL; -- 与测试库一致:单位名称 IF COL_LENGTH('dbo.SysUser','UnitPlatform') IS NULL ALTER TABLE dbo.SysUser ADD UnitPlatform INT NOT NULL CONSTRAINT DF_SysUser_UnitPlatform DEFAULT(0) WITH VALUES; -- 所属平台:0-赛事系统用户,1-报名平台,2-打分系统,默认0 /* EventResult 成绩表:关联场次/出场 SessionId、SessionEntryId */ IF COL_LENGTH('dbo.EventResult','SessionId') IS NULL ALTER TABLE dbo.EventResult ADD SessionId BIGINT NULL; -- 关联比赛场次Id(EventSession.Id) @@ -148,24 +131,32 @@ BEGIN TRY /* 2. 约束、外键和索引(存在则跳过)。 */ PRINT N'[ALTER] 创建约束、外键和索引'; /* CHECK 域值约束。 */ - IF OBJECT_ID('CK_AppUser_MiniProgramRole','C') IS NULL ALTER TABLE dbo.AppUser WITH CHECK ADD CONSTRAINT CK_AppUser_MiniProgramRole CHECK(MiniProgramRole IN(1,2,3)); - IF OBJECT_ID('CK_SysUser_UnitPlatform','C') IS NULL ALTER TABLE dbo.SysUser WITH CHECK ADD CONSTRAINT CK_SysUser_UnitPlatform CHECK(UnitPlatform IN(0,1,2)); + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_AppUser_MiniProgramRole'',N''C'') IS NULL ALTER TABLE dbo.AppUser WITH CHECK ADD CONSTRAINT CK_AppUser_MiniProgramRole CHECK(MiniProgramRole IN(1,2,3));'; + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_SysUser_UnitPlatform'',N''C'') IS NULL ALTER TABLE dbo.SysUser WITH CHECK ADD CONSTRAINT CK_SysUser_UnitPlatform CHECK(UnitPlatform IN(0,1,2));'; IF OBJECT_ID('CK_CheckinTask_CheckinNo','C') IS NULL ALTER TABLE dbo.CheckinTask WITH CHECK ADD CONSTRAINT CK_CheckinTask_CheckinNo CHECK(CheckinNo BETWEEN 1 AND 3 AND TotalRounds BETWEEN 1 AND 3 AND CurrentRound BETWEEN 1 AND 3); IF OBJECT_ID('CK_EventSession_Time','C') IS NULL ALTER TABLE dbo.EventSession WITH CHECK ADD CONSTRAINT CK_EventSession_Time CHECK(EndTime IS NULL OR StartTime IS NULL OR EndTime>=StartTime); IF OBJECT_ID('CK_ScoreRule_Version','C') IS NULL ALTER TABLE dbo.ScoreRule WITH CHECK ADD CONSTRAINT CK_ScoreRule_Version CHECK(RuleVersion>=1); IF OBJECT_ID('CK_EventJudgeScoreSheet_Version','C') IS NULL ALTER TABLE dbo.EventJudgeScoreSheet WITH CHECK ADD CONSTRAINT CK_EventJudgeScoreSheet_Version CHECK(RuleVersion>=1 AND SheetVersion>=1); - IF OBJECT_ID('CK_EventScoreCorrection_Applicant','C') IS NULL ALTER TABLE dbo.EventScoreCorrection WITH CHECK ADD CONSTRAINT CK_EventScoreCorrection_Applicant CHECK((ApplyUserId IS NOT NULL AND ApplyRefereeId IS NULL) OR (ApplyUserId IS NULL AND ApplyRefereeId IS NOT NULL)); - IF OBJECT_ID(N'dbo.CK_EventRegistrationItem_TeamIndex', N'C') IS NULL ALTER TABLE dbo.EventRegistrationItem WITH CHECK ADD CONSTRAINT CK_EventRegistrationItem_TeamIndex CHECK(TeamIndex IS NULL OR TeamIndex>0); - IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem item LEFT JOIN dbo.Team team ON team.Id=item.TeamId WHERE item.TeamId IS NOT NULL AND team.Id IS NULL) THROW 51024,N'EventRegistrationItem 存在无效 TeamId,停止升级。',1; + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.CK_EventScoreCorrection_Applicant'',N''C'') IS NULL ALTER TABLE dbo.EventScoreCorrection WITH CHECK ADD CONSTRAINT CK_EventScoreCorrection_Applicant CHECK((ApplyUserId IS NOT NULL AND ApplyRefereeId IS NULL) OR (ApplyUserId IS NULL AND ApplyRefereeId IS NOT NULL));'; + EXEC sys.sp_executesql N' + IF OBJECT_ID(N''dbo.CK_EventRegistrationItem_TeamIndex'',N''C'') IS NULL + ALTER TABLE dbo.EventRegistrationItem WITH CHECK ADD CONSTRAINT CK_EventRegistrationItem_TeamIndex CHECK(TeamIndex IS NULL OR TeamIndex>0); + IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem item LEFT JOIN dbo.Team team ON team.Id=item.TeamId WHERE item.TeamId IS NOT NULL AND team.Id IS NULL) + THROW 51024,N''EventRegistrationItem 存在无效 TeamId,停止升级。'',1;'; /* 外键:二期表引用一期表及二期表。 */ IF OBJECT_ID(N'dbo.[FK_RefereeApplication_Event]','F') IS NULL ALTER TABLE dbo.[RefereeApplication] WITH CHECK ADD CONSTRAINT [FK_RefereeApplication_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); IF OBJECT_ID(N'dbo.[FK_RefereeApplication_AppUser]','F') IS NULL ALTER TABLE dbo.[RefereeApplication] WITH CHECK ADD CONSTRAINT [FK_RefereeApplication_AppUser] FOREIGN KEY([RefereeUserId]) REFERENCES dbo.[AppUser]([Id]); IF OBJECT_ID(N'dbo.[FK_CheckinTask_Event]','F') IS NULL ALTER TABLE dbo.[CheckinTask] WITH CHECK ADD CONSTRAINT [FK_CheckinTask_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); IF OBJECT_ID(N'dbo.[FK_CheckinRecord_Task]','F') IS NULL ALTER TABLE dbo.[CheckinRecord] WITH CHECK ADD CONSTRAINT [FK_CheckinRecord_Task] FOREIGN KEY([TaskId]) REFERENCES dbo.[CheckinTask]([Id]); - IF OBJECT_ID(N'dbo.[FK_EventRegistrationItem_Team]','F') IS NULL ALTER TABLE dbo.[EventRegistrationItem] WITH CHECK ADD CONSTRAINT [FK_EventRegistrationItem_Team] FOREIGN KEY([TeamId]) REFERENCES dbo.[Team]([Id]); - IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventRegistrationItem]') AND name=N'IX_EventRegistrationItem_RegistrationId_TeamId') CREATE NONCLUSTERED INDEX [IX_EventRegistrationItem_RegistrationId_TeamId] ON dbo.[EventRegistrationItem]([RegistrationId],[TeamId]) INCLUDE([EventProjectGroupId],[TeamIndex]) WHERE [TeamId] IS NOT NULL; - IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0 GROUP BY RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex HAVING COUNT_BIG(1)>1) THROW 51025,N'EventRegistrationItem 存在重复的来源团队队伍序号,停止创建唯一索引。',1; - IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventRegistrationItem]') AND name=N'UX_EventRegistrationItem_SourceTeamSquad_Active') CREATE UNIQUE NONCLUSTERED INDEX [UX_EventRegistrationItem_SourceTeamSquad_Active] ON dbo.[EventRegistrationItem]([RegistrationId],[ProjectId],[EventProjectGroupId],[TeamId],[TeamIndex]) WHERE [TeamId] IS NOT NULL AND [TeamIndex] IS NOT NULL AND [DeleteMark]=0; + EXEC sys.sp_executesql N' + IF OBJECT_ID(N''dbo.FK_EventRegistrationItem_Team'',N''F'') IS NULL + ALTER TABLE dbo.EventRegistrationItem WITH CHECK ADD CONSTRAINT FK_EventRegistrationItem_Team FOREIGN KEY(TeamId) REFERENCES dbo.Team(Id); + IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N''dbo.EventRegistrationItem'') AND name=N''IX_EventRegistrationItem_RegistrationId_TeamId'') + CREATE NONCLUSTERED INDEX IX_EventRegistrationItem_RegistrationId_TeamId ON dbo.EventRegistrationItem(RegistrationId,TeamId) INCLUDE(EventProjectGroupId,TeamIndex) WHERE TeamId IS NOT NULL; + IF EXISTS(SELECT 1 FROM dbo.EventRegistrationItem WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0 GROUP BY RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex HAVING COUNT_BIG(1)>1) + THROW 51025,N''EventRegistrationItem 存在重复的来源团队队伍序号,停止创建唯一索引。'',1; + IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N''dbo.EventRegistrationItem'') AND name=N''UX_EventRegistrationItem_SourceTeamSquad_Active'') + CREATE UNIQUE NONCLUSTERED INDEX UX_EventRegistrationItem_SourceTeamSquad_Active ON dbo.EventRegistrationItem(RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex) WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0;'; IF OBJECT_ID(N'dbo.[FK_Referee_AppUser]','F') IS NULL ALTER TABLE dbo.[Referee] WITH CHECK ADD CONSTRAINT [FK_Referee_AppUser] FOREIGN KEY([AppUserId]) REFERENCES dbo.[AppUser]([Id]); IF OBJECT_ID(N'dbo.[FK_EventReferee_Event]','F') IS NULL ALTER TABLE dbo.[EventReferee] WITH CHECK ADD CONSTRAINT [FK_EventReferee_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); IF OBJECT_ID(N'dbo.[FK_EventReferee_Referee]','F') IS NULL ALTER TABLE dbo.[EventReferee] WITH CHECK ADD CONSTRAINT [FK_EventReferee_Referee] FOREIGN KEY([RefereeId]) REFERENCES dbo.[Referee]([Id]); @@ -189,7 +180,7 @@ BEGIN TRY IF OBJECT_ID(N'dbo.[FK_EventResultVersion_Rule]','F') IS NULL ALTER TABLE dbo.[EventResultVersion] WITH CHECK ADD CONSTRAINT [FK_EventResultVersion_Rule] FOREIGN KEY([ScoreRuleId]) REFERENCES dbo.[ScoreRule]([Id]); IF OBJECT_ID(N'dbo.[FK_EventScoreCorrection_Entry]','F') IS NULL ALTER TABLE dbo.[EventScoreCorrection] WITH CHECK ADD CONSTRAINT [FK_EventScoreCorrection_Entry] FOREIGN KEY([SessionEntryId]) REFERENCES dbo.[EventSessionEntry]([Id]); IF OBJECT_ID(N'dbo.[FK_EventScoreCorrection_OriginalSheet]','F') IS NULL ALTER TABLE dbo.[EventScoreCorrection] WITH CHECK ADD CONSTRAINT [FK_EventScoreCorrection_OriginalSheet] FOREIGN KEY([OriginalScoreSheetId]) REFERENCES dbo.[EventJudgeScoreSheet]([Id]); - IF OBJECT_ID(N'dbo.[FK_EventScoreCorrection_ApplyReferee]','F') IS NULL ALTER TABLE dbo.[EventScoreCorrection] WITH CHECK ADD CONSTRAINT [FK_EventScoreCorrection_ApplyReferee] FOREIGN KEY([ApplyRefereeId]) REFERENCES dbo.[Referee]([Id]); + EXEC sys.sp_executesql N'IF OBJECT_ID(N''dbo.FK_EventScoreCorrection_ApplyReferee'',N''F'') IS NULL ALTER TABLE dbo.EventScoreCorrection WITH CHECK ADD CONSTRAINT FK_EventScoreCorrection_ApplyReferee FOREIGN KEY(ApplyRefereeId) REFERENCES dbo.Referee(Id);'; IF OBJECT_ID(N'dbo.[FK_EventResultScreenCast_Event]','F') IS NULL ALTER TABLE dbo.[EventResultScreenCast] WITH CHECK ADD CONSTRAINT [FK_EventResultScreenCast_Event] FOREIGN KEY([EventId]) REFERENCES dbo.[EventInfo]([Id]); /* 索引:UX_ 唯一索引,IX_ 非聚集索引。 */ IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[Referee]') AND name=N'UX_Referee_Mobile_Active') CREATE UNIQUE NONCLUSTERED INDEX [UX_Referee_Mobile_Active] ON dbo.[Referee]([Mobile]) WHERE [DeleteMark]=0; @@ -220,12 +211,45 @@ BEGIN TRY IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventJudgeScoreAttachment]') AND name=N'UX_EventJudgeScoreAttachment_Current') CREATE UNIQUE NONCLUSTERED INDEX [UX_EventJudgeScoreAttachment_Current] ON dbo.[EventJudgeScoreAttachment]([ScoreSheetId],[AttachmentType]) WHERE [IsCurrent]=1 AND [DeleteMark]=0; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventJudgeScoreDetail]') AND name=N'IX_EventJudgeScoreDetail_Sheet') CREATE NONCLUSTERED INDEX [IX_EventJudgeScoreDetail_Sheet] ON dbo.[EventJudgeScoreDetail]([ScoreSheetId],[Sort]); /* 集体项目按队员分别保存成绩;旧版仅以 SessionEntryId 唯一会导致第二名队员写入失败。 */ - IF EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResult]') AND name=N'UX_EventResult_SessionEntry_Active' - AND (INDEX_COL(N'dbo.EventResult',N'UX_EventResult_SessionEntry_Active',1)<>N'SessionEntryId' - OR ISNULL(INDEX_COL(N'dbo.EventResult',N'UX_EventResult_SessionEntry_Active',2),N'')<>N'RegistrationPersonId')) + IF EXISTS( + SELECT 1 + FROM sys.indexes indexInfo + WHERE indexInfo.object_id=OBJECT_ID(N'dbo.[EventResult]') + AND indexInfo.name=N'UX_EventResult_SessionEntry_Active' + AND ( + NOT EXISTS( + SELECT 1 + FROM sys.index_columns indexColumn + JOIN sys.columns columnInfo + ON columnInfo.object_id=indexColumn.object_id + AND columnInfo.column_id=indexColumn.column_id + WHERE indexColumn.object_id=indexInfo.object_id + AND indexColumn.index_id=indexInfo.index_id + AND indexColumn.key_ordinal=1 + AND columnInfo.name=N'SessionEntryId' + ) + OR NOT EXISTS( + SELECT 1 + FROM sys.index_columns indexColumn + JOIN sys.columns columnInfo + ON columnInfo.object_id=indexColumn.object_id + AND columnInfo.column_id=indexColumn.column_id + WHERE indexColumn.object_id=indexInfo.object_id + AND indexColumn.index_id=indexInfo.index_id + AND indexColumn.key_ordinal=2 + AND columnInfo.name=N'RegistrationPersonId' + ) + OR EXISTS( + SELECT 1 + FROM sys.index_columns indexColumn + WHERE indexColumn.object_id=indexInfo.object_id + AND indexColumn.index_id=indexInfo.index_id + AND indexColumn.key_ordinal>2 + ) + ) + ) DROP INDEX [UX_EventResult_SessionEntry_Active] ON dbo.[EventResult]; - IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResult]') AND name=N'UX_EventResult_SessionEntry_Active') - CREATE UNIQUE NONCLUSTERED INDEX [UX_EventResult_SessionEntry_Active] ON dbo.[EventResult]([SessionEntryId],[RegistrationPersonId]) WHERE [SessionEntryId] IS NOT NULL AND [DeleteMark]=0; + EXEC sys.sp_executesql N'IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N''dbo.EventResult'') AND name=N''UX_EventResult_SessionEntry_Active'') CREATE UNIQUE NONCLUSTERED INDEX UX_EventResult_SessionEntry_Active ON dbo.EventResult(SessionEntryId,RegistrationPersonId) WHERE SessionEntryId IS NOT NULL AND DeleteMark=0;'; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResultVersion]') AND name=N'UX_EventResultVersion_Result_Version') CREATE UNIQUE NONCLUSTERED INDEX [UX_EventResultVersion_Result_Version] ON dbo.[EventResultVersion]([EventResultId],[ResultVersion]) WHERE [DeleteMark]=0; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventJudgeMessage]') AND name=N'IX_EventJudgeMessage_Receiver_Unread') CREATE NONCLUSTERED INDEX [IX_EventJudgeMessage_Receiver_Unread] ON dbo.[EventJudgeMessage]([ReceiverUserId],[IsRead],[CreatedTime]) WHERE [DeleteMark]=0; IF NOT EXISTS(SELECT 1 FROM sys.indexes WHERE object_id=OBJECT_ID(N'dbo.[EventResultScreenCast]') AND name=N'IX_EventResultScreenCast_Event_Time') CREATE NONCLUSTERED INDEX [IX_EventResultScreenCast_Event_Time] ON dbo.[EventResultScreenCast]([EventId],[CastTime]) WHERE [DeleteMark]=0; @@ -338,30 +362,25 @@ SELECT r.RuleCode,COUNT(i.Id) AS ItemCount FROM dbo.ScoreRule r LEFT JOIN dbo.Sc PRINT N'二期 ALTER 脚本执行成功。'; /* 多团队报名升级结果:未匹配记录允许保留为空,但上线前必须人工核对。 */ - SELECT - item.Id AS RegistrationItemId, - item.RegistrationId, - registration.TeamName AS HistoricalTeamName, - registration.MerchantCertificationId, - registration.CreatedUserId, - item.ProjectName, - item.GroupName, - item.TeamIndex - FROM dbo.EventRegistrationItem item - INNER JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId - WHERE item.TeamId IS NULL AND registration.RegistrationMode=2 AND item.DeleteMark=0 - ORDER BY item.RegistrationId,item.ProjectId,item.Id; + EXEC sys.sp_executesql N' + SELECT item.Id AS RegistrationItemId,item.RegistrationId,registration.TeamName AS HistoricalTeamName, + registration.MerchantCertificationId,registration.CreatedUserId,item.ProjectName,item.GroupName,item.TeamIndex + FROM dbo.EventRegistrationItem item + JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId + WHERE item.TeamId IS NULL AND registration.RegistrationMode=2 AND item.DeleteMark=0 + ORDER BY item.RegistrationId,item.ProjectId,item.Id; SELECT (SELECT COUNT_BIG(1) FROM dbo.EventRegistrationItem item LEFT JOIN dbo.Team team ON team.Id=item.TeamId WHERE item.TeamId IS NOT NULL AND team.Id IS NULL) AS InvalidTeamIdCount, (SELECT COUNT_BIG(1) FROM dbo.EventRegistrationItem WHERE TeamIndex IS NOT NULL AND TeamIndex<=0) AS InvalidTeamIndexCount, + (SELECT COUNT_BIG(1) FROM dbo.EventRegistrationItem item JOIN dbo.EventRegistration registration ON registration.Id=item.RegistrationId WHERE item.TeamId IS NULL AND registration.RegistrationMode=2 AND item.DeleteMark=0) AS UnmatchedTeamCount, (SELECT COUNT_BIG(1) FROM ( SELECT RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex - FROM dbo.EventRegistrationItem - WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0 - GROUP BY RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex + FROM dbo.EventRegistrationItem + WHERE TeamId IS NOT NULL AND TeamIndex IS NOT NULL AND DeleteMark=0 + GROUP BY RegistrationId,ProjectId,EventProjectGroupId,TeamId,TeamIndex HAVING COUNT_BIG(1)>1 - ) duplicateItems) AS DuplicateSquadCount; + ) duplicateItems) AS DuplicateSquadCount;'; END TRY BEGIN CATCH DECLARE @ErrorNumber INT=ERROR_NUMBER(),@ErrorLine INT=ERROR_LINE(),@ErrorMessage NVARCHAR(4000)=ERROR_MESSAGE(); diff --git a/二期需求/上线/dbo_insert.sql b/二期需求/上线/dbo_insert.sql index e36dd0e..402bf32 100644 --- a/二期需求/上线/dbo_insert.sql +++ b/二期需求/上线/dbo_insert.sql @@ -1,4 +1,4 @@ -/* 二期上线 3/3:同步种子数据并校验。可重复执行,失败自动回滚。 */ +/* 二期上线 3/3:初始化数据和最终校验。可重复执行,失败自动回滚。 */ SET NOCOUNT ON; SET XACT_ABORT ON; @@ -9,28 +9,22 @@ BEGIN TRY BEGIN TRANSACTION; DECLARE @LockResult INT; EXEC @LockResult=sys.sp_getapplock @Resource=N'YD_Event_Phase2_Production_Deployment',@LockMode='Exclusive',@LockOwner='Transaction',@LockTimeout=10000; - IF @LockResult<0 THROW 51002,N'无法取得二期部署排他锁,可能有另一个部署正在执行。',1; + IF @LockResult<0 RAISERROR(N'无法取得二期部署排他锁,可能有另一个部署正在执行。',16,1); /* 存在则更新,缺失才插入。 */ PRINT N'[INSERT] 同步计分规则、评分项、角色和菜单'; /* 1. 计分规则(8 条,按 RuleCode 同步)。 */ CREATE TABLE #RuleSeed(SourceId BIGINT PRIMARY KEY,RuleCode NVARCHAR(64),RuleName NVARCHAR(128),JudgeRoleSchemaJson NVARCHAR(2000),RuleConfigJson NVARCHAR(4000),RuleVersion INT,Status INT,Sort INT,DeleteMark BIT,CreatedUserId BIGINT,CreatedTime DATETIME2(3)); - INSERT #RuleSeed VALUES (3000,N'ROPE_PRESCRIBED',N'规定赛',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判","min":1,"max":1}]},{"title":"创意编排裁判","slots":[{"code":"CJ","name":"创意编排裁判","min":1,"max":3}]},{"title":"完成质量裁判","slots":[{"code":"CQ","name":"完成质量裁判","min":1,"max":3}]}]',N'{"ruleType":"PRESCRIBED","baseScore":100,"scoreDecimals":2,"deductionUnit":5,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"CJ","symbol":"T1","label":"创意分","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1},{"roleType":"CQ","symbol":"T2","label":"完成分","sourceField":"RequiredScore","targetField":"RequiredScore","aggregate":"avg","sign":1},{"roleType":"T","symbol":"T3","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1}],"tieBreakers":["TotalScore","RequiredScore","PerformanceScore"]}',1,0,1,0,1000,N'2026-08-19T00:00:00'), - (3100,N'ROPE_FREESTYLE_SINGLE',N'个人花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_SINGLE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,2,0,1000,N'2026-08-19T00:00:00'), - (3200,N'ROPE_FREESTYLE_DOUBLE_SYNC',N'两人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_DOUBLE_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,3,0,1000,N'2026-08-19T00:00:00'), - (3300,N'ROPE_FREESTYLE_QUAD_SYNC',N'四人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_QUAD_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,4,0,1000,N'2026-08-19T00:00:00'), - (3400,N'ROPE_FREESTYLE_WHEEL_PAIR',N'两人车轮跳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DA","name":"难度裁判-DA(运动员A难度裁判)","min":1,"max":2},{"code":"DB","name":"难度裁判-DB(运动员B难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WHEEL","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DA","symbol":"dA","label":"运动员A难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DB","symbol":"dB","label":"运动员B难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,5,0,1000,N'2026-08-19T00:00:00'), - (3500,N'ROPE_FREESTYLE_WIRE_TRIPLE',N'三人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',1,0,6,0,1000,N'2026-08-19T00:00:00'), - (3600,N'ROPE_FREESTYLE_WIRE_QUAD',N'四人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',1,0,7,0,1000,N'2026-08-19T00:00:00'), - (3700,N'ROPE_SHOWCASE',N'表演赛(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (长绳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}]',N'{"ruleType":"SHOWCASE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DGA","symbol":"A","label":"A组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DGB","symbol":"B","label":"B组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',1,0,8,0,1000,N'2026-08-19T00:00:00'); + INSERT #RuleSeed VALUES (3000,N'ROPE_PRESCRIBED',N'规定赛',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判","min":1,"max":1}]},{"title":"创意编排裁判","slots":[{"code":"CJ","name":"创意编排裁判","min":1,"max":3}]},{"title":"完成质量裁判","slots":[{"code":"CQ","name":"完成质量裁判","min":1,"max":3}]}]',N'{"ruleType":"PRESCRIBED","baseScore":100,"scoreDecimals":2,"deductionUnit":5,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"CJ","symbol":"T1","label":"创意分","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1},{"roleType":"CQ","symbol":"T2","label":"完成分","sourceField":"RequiredScore","targetField":"RequiredScore","aggregate":"avg","sign":1},{"roleType":"T","symbol":"T3","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1}],"tieBreakers":["TotalScore","RequiredScore","PerformanceScore"]}',5,0,1,0,1000,N'2026-08-19T00:00:00'), + (3100,N'ROPE_FREESTYLE_SINGLE',N'个人花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_SINGLE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',6,0,2,0,1000,N'2026-08-19T00:00:00'), + (3200,N'ROPE_FREESTYLE_DOUBLE_SYNC',N'两人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_DOUBLE_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1},{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","sign":1,"factor":"Q","factorWeight":0.025}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',6,0,3,0,1000,N'2026-08-19T00:00:00'), + (3300,N'ROPE_FREESTYLE_QUAD_SYNC',N'四人同步花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DP","name":"难度裁判-DP(力量体操裁判)","min":1,"max":2},{"code":"DM","name":"难度裁判-DM(多摇裁判)","min":1,"max":2},{"code":"DR","name":"难度裁判-DR(绳子运用裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_QUAD_SYNC","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":3,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DP","symbol":"dDP","label":"力量体操难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DM","symbol":"dDM","label":"多摇难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DR","symbol":"dDR","label":"绳子运用难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DP","symbol":"qP","label":"力量体操规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DM","symbol":"qM","label":"多摇规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"DR","symbol":"qR","label":"绳子运用规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","aggregateDecimals":0,"sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1},{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","sign":1,"factor":"Q","factorWeight":0.025}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',6,0,4,0,1000,N'2026-08-19T00:00:00'), + (3400,N'ROPE_FREESTYLE_WHEEL_PAIR',N'两人车轮跳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DA","name":"难度裁判-DA(运动员A难度裁判)","min":1,"max":2},{"code":"DB","name":"难度裁判-DB(运动员B难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WHEEL","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DA","symbol":"dA","label":"运动员A难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DB","symbol":"dB","label":"运动员B难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.025},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',5,0,5,0,1000,N'2026-08-19T00:00:00'), + (3500,N'ROPE_FREESTYLE_WIRE_TRIPLE',N'三人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',5,0,6,0,1000,N'2026-08-19T00:00:00'), + (3600,N'ROPE_FREESTYLE_WIRE_QUAD',N'四人交互绳花样(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DJ","name":"难度裁判-DJ(跳绳运动员难度裁判)","min":1,"max":2},{"code":"DT","name":"难度裁判-DT(摇绳运动员难度裁判)","min":1,"max":2}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":2}]}]',N'{"ruleType":"FREESTYLE_WIRE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":1,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DJ","symbol":"dJ","label":"跳绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1.4},{"roleType":"DT","symbol":"dT","label":"摇绳运动员难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.033},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","PerformanceScore","DifficultyScore"]}',5,0,7,0,1000,N'2026-08-19T00:00:00'), + (3700,N'ROPE_SHOWCASE',N'表演赛(精英级)',N'[{"title":"主裁判","slots":[{"code":"T","name":"主裁判-T","min":1,"max":1}]},{"title":"难度裁判","slots":[{"code":"DGA","name":"难度裁判-A组裁判","min":1,"max":3,"categories":["DP+DM (个人绳)","DA (车轮跳)","DT (交互绳)","DT (旅行跳)"]},{"code":"DGB","name":"难度裁判-B组裁判","min":1,"max":3,"categories":["DR (个人绳)","DB (车轮跳)","DJ (交互绳)","DL (长绳)"]}]},{"title":"表现裁判","slots":[{"code":"P","name":"表现裁判-P","min":1,"max":3}]}]',N'{"ruleType":"SHOWCASE","totalMode":"factor","baseScore":0,"scoreDecimals":2,"difficultyDivisor":2,"correctionNeedApproval":false,"roleAggregations":[{"roleType":"DGA","symbol":"A","label":"A组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"DGB","symbol":"B","label":"B组难度","sourceField":"DifficultyScore","targetField":"DifficultyScore","aggregate":"avg","sign":1,"factor":"D","factorWeight":1},{"roleType":"P","symbol":"P","label":"表现","sourceField":"PerformanceScore","targetField":"PerformanceScore","aggregate":"avg","sign":1,"factor":"P","factorWeight":0.05},{"roleType":"T","symbol":"Q","label":"规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"max","sign":1,"factor":"Q","factorWeight":0.05},{"roleType":"T","symbol":"M","label":"扣分","sourceField":"DeductionScore","targetField":"DeductionScore","aggregate":"sum","sign":-1,"factor":"M","factorWeight":1}],"tieBreakers":["TotalScore","-DeductionScore","RequiredScore","PerformanceScore","DifficultyScore"]}',5,0,8,0,1000,N'2026-08-19T00:00:00'); - -- 两人/四人同步花样由主裁录入互动配合,缺失数 qI 与 DP/DM/DR 一同参与 Q。 - UPDATE #RuleSeed - SET RuleConfigJson=JSON_MODIFY( - RuleConfigJson, - N'append $.roleAggregations', - JSON_QUERY(N'{"roleType":"T","symbol":"qI","label":"互动配合规定元素缺失","sourceField":"RequiredMissingCount","targetField":"RequiredScore","aggregate":"avg","sign":1,"factor":"Q","factorWeight":0.025}')) - WHERE RuleCode IN (N'ROPE_FREESTYLE_DOUBLE_SYNC',N'ROPE_FREESTYLE_QUAD_SYNC'); + /* 规则版本和互动配合聚合已直接固化在种子行,避免上线时二次改写临时表。 */ UPDATE r SET RuleName=s.RuleName,JudgeRoleSchemaJson=s.JudgeRoleSchemaJson,RuleConfigJson=s.RuleConfigJson, RuleVersion=s.RuleVersion,Status=s.Status,Sort=s.Sort,DeleteMark=0,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() @@ -42,7 +36,7 @@ BEGIN TRY FROM #RuleSeed s WHERE NOT EXISTS(SELECT 1 FROM dbo.ScoreRule r WHERE r.RuleCode=s.RuleCode AND r.DeleteMark=0) AND NOT EXISTS(SELECT 1 FROM dbo.ScoreRule r WHERE r.Id=s.SourceId); IF EXISTS(SELECT 1 FROM #RuleSeed s WHERE NOT EXISTS(SELECT 1 FROM dbo.ScoreRule r WHERE r.RuleCode=s.RuleCode AND r.DeleteMark=0)) - THROW 51003,N'计分规则种子ID被占用且规则编码不存在,无法安全初始化。',1; + RAISERROR(N'计分规则种子ID被占用且规则编码不存在,无法安全初始化。',16,1); /* 源 Id 映射到目标库实际规则 Id。 */ CREATE TABLE #RuleMap(SourceId BIGINT PRIMARY KEY,TargetId BIGINT NOT NULL); @@ -346,33 +340,33 @@ BEGIN TRY (3518,3500,N'DT',N'DIFF_LEVEL_1',N'1 级',1,NULL,1.5000,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',18,0,1000,N'2026-08-19T00:00:00'), (3519,3500,N'DT',N'DIFF_LEVEL_1_PLUS',N'1+ 级',1,NULL,1.8371,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',19,0,1000,N'2026-08-19T00:00:00'), (3520,3500,N'DT',N'DIFF_LEVEL_2_MINUS',N'2- 级',1,NULL,2.0331,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',20,0,1000,N'2026-08-19T00:00:00'), - (3521,3500,N'P',N'MUSIC_PLUS',N'音乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":1}',21,0,1000,N'2026-08-19T00:00:00'), - (3522,3500,N'P',N'MUSIC_MINUS',N'音乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":-1}',22,0,1000,N'2026-08-19T00:00:00'), - (3523,3500,N'P',N'MUSIC_SCORE',N'音乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"MUSIC","dimensionWeight":0.20,"baseValue":12.0}',23,0,1000,N'2026-08-19T00:00:00'), - (3524,3500,N'P',N'QUALITY_PLUS',N'完成质量(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":1}',24,0,1000,N'2026-08-19T00:00:00'), - (3525,3500,N'P',N'QUALITY_MINUS',N'完成质量(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":-1}',25,0,1000,N'2026-08-19T00:00:00'), - (3526,3500,N'P',N'QUALITY_SCORE',N'完成质量',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"QUALITY","dimensionWeight":0.25,"baseValue":12.0}',26,0,1000,N'2026-08-19T00:00:00'), - (3527,3500,N'P',N'ENTERTAINMENT_PLUS',N'娱乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":1}',27,0,1000,N'2026-08-19T00:00:00'), - (3528,3500,N'P',N'ENTERTAINMENT_MINUS',N'娱乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":-1}',28,0,1000,N'2026-08-19T00:00:00'), - (3529,3500,N'P',N'ENTERTAINMENT_SCORE',N'娱乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"ENTERTAINMENT","dimensionWeight":0.25,"baseValue":12.0}',29,0,1000,N'2026-08-19T00:00:00'), - (3530,3500,N'P',N'CREATIVITY_PLUS',N'创意(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":1}',30,0,1000,N'2026-08-19T00:00:00'), - (3531,3500,N'P',N'CREATIVITY_MINUS',N'创意(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":-1}',31,0,1000,N'2026-08-19T00:00:00'), - (3532,3500,N'P',N'CREATIVITY_SCORE',N'创意',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"CREATIVITY","dimensionWeight":0.15,"baseValue":12.0}',32,0,1000,N'2026-08-19T00:00:00'), - (3533,3500,N'P',N'VARIETY_PLUS',N'多样性(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":1}',33,0,1000,N'2026-08-19T00:00:00'), - (3534,3500,N'P',N'VARIETY_MINUS',N'多样性(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":-1}',34,0,1000,N'2026-08-19T00:00:00'), - (3535,3500,N'P',N'VARIETY_SCORE',N'多样性',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"VARIETY","dimensionWeight":0.15,"baseValue":12.0}',35,0,1000,N'2026-08-19T00:00:00'), - (3536,3500,N'P',N'FAILURE_COUNT',N'失误次数',3,NULL,1,0,50,1,0,0,0,0,N'{"inputMode":"count","unitLabel":"次","isFailureCount":true,"remark":"表现裁判记一次失误,其对应的表现五个方面(音乐,完成质量,创意,娱乐和多样性)减数量+1"}',36,0,1000,N'2026-08-19T00:00:00'), - (3537,3500,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次","stepDeductions":[0.05,0.075,0.1],"remark":"第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',37,0,1000,N'2026-08-19T00:00:00'), - (3538,3500,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',38,0,1000,N'2026-08-19T00:00:00'), - (3539,3500,N'T',N'T_SPACE_VIOLATION',N'空间违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',39,0,1000,N'2026-08-19T00:00:00'), - (3540,3500,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,40,0,1000,N'2026-08-19T00:00:00'), - (3541,3500,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,41,0,1000,N'2026-08-19T00:00:00'), - (3542,3500,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,42,0,1000,N'2026-08-19T00:00:00'), - (3543,3500,N'T',N'DQ_EXTERNAL_AID',N'使用外部助力器材',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,43,0,1000,N'2026-08-19T00:00:00'), - (3544,3500,N'T',N'DQ_UNCIVILIZED',N'比赛中嚼口香糖/不文明用语等',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,44,0,1000,N'2026-08-19T00:00:00'), - (3545,3500,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,45,0,1000,N'2026-08-19T00:00:00'), - (3546,3500,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,46,0,1000,N'2026-08-19T00:00:00'), - (3547,3500,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,47,0,1000,N'2026-08-19T00:00:00'), + (3521,3500,N'P',N'MUSIC_PLUS',N'音乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":1}',32,0,1000,N'2026-08-19T00:00:00'), + (3522,3500,N'P',N'MUSIC_MINUS',N'音乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"MUSIC","adjustSign":-1}',33,0,1000,N'2026-08-19T00:00:00'), + (3523,3500,N'P',N'MUSIC_SCORE',N'音乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"MUSIC","dimensionWeight":0.20,"baseValue":12.0}',34,0,1000,N'2026-08-19T00:00:00'), + (3524,3500,N'P',N'QUALITY_PLUS',N'完成质量(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":1}',35,0,1000,N'2026-08-19T00:00:00'), + (3525,3500,N'P',N'QUALITY_MINUS',N'完成质量(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"QUALITY","adjustSign":-1}',36,0,1000,N'2026-08-19T00:00:00'), + (3526,3500,N'P',N'QUALITY_SCORE',N'完成质量',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"QUALITY","dimensionWeight":0.25,"baseValue":12.0}',37,0,1000,N'2026-08-19T00:00:00'), + (3527,3500,N'P',N'ENTERTAINMENT_PLUS',N'娱乐(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":1}',38,0,1000,N'2026-08-19T00:00:00'), + (3528,3500,N'P',N'ENTERTAINMENT_MINUS',N'娱乐(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"ENTERTAINMENT","adjustSign":-1}',39,0,1000,N'2026-08-19T00:00:00'), + (3529,3500,N'P',N'ENTERTAINMENT_SCORE',N'娱乐',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"ENTERTAINMENT","dimensionWeight":0.25,"baseValue":12.0}',40,0,1000,N'2026-08-19T00:00:00'), + (3530,3500,N'P',N'CREATIVITY_PLUS',N'创意(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":1}',41,0,1000,N'2026-08-19T00:00:00'), + (3531,3500,N'P',N'CREATIVITY_MINUS',N'创意(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"CREATIVITY","adjustSign":-1}',42,0,1000,N'2026-08-19T00:00:00'), + (3532,3500,N'P',N'CREATIVITY_SCORE',N'创意',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"CREATIVITY","dimensionWeight":0.15,"baseValue":12.0}',43,0,1000,N'2026-08-19T00:00:00'), + (3533,3500,N'P',N'VARIETY_PLUS',N'多样性(加数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":1}',44,0,1000,N'2026-08-19T00:00:00'), + (3534,3500,N'P',N'VARIETY_MINUS',N'多样性(减数量)',3,NULL,1,0,50,1,0,0,2,0,N'{"inputMode":"count","unitLabel":"次","dimensionCode":"VARIETY","adjustSign":-1}',45,0,1000,N'2026-08-19T00:00:00'), + (3535,3500,N'P',N'VARIETY_SCORE',N'多样性',3,NULL,1,0,24,1,12,1,2,0,N'{"inputMode":"score","isAuto":true,"dimensionCode":"VARIETY","dimensionWeight":0.15,"baseValue":12.0}',46,0,1000,N'2026-08-19T00:00:00'), + (3536,3500,N'P',N'FAILURE_COUNT',N'失误次数',3,NULL,1,0,50,1,0,0,0,0,N'{"inputMode":"count","unitLabel":"次","isFailureCount":true,"remark":"表现裁判记一次失误,其对应的表现五个方面(音乐,完成质量,创意,娱乐和多样性)减数量+1"}',47,0,1000,N'2026-08-19T00:00:00'), + (3537,3500,N'T',N'T_FAILURE',N'失误',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次","stepDeductions":[0.05,0.075,0.1],"remark":"第1次扣0.05,第2次扣0.075,第3次起每次扣0.1"}',50,0,1000,N'2026-08-19T00:00:00'), + (3538,3500,N'T',N'T_VIOLATION',N'违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',48,0,1000,N'2026-08-19T00:00:00'), + (3539,3500,N'T',N'T_SPACE_VIOLATION',N'空间违例',4,NULL,0.05,0,50,1,0,0,4,0,N'{"inputMode":"count","unitLabel":"次"}',49,0,1000,N'2026-08-19T00:00:00'), + (3540,3500,N'T',N'DQ_DISCIPLINE',N'违反赛场纪律',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,51,0,1000,N'2026-08-19T00:00:00'), + (3541,3500,N'T',N'DQ_MEMBER_COUNT',N'参赛人员不符合规定(不足或超过)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,52,0,1000,N'2026-08-19T00:00:00'), + (3542,3500,N'T',N'DQ_NO_ROPE_SHOES',N'未穿跳绳鞋',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,53,0,1000,N'2026-08-19T00:00:00'), + (3543,3500,N'T',N'DQ_EXTERNAL_AID',N'使用外部助力器材',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,54,0,1000,N'2026-08-19T00:00:00'), + (3544,3500,N'T',N'DQ_UNCIVILIZED',N'比赛中嚼口香糖/不文明用语等',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,55,0,1000,N'2026-08-19T00:00:00'), + (3545,3500,N'T',N'DQ_ANTI_OLYMPIC',N'有悖奥林匹克精神的元素(描绘暴力、战争、宗教、色情有关的元素)',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,56,0,1000,N'2026-08-19T00:00:00'), + (3546,3500,N'T',N'DQ_LATE_60S',N'运动员(队)被叫超过60秒未上场',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,57,0,1000,N'2026-08-19T00:00:00'), + (3547,3500,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,58,0,1000,N'2026-08-19T00:00:00'), (3548,3500,N'DT',N'DIFF_LEVEL_2',N'2 级',1,NULL,2.2500,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',21,0,1000,N'2026-08-19T00:00:00'), (3549,3500,N'DT',N'DIFF_LEVEL_2_PLUS',N'2+ 级',1,NULL,2.7557,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',22,0,1000,N'2026-08-19T00:00:00'), (3550,3500,N'DT',N'DIFF_LEVEL_3_MINUS',N'3- 级',1,NULL,3.0497,0,50,1,0,0,1,0,N'{"inputMode":"count","unitLabel":"个","difficultyAggregate":"top","difficultyTopCount":20}',23,0,1000,N'2026-08-19T00:00:00'), @@ -556,6 +550,8 @@ BEGIN TRY (3812,3700,N'T',N'DQ_TATTOO',N'显露纹身',5,NULL,NULL,NULL,NULL,NULL,NULL,2,0,0,NULL,112,0,1000,N'2026-08-19T00:00:00'); + /* 三人交互绳评分项顺序已直接固化为测试库基线 32-58。 */ + UPDATE i SET ItemName=s.ItemName,ItemType=s.ItemType,ParentItemCode=s.ParentItemCode,UnitValue=s.UnitValue,MinValue=s.MinValue, MaxValue=s.MaxValue,StepValue=s.StepValue,DefaultValue=s.DefaultValue,CalcMode=s.CalcMode,ScoreDimension=s.ScoreDimension, IsRequired=s.IsRequired,ExtensionJson=s.ExtensionJson,Sort=s.Sort,DeleteMark=s.DeleteMark,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() @@ -569,7 +565,7 @@ BEGIN TRY WHERE NOT EXISTS(SELECT 1 FROM dbo.ScoreRuleItem i WHERE i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode) AND NOT EXISTS(SELECT 1 FROM dbo.ScoreRuleItem i WHERE i.Id=s.Id); IF EXISTS(SELECT 1 FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId WHERE NOT EXISTS(SELECT 1 FROM dbo.ScoreRuleItem i WHERE i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=s.DeleteMark)) - THROW 51004,N'计分规则明细种子ID被占用且业务键不存在,无法安全初始化。',1; + RAISERROR(N'计分规则明细种子ID被占用且业务键不存在,无法安全初始化。',16,1); -- 若重复执行初始化脚本,先保留历史评分快照并解除规则项引用,再物理删除旧交互绳难度项。 IF OBJECT_ID(N'dbo.EventJudgeScoreDetail',N'U') IS NOT NULL @@ -590,26 +586,60 @@ BEGIN TRY AND i.ItemType=1 AND NOT EXISTS(SELECT 1 FROM #ItemSeed s WHERE s.SourceRuleId=m.SourceId AND s.JudgeRoleType=i.JudgeRoleType AND s.ItemCode=i.ItemCode); - /* 3. 交互绳项目绑定计分规则。 */ - DECLARE @WireRuleId BIGINT = (SELECT TOP 1 Id FROM dbo.ScoreRule WHERE RuleCode LIKE N'ROPE_FREESTYLE_WIRE_%' AND DeleteMark=0 ORDER BY Id); - IF @WireRuleId IS NULL THROW 51012,N'未找到交互绳花样计分规则(ROPE_FREESTYLE_WIRE_*)。',1; - UPDATE dbo.Project - SET ScoreRuleId=@WireRuleId,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() - WHERE Name IN (N'2人交互绳',N'3人交互绳') - AND DeleteMark=0 - AND ISNULL(ScoreRuleId,0)<>@WireRuleId; + /* 将脚本范围内未定义但仍启用的旧评分项软删除,保证有效项与测试库种子完全一致。 */ + UPDATE item + SET DeleteMark=1,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() + FROM dbo.ScoreRuleItem item + JOIN #RuleMap map ON map.TargetId=item.ScoreRuleId + WHERE item.DeleteMark=0 + AND NOT EXISTS( + SELECT 1 + FROM #ItemSeed seed + WHERE seed.SourceRuleId=map.SourceId + AND seed.JudgeRoleType=item.JudgeRoleType + AND seed.ItemCode=item.ItemCode + AND seed.DeleteMark=0 + ); + + /* 3. 标准项目及已确认历史名称绑定计分规则(名称 + 项目类型共同定位,避免同名项目误绑)。 */ + DECLARE @ProjectRuleSeed TABLE(ProjectName NVARCHAR(128),ProjectType INT,RuleCode NVARCHAR(64),PRIMARY KEY(ProjectName,ProjectType)); + INSERT @ProjectRuleSeed(ProjectName,ProjectType,RuleCode) VALUES + (N'个人花样',1004,N'ROPE_FREESTYLE_SINGLE'), + (N'规定赛',1004,N'ROPE_PRESCRIBED'), + (N'两人同步花样',1004,N'ROPE_FREESTYLE_DOUBLE_SYNC'), + (N'四人同步花样',1004,N'ROPE_FREESTYLE_QUAD_SYNC'), + (N'两人车轮跳花样',1004,N'ROPE_FREESTYLE_WHEEL_PAIR'), + (N'三人交互绳花样',1004,N'ROPE_FREESTYLE_WIRE_TRIPLE'), + (N'四人交互绳花样',1004,N'ROPE_FREESTYLE_WIRE_QUAD'), + (N'表演赛',1006,N'ROPE_SHOWCASE'), + (N'2人交互绳',1006,N'ROPE_FREESTYLE_WIRE_TRIPLE'), + (N'3人交互绳',1006,N'ROPE_FREESTYLE_WIRE_TRIPLE'); + UPDATE project + SET ScoreRuleId=scoreRule.Id,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() + FROM dbo.Project project + JOIN @ProjectRuleSeed seed ON seed.ProjectName=project.Name AND seed.ProjectType=project.ProjectType + JOIN dbo.ScoreRule scoreRule ON scoreRule.RuleCode=seed.RuleCode AND scoreRule.DeleteMark=0 + WHERE project.DeleteMark=0 + AND ISNULL(project.ScoreRuleId,0)<>scoreRule.Id; + IF EXISTS( + SELECT 1 + FROM dbo.Project project + JOIN @ProjectRuleSeed seed ON seed.ProjectName=project.Name AND seed.ProjectType=project.ProjectType + LEFT JOIN dbo.ScoreRule scoreRule ON scoreRule.RuleCode=seed.RuleCode AND scoreRule.DeleteMark=0 + WHERE project.DeleteMark=0 AND (scoreRule.Id IS NULL OR ISNULL(project.ScoreRuleId,0)<>scoreRule.Id) + ) RAISERROR(N'标准项目计分规则绑定未完整同步。',16,1); /* 4. 打分系统单位角色。 */ - IF EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code<>N'scoringunit') THROW 51005,N'SysRole.Id=1003 已被其他角色占用。',1; + IF EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code<>N'scoringunit') RAISERROR(N'SysRole.Id=1003 已被其他角色占用。',16,1); IF NOT EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003) INSERT dbo.SysRole(Id,Name,Code,Status,Sort,Remark,DeleteMark,CreatedUserId,CreatedTime) VALUES(1003,N'打分系统单位',N'scoringunit',0,4,N'打分系统单位账号',0,1000,'2023-06-01'); ELSE UPDATE dbo.SysRole SET Name=N'打分系统单位',Code=N'scoringunit',Status=0,Sort=4,Remark=N'打分系统单位账号',DeleteMark=0 WHERE Id=1003; /* 5. 菜单和按钮。 */ IF NOT EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1047 AND Code=N'permission:account' AND DeleteMark=0) - THROW 51006,N'未找到权限管理-账号管理菜单(Id=1047,Code=permission:account)。',1; + RAISERROR(N'未找到权限管理-账号管理菜单(Id=1047,Code=permission:account)。',16,1); IF EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1080 AND ISNULL(Code,N'')<>N'system:unit') - THROW 51006,N'SysMenu.Id=1080 已被其他菜单占用。',1; + RAISERROR(N'SysMenu.Id=1080 已被其他菜单占用。',16,1); /* 保留独立单位管理菜单,账号管理仅维护后台系统账号。 */ CREATE TABLE #MenuSeed(Id BIGINT PRIMARY KEY,Name NVARCHAR(32),Type INT,Code NVARCHAR(128),ParentId BIGINT,RouteName NVARCHAR(32),Path NVARCHAR(128),Component NVARCHAR(128),Redirect NVARCHAR(128),Icon NVARCHAR(64),IsIframe BIT,Link NVARCHAR(256),IsVisible BIT,IsKeepAlive BIT,IsFixed BIT,Status INT,Sort INT,Remark NVARCHAR(256),DeleteMark BIT,CreatedUserId BIGINT,CreatedTime DATETIME2(3)); INSERT #MenuSeed VALUES @@ -619,13 +649,15 @@ BEGIN TRY (1083,N'打分账号-删除',2,N'system:unit:delete',1080,N'btn_system_unit_delete',N'',N'',N'',N'',0,N'',0,1,0,0,3,N'单位管理:账号删除',0,1000,N'2023-06-01'), (1084,N'打分账号-启用禁用',2,N'system:unit:status',1080,N'btn_system_unit_status',N'',N'',N'',N'',0,N'',0,1,0,0,4,N'单位管理:账号状态',0,1000,N'2023-06-01'), (1085,N'打分账号-重置密码',2,N'system:unit:resetpwd',1080,N'btn_system_unit_resetpwd',N'',N'',N'',N'',0,N'',0,1,0,0,5,N'单位管理:重置密码',0,1000,N'2023-06-01'), - (1086,N'打分系统工作台',0,N'scoring',NULL,N'scoring',N'/scoring',N'Layout',N'/scoring/launcher',N'ele-Trophy',0,N'',1,1,0,0,190,N'打分系统工作台',0,1000,N'2023-06-01'), - (1087,N'工作台',1,N'scoring:launcher',1086,N'scoringLauncher',N'/scoring/launcher',N'scoring/launcher/index',N'',N'ele-Monitor',0,N'',1,1,0,0,1,N'选择计分模式和赛事',0,1000,N'2023-06-01'), - (1088,N'秩序册',1,N'scoring:orderbook',1086,N'scoringOrderBook',N'/scoring/orderbook',N'scoring/orderbook/index',N'',N'ele-Notebook',0,N'',1,1,0,0,2,N'秩序册导入',0,1000,N'2023-06-01'), + (1086,N'打分系统工作台',0,N'scoring',NULL,N'scoring',N'/scoring',N'Layout',N'',N'ele-Trophy',0,N'',1,1,0,0,190,N'打分系统工作台',0,1000,N'2023-06-01'), + (1087,N'秩序册',1,N'scoring:launcher',1086,N'scoringLauncher',N'/scoring/launcher',N'scoring/launcher/index',N'',N'ele-Notebook',0,N'',1,1,0,0,1,N'秩序册',0,1000,N'2023-06-01'), + (1088,N'成绩投屏',1,N'scoring:screen',1086,N'scoringScreen',N'/scoring/screen',N'scoring/screen/index',N'',N'ele-DataLine',0,N'',1,1,0,0,2,N'成绩投屏',0,1000,N'2023-06-01'), (1089,N'成绩管理',1,N'scoring:workbench',1086,N'scoringWorkbench',N'/scoring/workbench',N'scoring/workbench/index',N'',N'ele-Management',0,N'',1,1,0,0,3,N'成绩管理',0,1000,N'2023-06-01'), - (1090,N'成绩投屏',1,N'scoring:cast',1086,N'scoringCast',N'/scoring/cast',N'scoring/workbench/index',N'',N'ele-DataLine',0,N'',1,1,0,0,4,N'成绩投屏操作台',0,1000,N'2023-06-01'), (2010,N'裁判管理',1,N'referee',NULL,N'referee',N'/referee',N'match/referee/index',N'',N'ele-UserFilled',0,N'',1,1,0,0,245,N'裁判库管理',0,1000,N'2023-06-01'); - IF EXISTS(SELECT 1 FROM #MenuSeed s JOIN dbo.SysMenu m ON m.Id=s.Id WHERE ISNULL(m.Code,N'')<>ISNULL(s.Code,N'')) THROW 51006,N'二期菜单ID已被其他菜单占用。',1; + IF EXISTS( + SELECT 1 FROM #MenuSeed s JOIN dbo.SysMenu m ON m.Id=s.Id + WHERE ISNULL(m.Code,N'')<>ISNULL(s.Code,N'') + ) RAISERROR(N'二期菜单ID已被其他菜单占用。',16,1); UPDATE m SET Name=s.Name,Type=s.Type,Code=s.Code,ParentId=s.ParentId,RouteName=s.RouteName,Path=s.Path,Component=s.Component,Redirect=s.Redirect,Icon=s.Icon,IsIframe=s.IsIframe,Link=s.Link,IsVisible=s.IsVisible,IsKeepAlive=s.IsKeepAlive,IsFixed=s.IsFixed,Status=s.Status,Sort=s.Sort,Remark=s.Remark,DeleteMark=0,UpdatedUserId=1000,UpdatedTime=SYSUTCDATETIME() FROM dbo.SysMenu m JOIN #MenuSeed s ON s.Id=m.Id WHERE EXISTS(SELECT m.Name,m.Type,m.Code,m.ParentId,m.RouteName,m.Path,m.Component,m.Redirect,m.Icon,m.IsIframe,m.Link,m.IsVisible,m.IsKeepAlive,m.IsFixed,m.Status,m.Sort,m.Remark,m.DeleteMark @@ -636,9 +668,9 @@ BEGIN TRY /* 6. 角色菜单授权。 */ DECLARE @RoleMenuSeed TABLE(Id BIGINT NULL,RoleId BIGINT,MenuId BIGINT,SeedOrder INT IDENTITY(1,1),PRIMARY KEY(RoleId,MenuId)); INSERT @RoleMenuSeed(RoleId,MenuId) VALUES - (1000,1080),(1000,1081),(1000,1082),(1000,1083),(1000,1084),(1000,1085),(1000,1086),(1000,1087),(1000,1088),(1000,1089),(1000,1090),(1000,2010), - (1003,1086),(1003,1087),(1003,1088),(1003,1089),(1003,1090), - (1001,1086),(1001,1089),(1001,1090); + (1000,1080),(1000,1081),(1000,1082),(1000,1083),(1000,1084),(1000,1085),(1000,1086),(1000,1087),(1000,1088),(1000,1089),(1000,2010), + (1003,1087),(1003,1088),(1003,1089), + (1001,1088),(1001,1089); DECLARE @RoleMenuNextId BIGINT; SELECT @RoleMenuNextId=ISNULL(MAX(Id),0) FROM dbo.SysRoleMenu WITH (UPDLOCK,HOLDLOCK); UPDATE s SET Id=rm.Id @@ -670,12 +702,12 @@ BEGIN TRY (N'CertificateTemplate',N'UpdatedUserId'),(N'CertificateTemplate',N'UpdatedTime'), (N'CertificatePlaceholder',N'CreatedUserId'),(N'CertificatePlaceholder',N'CreatedTime'),(N'CertificatePlaceholder',N'UpdatedUserId'),(N'CertificatePlaceholder',N'UpdatedTime'), (N'EventInfo',N'RefereeRegistrationCode'),(N'EventRegistrationLimit',N'RefereeLimit'), + (N'EventRegistrationItem',N'TeamId'),(N'EventRegistrationItem',N'TeamName'),(N'EventRegistrationItem',N'TeamIndex'), (N'Project',N'ScoreRuleId'),(N'SysUser',N'UnitName'),(N'SysUser',N'UnitPlatform'), (N'EventResult',N'SessionId'),(N'EventResult',N'SessionEntryId'),(N'EventResult',N'TotalScore'),(N'EventResult',N'ResultVersion'),(N'EventResult',N'ReviewUserId'),(N'EventResult',N'ReviewTime'), (N'EventReferee',N'RefereeApplicationId'),(N'EventVenue',N'VenueCode'),(N'EventJudgeMessage',N'ReceiverUserId'), (N'EventJudgeScoreDetail',N'ScoreRuleItemId'),(N'EventResultVersion',N'EventResultId'),(N'EventScoreCorrection',N'OriginalScoreSheetId'); INSERT @Validation SELECT N'COLUMN',TableName+N'.'+ColumnName,CASE WHEN COL_LENGTH(N'dbo.'+TableName,ColumnName) IS NOT NULL THEN 1 ELSE 0 END,N'dbo.'+TableName+N'.'+ColumnName FROM @ExpectedColumns; - INSERT @Validation VALUES (N'OBJECT',N'二期视图',CASE WHEN (SELECT COUNT(*) FROM sys.views WHERE name LIKE 'vw_Phase2[_]%')=3 THEN 1 ELSE 0 END,CONVERT(NVARCHAR(20),(SELECT COUNT(*) FROM sys.views WHERE name LIKE 'vw_Phase2[_]%'))), (N'OBJECT',N'二期存储过程',CASE WHEN (SELECT COUNT(*) FROM sys.procedures WHERE name LIKE 'usp_Phase2[_]%')=2 THEN 1 ELSE 0 END,CONVERT(NVARCHAR(20),(SELECT COUNT(*) FROM sys.procedures WHERE name LIKE 'usp_Phase2[_]%'))), @@ -683,16 +715,19 @@ BEGIN TRY (N'INDEX',N'二期索引',CASE WHEN (SELECT COUNT(*) FROM sys.indexes WHERE name IN(N'UX_Referee_Mobile_Active',N'UX_EventReferee_Event_Referee_Active',N'UX_EventVenue_Event_Code_Active',N'UX_EventSession_Event_No_Active',N'UX_EventJudgeScoreSheet_Idempotency',N'UX_EventResultVersion_Result_Version'))=6 THEN 1 ELSE 0 END,N'6个关键索引'), (N'CONSTRAINT',N'二期外键',CASE WHEN (SELECT COUNT(*) FROM sys.foreign_keys WHERE name LIKE 'FK[_]%' AND parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables))>=20 THEN 1 ELSE 0 END,CONVERT(NVARCHAR(20),(SELECT COUNT(*) FROM sys.foreign_keys WHERE name LIKE 'FK[_]%' AND parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables)))), (N'SEED',N'计分规则',CASE WHEN (SELECT COUNT(DISTINCT r.RuleCode) FROM dbo.ScoreRule r JOIN #RuleSeed s ON s.RuleCode=r.RuleCode WHERE r.DeleteMark=0)=8 THEN 1 ELSE 0 END,N'期望8条'), - (N'SEED',N'计分规则明细',CASE WHEN (SELECT COUNT(*) FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId JOIN dbo.ScoreRuleItem i ON i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=0 WHERE s.DeleteMark=0)=(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0) THEN 1 ELSE 0 END,CONCAT(N'期望',(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0),N'条启用评分项')), + (N'SEED',N'计分规则明细',CASE WHEN (SELECT COUNT(*) FROM #ItemSeed s JOIN #RuleMap m ON m.SourceId=s.SourceRuleId JOIN dbo.ScoreRuleItem i ON i.ScoreRuleId=m.TargetId AND i.JudgeRoleType=s.JudgeRoleType AND i.ItemCode=s.ItemCode AND i.DeleteMark=0 WHERE s.DeleteMark=0)=(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0) + AND (SELECT COUNT(*) FROM dbo.ScoreRuleItem i JOIN #RuleMap m ON m.TargetId=i.ScoreRuleId WHERE i.DeleteMark=0)=(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0) + THEN 1 ELSE 0 END,CONCAT(N'期望且仅允许',(SELECT COUNT(*) FROM #ItemSeed WHERE DeleteMark=0),N'条启用评分项')), + (N'SEED',N'标准项目规则绑定',CASE WHEN NOT EXISTS(SELECT 1 FROM dbo.Project project JOIN @ProjectRuleSeed seed ON seed.ProjectName=project.Name AND seed.ProjectType=project.ProjectType LEFT JOIN dbo.ScoreRule scoreRule ON scoreRule.RuleCode=seed.RuleCode AND scoreRule.DeleteMark=0 WHERE project.DeleteMark=0 AND (scoreRule.Id IS NULL OR ISNULL(project.ScoreRuleId,0)<>scoreRule.Id)) THEN 1 ELSE 0 END,N'按项目名称和项目类型核对10条映射'), (N'SEED',N'角色与菜单',CASE WHEN EXISTS(SELECT 1 FROM dbo.SysRole WHERE Id=1003 AND Code='scoringunit' AND DeleteMark=0) - AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,1090,2010) AND DeleteMark=0)=12 + AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,2010) AND DeleteMark=0)=11 AND EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1080 AND Code='system:unit' AND ParentId=1070 AND DeleteMark=0) AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1081,1082,1083,1084,1085) AND ParentId=1080 AND DeleteMark=0)=5 AND EXISTS(SELECT 1 FROM dbo.SysMenu WHERE Id=1086 AND Code='scoring' AND DeleteMark=0) - AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1087,1088,1089,1090) AND ParentId=1086 AND DeleteMark=0)=4 - AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1000 AND MenuId IN(1080,1086,1087,1088,1089,1090) AND DeleteMark=0)=6 - AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1003 AND MenuId IN(1086,1087,1088,1089,1090) AND DeleteMark=0)=5 - AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1001 AND MenuId IN(1086,1089,1090) AND DeleteMark=0)=3 + AND (SELECT COUNT(*) FROM dbo.SysMenu WHERE Id IN(1087,1088,1089) AND ParentId=1086 AND DeleteMark=0)=3 + AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1000 AND MenuId IN(1080,1081,1082,1083,1084,1085,1086,1087,1088,1089,2010) AND DeleteMark=0)=11 + AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1003 AND MenuId IN(1087,1088,1089) AND DeleteMark=0)=3 + AND (SELECT COUNT(*) FROM dbo.SysRoleMenu WHERE RoleId=1001 AND MenuId IN(1088,1089) AND DeleteMark=0)=2 THEN 1 ELSE 0 END,N'单位管理、工作台及三个业务模块、三类角色菜单授权'), (N'PERMISSION',N'最小权限角色',CASE WHEN (SELECT COUNT(*) FROM sys.database_principals WHERE name IN('yd_phase2_app_rw','yd_phase2_app_ro','yd_phase2_executor') AND type='R')=3 THEN 1 ELSE 0 END,N'期望3个数据库角色'); @@ -701,7 +736,7 @@ BEGIN TRY BEGIN DECLARE @FailedValidation NVARCHAR(2048); SELECT TOP 1 @FailedValidation=N'二期部署后置校验失败:'+[Category]+N' / '+[Item]+N',实际值:'+ISNULL([Actual],N'') FROM @Validation WHERE Passed=0 ORDER BY [Category],[Item]; - THROW 51008,@FailedValidation,1; + RAISERROR(@FailedValidation,16,1); END; PRINT N'[INSERT] 生成部署摘要'; @@ -711,7 +746,6 @@ BEGIN TRY (SELECT COUNT(*) FROM sys.foreign_keys f WHERE f.parent_object_id IN(SELECT OBJECT_ID(N'dbo.'+QUOTENAME(Name)) FROM @ExpectedTables)) AS Phase2ForeignKeyCount, (SELECT COUNT(*) FROM #RuleSeed) AS RuleSeedCount,(SELECT COUNT(*) FROM #ItemSeed) AS RuleItemSeedCount; - COMMIT TRANSACTION; PRINT N'二期 INSERT 脚本执行成功,最终校验已通过。'; END TRY @@ -719,6 +753,5 @@ BEGIN CATCH DECLARE @ErrorNumber INT=ERROR_NUMBER(),@ErrorLine INT=ERROR_LINE(),@ErrorMessage NVARCHAR(4000)=ERROR_MESSAGE(); IF XACT_STATE()<>0 ROLLBACK TRANSACTION; SELECT N'FAILED' AS [Stage],@ErrorNumber AS ErrorNumber,@ErrorLine AS ErrorLine,@ErrorMessage AS ErrorMessage,N'当前脚本未提交的变更已回滚' AS RollbackStatus; - THROW; + RAISERROR(@ErrorMessage,16,1); END CATCH; -