feat(deployment): add v1.2.0 database scripts and improve Docker/auth configuration
All checks were successful
continuous-integration/drone/push Build is passing

- Add v1.2.0 complete database upgrade scripts for business and admin databases
- Enhance WeChat login logic to handle OpenId reassociation when user logs in via phone number
- Add UpdatedAt timestamp update in WeChat login record updates
- Configure Docker container permissions for AgileConfig cache file writes
- Add Caddy image tagging to CI-CD deployment documentation
- Update frontend Config.js for deployment configuration management
This commit is contained in:
zpc 2026-03-26 22:10:57 +08:00
parent 8f0056c9b2
commit 442f32a043
6 changed files with 758 additions and 15 deletions

View File

@ -54,6 +54,8 @@
docker pull mcr.microsoft.com/dotnet/aspnet:8.0
docker tag mcr.microsoft.com/dotnet/aspnet:8.0 192.168.195.25:19900/library/dotnet/aspnet:8.0
docker push 192.168.195.25:19900/library/dotnet/aspnet:8.0
docker tag caddy:alpine 192.168.195.25:19900/library/caddy:alpine
```
## 五、前置条件

View File

@ -548,11 +548,30 @@ namespace LiveForum.Service.Auth
if (user != null)
{
// 找到手机号用户,确保绑定/更新 OpenID
// 先按 UserId 查当前用户的微信记录
wechatLogin = await _wechatMiniProgramLoginsRepository.Select
.Where(x => x.UserId == user.Id)
.FirstAsync();
if (wechatLogin == null)
{
// 当前用户没有微信记录,检查该 OpenId 是否已被其他用户占用
var existingByOpenId = await _wechatMiniProgramLoginsRepository.Select
.Where(x => x.OpenId == openId)
.FirstAsync();
if (existingByOpenId != null)
{
// OpenId 已存在,将其重新关联到当前手机号用户
existingByOpenId.UserId = user.Id;
existingByOpenId.SessionKey = sessionKey;
existingByOpenId.LastLoginTime = now;
existingByOpenId.LastLoginIp = clientIp;
existingByOpenId.UpdatedAt = now;
await _wechatMiniProgramLoginsRepository.UpdateAsync(existingByOpenId);
wechatLogin = existingByOpenId;
}
else
{
wechatLogin = new T_WechatMiniProgramLogins
{
@ -567,12 +586,14 @@ namespace LiveForum.Service.Auth
};
await _wechatMiniProgramLoginsRepository.InsertAsync(wechatLogin);
}
}
else
{
wechatLogin.OpenId = openId;
wechatLogin.SessionKey = sessionKey;
wechatLogin.LastLoginTime = now;
wechatLogin.LastLoginIp = clientIp;
wechatLogin.UpdatedAt = now;
await _wechatMiniProgramLoginsRepository.UpdateAsync(wechatLogin);
}
}

View File

@ -31,4 +31,10 @@ RUN dotnet publish "./LiveForum.WebApi.csproj" -c $BUILD_CONFIGURATION -o /app/p
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
# 给 AgileConfig 缓存文件写权限app 用户需要写入配置缓存)
USER root
RUN mkdir -p /app && chown -R $APP_UID:$APP_UID /app
USER $APP_UID
ENTRYPOINT ["dotnet", "LiveForum.WebApi.dll"]

View File

@ -0,0 +1,557 @@
-- ==========================================
-- 团播机构 v1.2.0 业务库 (LiveForumDB) 完整升级脚本
-- 整合时间: 2025-01-25
-- 说明: 整合所有 v1.2.0 业务库变更,按依赖顺序执行
-- 执行前请备份数据库!建议在业务低峰期执行
-- ==========================================
-- 包含模块(按执行顺序):
-- 1. CDK 激活系统T_CDKs、T_SystemSettings、T_Users 字段)
-- 2. 实名认证 & 手机号登录T_Users 字段、T_RealNameVerifyLogs
-- 3. 帖子回复权限T_Posts.AllowReply
-- 4. 发帖回复时间间隔T_PostReplyIntervals
-- 5. 防沉迷规则T_AntiAddictionRules
-- 6. 身份权限设置4张表 + 默认数据)
-- 7. 点赞唯一索引T_Likes
-- 8. 消息系统字段扩展T_Messages 新字段)
-- 9. 消息系统重构(类型调整 + MyCommentContent
-- ==========================================
PRINT '=========================================='
PRINT '开始执行 v1.2.0 业务库完整升级脚本'
PRINT '执行时间: ' + CONVERT(VARCHAR, GETDATE(), 120)
PRINT '=========================================='
PRINT ''
-- ##########################################################
-- 模块1: CDK 激活系统
-- ##########################################################
PRINT '>>> 模块1: CDK 激活系统'
PRINT ''
-- 1.1 创建 CDK 表 T_CDKs
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'T_CDKs')
BEGIN
CREATE TABLE T_CDKs (
Id BIGINT PRIMARY KEY IDENTITY(1,1),
Code NVARCHAR(50) NOT NULL,
BatchNo NVARCHAR(50) NULL,
Status INT NOT NULL DEFAULT 0,
UsedByUserId BIGINT NULL,
UsedAt DATETIME2 NULL,
CreatedAt DATETIME2 NOT NULL DEFAULT GETDATE(),
Remark NVARCHAR(200) NULL
);
PRINT '✓ T_CDKs 表创建成功'
END
ELSE
PRINT '⚠ T_CDKs 表已存在,跳过'
-- 1.2 T_CDKs 索引
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_T_CDKs_Code' AND object_id = OBJECT_ID('T_CDKs'))
BEGIN
CREATE UNIQUE INDEX IX_T_CDKs_Code ON T_CDKs (Code);
PRINT '✓ IX_T_CDKs_Code 唯一索引创建成功'
END
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_T_CDKs_BatchNo' AND object_id = OBJECT_ID('T_CDKs'))
BEGIN
CREATE INDEX IX_T_CDKs_BatchNo ON T_CDKs (BatchNo);
PRINT '✓ IX_T_CDKs_BatchNo 索引创建成功'
END
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_T_CDKs_Status' AND object_id = OBJECT_ID('T_CDKs'))
BEGIN
CREATE INDEX IX_T_CDKs_Status ON T_CDKs (Status);
PRINT '✓ IX_T_CDKs_Status 索引创建成功'
END
-- 1.3 创建系统设置表 T_SystemSettings
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'T_SystemSettings')
BEGIN
CREATE TABLE T_SystemSettings (
Id INT PRIMARY KEY IDENTITY(1,1),
SettingKey NVARCHAR(100) NOT NULL,
SettingValue NVARCHAR(500) NULL,
Description NVARCHAR(200) NULL,
UpdatedAt DATETIME2 NOT NULL DEFAULT GETDATE()
);
PRINT '✓ T_SystemSettings 表创建成功'
END
ELSE
PRINT '⚠ T_SystemSettings 表已存在,跳过'
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_T_SystemSettings_SettingKey' AND object_id = OBJECT_ID('T_SystemSettings'))
BEGIN
CREATE UNIQUE INDEX IX_T_SystemSettings_SettingKey ON T_SystemSettings (SettingKey);
PRINT '✓ IX_T_SystemSettings_SettingKey 唯一索引创建成功'
END
-- 1.4 CDK 功能开关默认配置
IF NOT EXISTS (SELECT * FROM T_SystemSettings WHERE SettingKey = 'cdk_enabled')
BEGIN
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('cdk_enabled', 'true', 'CDK功能开关', GETDATE());
PRINT '✓ cdk_enabled 配置插入成功'
END
-- 1.5 T_Users 添加 CDK 激活字段
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'T_Users' AND COLUMN_NAME = 'IsCdkActivated')
BEGIN
ALTER TABLE T_Users ADD IsCdkActivated BIT NOT NULL DEFAULT 0;
PRINT '✓ T_Users.IsCdkActivated 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'T_Users' AND COLUMN_NAME = 'CdkActivatedAt')
BEGIN
ALTER TABLE T_Users ADD CdkActivatedAt DATETIME2 NULL;
PRINT '✓ T_Users.CdkActivatedAt 字段添加成功'
END
PRINT ''
-- ##########################################################
-- 模块2: 实名认证 & 手机号登录
-- ##########################################################
PRINT '>>> 模块2: 实名认证 & 手机号登录'
PRINT ''
-- 2.1 T_Users 新增实名认证字段
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Users') AND name = 'IsRealNameVerified')
BEGIN
ALTER TABLE T_Users ADD IsRealNameVerified BIT NOT NULL DEFAULT 0;
PRINT '✓ T_Users.IsRealNameVerified 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Users') AND name = 'RealName')
BEGIN
ALTER TABLE T_Users ADD RealName NVARCHAR(50) NULL;
PRINT '✓ T_Users.RealName 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Users') AND name = 'IdCardNumber')
BEGIN
ALTER TABLE T_Users ADD IdCardNumber NVARCHAR(100) NULL;
PRINT '✓ T_Users.IdCardNumber 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Users') AND name = 'RealNameVerifiedAt')
BEGIN
ALTER TABLE T_Users ADD RealNameVerifiedAt DATETIME2 NULL;
PRINT '✓ T_Users.RealNameVerifiedAt 字段添加成功'
END
-- 2.2 T_Users.PhoneNumber 索引
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_T_Users_PhoneNumber' AND object_id = OBJECT_ID('T_Users'))
BEGIN
CREATE INDEX IX_T_Users_PhoneNumber ON T_Users (PhoneNumber);
PRINT '✓ IX_T_Users_PhoneNumber 索引创建成功'
END
-- 2.3 创建实名验证记录表
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('T_RealNameVerifyLogs') AND type = 'U')
BEGIN
CREATE TABLE T_RealNameVerifyLogs (
Id BIGINT PRIMARY KEY IDENTITY(1,1),
UserId BIGINT NOT NULL,
RealName NVARCHAR(50) NOT NULL,
IdCardNumberMasked NVARCHAR(20) NOT NULL,
IsSuccess BIT NOT NULL DEFAULT 0,
FailReason NVARCHAR(200) NULL,
ClientIp NVARCHAR(50) NULL,
CreatedAt DATETIME2 NOT NULL DEFAULT GETDATE()
);
CREATE INDEX IX_T_RealNameVerifyLogs_UserId_CreatedAt
ON T_RealNameVerifyLogs (UserId, CreatedAt);
PRINT '✓ T_RealNameVerifyLogs 表及索引创建成功'
END
ELSE
PRINT '⚠ T_RealNameVerifyLogs 表已存在,跳过'
-- 2.4 实名认证系统配置
IF NOT EXISTS (SELECT 1 FROM T_SystemSettings WHERE SettingKey = 'real_name_enabled')
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('real_name_enabled', 'true', N'实名认证功能开关', GETDATE());
IF NOT EXISTS (SELECT 1 FROM T_SystemSettings WHERE SettingKey = 'real_name_provider')
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('real_name_provider', 'aliyun', N'实名认证服务商aliyun/tencent', GETDATE());
IF NOT EXISTS (SELECT 1 FROM T_SystemSettings WHERE SettingKey = 'real_name_daily_limit')
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('real_name_daily_limit', '5', N'每用户每天最多验证次数', GETDATE());
IF NOT EXISTS (SELECT 1 FROM T_SystemSettings WHERE SettingKey = 'real_name_interval_seconds')
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('real_name_interval_seconds', '60', N'两次验证最小间隔(秒)', GETDATE());
IF NOT EXISTS (SELECT 1 FROM T_SystemSettings WHERE SettingKey = 'aliyun_access_key_id')
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('aliyun_access_key_id', '', N'阿里云 AccessKey ID', GETDATE());
IF NOT EXISTS (SELECT 1 FROM T_SystemSettings WHERE SettingKey = 'aliyun_access_key_secret')
INSERT INTO T_SystemSettings (SettingKey, SettingValue, Description, UpdatedAt)
VALUES ('aliyun_access_key_secret', '', N'阿里云 AccessKey Secret', GETDATE());
PRINT '✓ 实名认证系统配置插入完成'
PRINT ''
-- ##########################################################
-- 模块3: 帖子回复权限
-- ##########################################################
PRINT '>>> 模块3: 帖子回复权限'
PRINT ''
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Posts') AND name = 'AllowReply')
BEGIN
ALTER TABLE T_Posts ADD AllowReply BIT NOT NULL DEFAULT 1;
PRINT '✓ T_Posts.AllowReply 字段添加成功'
END
ELSE
PRINT '⚠ AllowReply 字段已存在,跳过'
PRINT ''
-- ##########################################################
-- 模块4: 发帖回复时间间隔
-- ##########################################################
PRINT '>>> 模块4: 发帖回复时间间隔'
PRINT ''
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('T_PostReplyIntervals') AND type = 'U')
BEGIN
CREATE TABLE T_PostReplyIntervals (
Id INT IDENTITY(1,1) PRIMARY KEY,
CertificationTypeId INT NOT NULL,
PostInterval INT NOT NULL DEFAULT 0,
ReplyInterval INT NOT NULL DEFAULT 0,
CreatedAt DATETIME2 NOT NULL DEFAULT GETDATE(),
UpdatedAt DATETIME2 NOT NULL DEFAULT GETDATE(),
CONSTRAINT UQ_PostReplyIntervals_CertTypeId UNIQUE (CertificationTypeId),
CONSTRAINT FK_PostReplyIntervals_CertType FOREIGN KEY (CertificationTypeId) REFERENCES T_CertificationTypes(Id)
);
PRINT '✓ T_PostReplyIntervals 表创建成功'
END
ELSE
PRINT '⚠ T_PostReplyIntervals 表已存在,跳过'
PRINT ''
-- ##########################################################
-- 模块5: 防沉迷规则
-- ##########################################################
PRINT '>>> 模块5: 防沉迷规则'
PRINT ''
IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID('T_AntiAddictionRules') AND type = 'U')
BEGIN
CREATE TABLE T_AntiAddictionRules (
Id INT IDENTITY(1,1) PRIMARY KEY,
StartTime TIME NOT NULL,
EndTime TIME NOT NULL,
RestrictPost BIT NOT NULL DEFAULT 0,
RestrictReply BIT NOT NULL DEFAULT 0,
RestrictFlower BIT NOT NULL DEFAULT 0,
CreatedAt DATETIME2 NOT NULL DEFAULT GETDATE(),
UpdatedAt DATETIME2 NOT NULL DEFAULT GETDATE()
);
PRINT '✓ T_AntiAddictionRules 表创建成功'
END
ELSE
PRINT '⚠ T_AntiAddictionRules 表已存在,跳过'
PRINT ''
-- ##########################################################
-- 模块6: 身份权限设置4张表 + 默认数据)
-- ##########################################################
PRINT '>>> 模块6: 身份权限设置'
PRINT ''
BEGIN TRANSACTION;
-- 6.1 创建认证等级权限配置表
IF OBJECT_ID('T_CertificationTypePermissions', 'U') IS NULL
BEGIN
CREATE TABLE T_CertificationTypePermissions (
Id INT IDENTITY(1,1) PRIMARY KEY,
CertificationTypeId INT NOT NULL,
CanPost BIT NOT NULL DEFAULT 0,
CanReply BIT NOT NULL DEFAULT 0,
CanFlower BIT NOT NULL DEFAULT 0,
CanLike BIT NOT NULL DEFAULT 0,
CanDeleteOtherPost BIT NOT NULL DEFAULT 0,
CreatedAt DATETIME NULL,
UpdatedAt DATETIME NULL,
CONSTRAINT UQ_CertTypePermissions_CertTypeId UNIQUE (CertificationTypeId),
CONSTRAINT FK_CertTypePermissions_CertType FOREIGN KEY (CertificationTypeId) REFERENCES T_CertificationTypes(Id)
);
PRINT '✓ T_CertificationTypePermissions 表创建成功'
END
ELSE
PRINT '⚠ T_CertificationTypePermissions 表已存在,跳过'
-- 6.2 创建身份组表
IF OBJECT_ID('T_IdentityGroups', 'U') IS NULL
BEGIN
CREATE TABLE T_IdentityGroups (
Id INT IDENTITY(1,1) PRIMARY KEY,
Name NVARCHAR(50) NOT NULL,
IsDefault BIT NOT NULL DEFAULT 0,
CreatedAt DATETIME NULL,
UpdatedAt DATETIME NULL,
CONSTRAINT UQ_IdentityGroups_Name UNIQUE (Name)
);
PRINT '✓ T_IdentityGroups 表创建成功'
END
ELSE
PRINT '⚠ T_IdentityGroups 表已存在,跳过'
-- 6.3 创建身份组权限配置表
IF OBJECT_ID('T_IdentityGroupPermissions', 'U') IS NULL
BEGIN
CREATE TABLE T_IdentityGroupPermissions (
Id INT IDENTITY(1,1) PRIMARY KEY,
IdentityGroupId INT NOT NULL,
CanPost BIT NOT NULL DEFAULT 0,
CanReply BIT NOT NULL DEFAULT 0,
CanFlower BIT NOT NULL DEFAULT 0,
CanLike BIT NOT NULL DEFAULT 0,
CanDeleteOtherPost BIT NOT NULL DEFAULT 0,
CreatedAt DATETIME NULL,
UpdatedAt DATETIME NULL,
CONSTRAINT UQ_IdentityGroupPermissions_GroupId UNIQUE (IdentityGroupId),
CONSTRAINT FK_IdentityGroupPermissions_Group FOREIGN KEY (IdentityGroupId) REFERENCES T_IdentityGroups(Id) ON DELETE CASCADE
);
PRINT '✓ T_IdentityGroupPermissions 表创建成功'
END
ELSE
PRINT '⚠ T_IdentityGroupPermissions 表已存在,跳过'
-- 6.4 创建用户身份组关联表
IF OBJECT_ID('T_UserIdentityGroups', 'U') IS NULL
BEGIN
CREATE TABLE T_UserIdentityGroups (
Id INT IDENTITY(1,1) PRIMARY KEY,
UserId BIGINT NOT NULL,
IdentityGroupId INT NOT NULL,
CreatedAt DATETIME NULL,
CONSTRAINT FK_UserIdentityGroups_User FOREIGN KEY (UserId) REFERENCES T_Users(Id),
CONSTRAINT FK_UserIdentityGroups_Group FOREIGN KEY (IdentityGroupId) REFERENCES T_IdentityGroups(Id) ON DELETE CASCADE,
CONSTRAINT UQ_UserIdentityGroups UNIQUE (UserId, IdentityGroupId)
);
PRINT '✓ T_UserIdentityGroups 表创建成功'
END
ELSE
PRINT '⚠ T_UserIdentityGroups 表已存在,跳过'
-- 6.5 插入默认身份组"普通用户"
IF NOT EXISTS (SELECT 1 FROM T_IdentityGroups WHERE IsDefault = 1)
BEGIN
INSERT INTO T_IdentityGroups (Name, IsDefault, CreatedAt)
VALUES (N'普通用户', 1, GETDATE());
PRINT '✓ 默认身份组"普通用户"插入成功'
END
ELSE
PRINT '⚠ 默认身份组已存在,跳过'
-- 6.6 为所有现有用户关联默认身份组
DECLARE @DefaultGroupId INT;
SELECT @DefaultGroupId = Id FROM T_IdentityGroups WHERE IsDefault = 1;
IF @DefaultGroupId IS NOT NULL
BEGIN
INSERT INTO T_UserIdentityGroups (UserId, IdentityGroupId, CreatedAt)
SELECT u.Id, @DefaultGroupId, GETDATE()
FROM T_Users u
WHERE NOT EXISTS (
SELECT 1 FROM T_UserIdentityGroups uig
WHERE uig.UserId = u.Id AND uig.IdentityGroupId = @DefaultGroupId
);
DECLARE @InsertedCount INT = @@ROWCOUNT;
PRINT '✓ 已为 ' + CAST(@InsertedCount AS NVARCHAR(10)) + ' 个现有用户关联默认身份组'
END
COMMIT TRANSACTION;
PRINT '✓ 身份权限设置事务已提交'
PRINT ''
-- ##########################################################
-- 模块7: 点赞唯一索引
-- ##########################################################
PRINT '>>> 模块7: 点赞唯一索引'
PRINT ''
IF NOT EXISTS (
SELECT 1 FROM sys.indexes
WHERE name = 'IX_T_Likes_User_Target' AND object_id = OBJECT_ID('T_Likes')
)
BEGIN
CREATE UNIQUE NONCLUSTERED INDEX IX_T_Likes_User_Target
ON T_Likes(UserId, TargetType, TargetId);
PRINT '✓ IX_T_Likes_User_Target 唯一索引创建成功'
END
ELSE
PRINT '⚠ IX_T_Likes_User_Target 索引已存在,跳过'
PRINT ''
-- ##########################################################
-- 模块8: 消息系统字段扩展
-- ##########################################################
PRINT '>>> 模块8: 消息系统字段扩展'
PRINT ''
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Messages') AND name = 'MessageTitle')
BEGIN
ALTER TABLE T_Messages ADD MessageTitle NVARCHAR(200) NULL;
PRINT '✓ T_Messages.MessageTitle 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Messages') AND name = 'SenderInfo')
BEGIN
ALTER TABLE T_Messages ADD SenderInfo NVARCHAR(MAX) NULL;
PRINT '✓ T_Messages.SenderInfo 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Messages') AND name = 'EventId')
BEGIN
ALTER TABLE T_Messages ADD EventId NVARCHAR(50) NULL;
PRINT '✓ T_Messages.EventId 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.columns WHERE object_id = OBJECT_ID('T_Messages') AND name = 'ContentSnapshot')
BEGIN
ALTER TABLE T_Messages ADD ContentSnapshot NVARCHAR(MAX) NULL;
PRINT '✓ T_Messages.ContentSnapshot 字段添加成功'
END
IF NOT EXISTS (SELECT * FROM sys.indexes WHERE name = 'IX_T_Messages_EventId' AND object_id = OBJECT_ID('T_Messages'))
BEGIN
CREATE INDEX IX_T_Messages_EventId ON T_Messages(EventId);
PRINT '✓ IX_T_Messages_EventId 索引创建成功'
END
PRINT ''
-- ##########################################################
-- 模块9: 消息系统重构(数据迁移)
-- ⚠ 注意: 此模块会删除关注消息(MessageType=3)并重新编号系统通知(4→3)
-- ⚠ 执行前请确认已备份数据!
-- ##########################################################
PRINT '>>> 模块9: 消息系统重构'
PRINT ''
BEGIN TRANSACTION;
-- 9.1 备份现有消息数据
IF OBJECT_ID('T_Messages_Backup_BeforeRefactor', 'U') IS NOT NULL
BEGIN
DROP TABLE T_Messages_Backup_BeforeRefactor;
PRINT '已删除旧的备份表'
END
SELECT * INTO T_Messages_Backup_BeforeRefactor FROM T_Messages;
PRINT '✓ 消息数据已备份到 T_Messages_Backup_BeforeRefactor'
-- 9.2 删除关注消息MessageType = 3
DECLARE @DeletedFollowCount INT;
SELECT @DeletedFollowCount = COUNT(*) FROM T_Messages WHERE MessageType = 3;
DELETE FROM T_Messages WHERE MessageType = 3;
PRINT '✓ 已删除 ' + CAST(@DeletedFollowCount AS NVARCHAR(10)) + ' 条关注消息'
-- 9.3 调整系统通知类型4 → 3
DECLARE @SystemNotificationCount INT;
SELECT @SystemNotificationCount = COUNT(*) FROM T_Messages WHERE MessageType = 4;
UPDATE T_Messages SET MessageType = 3 WHERE MessageType = 4;
PRINT '✓ 已将 ' + CAST(@SystemNotificationCount AS NVARCHAR(10)) + ' 条系统通知类型从 4 调整为 3'
-- 9.4 增加 MyCommentContent 字段
IF NOT EXISTS (
SELECT * FROM sys.columns
WHERE object_id = OBJECT_ID(N'dbo.T_Messages') AND name = 'MyCommentContent'
)
BEGIN
ALTER TABLE T_Messages ADD MyCommentContent NVARCHAR(MAX) NULL;
PRINT '✓ T_Messages.MyCommentContent 字段添加成功'
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'我的评论内容(回复消息展示被回复的内容)',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'T_Messages',
@level2type = N'COLUMN', @level2name = N'MyCommentContent';
END
ELSE
PRINT '⚠ MyCommentContent 字段已存在,跳过'
-- 9.5 更新字段注释
IF EXISTS (
SELECT * FROM sys.extended_properties
WHERE major_id = OBJECT_ID('dbo.T_Messages')
AND name = 'MS_Description'
AND minor_id = (SELECT column_id FROM sys.columns WHERE object_id = OBJECT_ID('dbo.T_Messages') AND name = 'MessageType')
)
EXEC sp_updateextendedproperty
@name = N'MS_Description',
@value = N'消息类型1-回复消息2-点赞消息含送花3-系统消息',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'T_Messages',
@level2type = N'COLUMN', @level2name = N'MessageType';
ELSE
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'消息类型1-回复消息2-点赞消息含送花3-系统消息',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'T_Messages',
@level2type = N'COLUMN', @level2name = N'MessageType';
IF EXISTS (
SELECT * FROM sys.extended_properties
WHERE major_id = OBJECT_ID('dbo.T_Messages')
AND name = 'MS_Description'
AND minor_id = (SELECT column_id FROM sys.columns WHERE object_id = OBJECT_ID('dbo.T_Messages') AND name = 'ContentType')
)
EXEC sp_updateextendedproperty
@name = N'MS_Description',
@value = N'内容类型1-帖子2-评论3-送花',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'T_Messages',
@level2type = N'COLUMN', @level2name = N'ContentType';
ELSE
EXEC sp_addextendedproperty
@name = N'MS_Description',
@value = N'内容类型1-帖子2-评论3-送花',
@level0type = N'SCHEMA', @level0name = N'dbo',
@level1type = N'TABLE', @level1name = N'T_Messages',
@level2type = N'COLUMN', @level2name = N'ContentType';
COMMIT TRANSACTION;
PRINT '✓ 消息系统重构事务已提交'
PRINT ''
-- ##########################################################
-- 升级完成
-- ##########################################################
PRINT '=========================================='
PRINT 'v1.2.0 业务库完整升级脚本执行完成!'
PRINT '完成时间: ' + CONVERT(VARCHAR, GETDATE(), 120)
PRINT '=========================================='
PRINT ''
PRINT '升级内容总结:'
PRINT ' 模块1: CDK 激活系统 (T_CDKs, T_SystemSettings, T_Users 字段)'
PRINT ' 模块2: 实名认证 (T_Users 字段, T_RealNameVerifyLogs, 系统配置)'
PRINT ' 模块3: 帖子回复权限 (T_Posts.AllowReply)'
PRINT ' 模块4: 发帖回复时间间隔 (T_PostReplyIntervals)'
PRINT ' 模块5: 防沉迷规则 (T_AntiAddictionRules)'
PRINT ' 模块6: 身份权限设置 (4张表 + 默认身份组 + 用户关联)'
PRINT ' 模块7: 点赞唯一索引 (IX_T_Likes_User_Target)'
PRINT ' 模块8: 消息系统字段扩展 (T_Messages 4个新字段)'
PRINT ' 模块9: 消息系统重构 (类型调整 + MyCommentContent)'
PRINT ''
PRINT '注意事项:'
PRINT ' - 模块9 已备份消息到 T_Messages_Backup_BeforeRefactor确认无误后可手动删除'
PRINT ' - 请在应用层清理 Redis 队列: DEL message:events:follow'
PRINT ' - 请确保应用程序代码已同步更新'
PRINT '=========================================='

View File

@ -0,0 +1,157 @@
-- ==========================================
-- 团播机构 v1.2.0 管理库 (admin) 完整菜单配置脚本
-- 整合时间: 2025-01-25
-- 说明: 整合所有 v1.2.0 后台管理菜单和权限配置
-- 数据库: 后台管理数据库 (admin)
-- ==========================================
-- 包含模块:
-- 1. CDK 管理菜单 + 权限按钮
-- 2. 发帖回复时间间隔配置菜单 + 权限按钮
-- 3. 防沉迷规则管理菜单 + 权限按钮
-- ==========================================
PRINT '=========================================='
PRINT '开始执行 v1.2.0 管理库完整菜单配置脚本'
PRINT '执行时间: ' + CONVERT(VARCHAR, GETDATE(), 120)
PRINT '=========================================='
PRINT ''
-- ##########################################################
-- 模块1: CDK 管理菜单
-- ##########################################################
PRINT '>>> 模块1: CDK 管理菜单'
PRINT ''
IF NOT EXISTS (SELECT 1 FROM sys_menu WHERE path = 'tcdk' AND component = 'liveforum/tcdk')
BEGIN
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('CDK管理', 1233, 10, 'tcdk', 'liveforum/tcdk', 1, 0, 'C', '0', '0', 'cdk:list', 'key', 'admin', GETDATE(), 'admin', GETDATE(), 'CDK激活码管理');
DECLARE @cdkMenuId BIGINT = SCOPE_IDENTITY();
PRINT '✓ CDK 管理菜单插入成功menuId: ' + CAST(@cdkMenuId AS VARCHAR);
-- 权限按钮
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('查询', @cdkMenuId, 1, '#', NULL, 1, 0, 'F', '0', '0', 'cdk:query', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('生成', @cdkMenuId, 2, '#', NULL, 1, 0, 'F', '0', '0', 'cdk:generate', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('删除', @cdkMenuId, 3, '#', NULL, 1, 0, 'F', '0', '0', 'cdk:delete', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('导出', @cdkMenuId, 4, '#', NULL, 1, 0, 'F', '0', '0', 'cdk:export', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('设置', @cdkMenuId, 5, '#', NULL, 1, 0, 'F', '0', '0', 'settings:edit', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('查询设置', @cdkMenuId, 6, '#', NULL, 1, 0, 'F', '0', '0', 'settings:query', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
PRINT '✓ CDK 权限按钮插入成功 (查询/生成/删除/导出/设置/查询设置)'
-- 为管理员角色分配权限
INSERT INTO sys_role_menu (Role_id, Menu_id, Create_time)
SELECT 1, menuId, GETDATE()
FROM sys_menu WHERE menuId >= @cdkMenuId;
PRINT '✓ CDK 菜单权限已分配给管理员角色'
END
ELSE
PRINT '⚠ CDK 管理菜单已存在,跳过'
PRINT ''
-- ##########################################################
-- 模块2: 发帖回复时间间隔配置菜单
-- ##########################################################
PRINT '>>> 模块2: 发帖回复时间间隔配置菜单'
PRINT ''
IF NOT EXISTS (SELECT 1 FROM sys_menu WHERE path = 'tpostreplyintervals' AND component = 'liveforum/tpostreplyintervals')
BEGIN
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('时间间隔配置', 1233, 12, 'tpostreplyintervals', 'liveforum/tpostreplyintervals', 1, 0, 'C', '0', '0', 'tpostreplyintervals:list', 'time-range', 'admin', GETDATE(), 'admin', GETDATE(), '发帖回复时间间隔配置');
DECLARE @intervalMenuId BIGINT = SCOPE_IDENTITY();
PRINT '✓ 时间间隔配置菜单插入成功menuId: ' + CAST(@intervalMenuId AS VARCHAR);
-- 权限按钮
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('查询', @intervalMenuId, 1, '', NULL, 1, 0, 'F', '0', '0', 'tpostreplyintervals:list', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('编辑', @intervalMenuId, 2, '', NULL, 1, 0, 'F', '0', '0', 'tpostreplyintervals:edit', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
PRINT '✓ 时间间隔配置权限按钮插入成功 (查询/编辑)'
-- 为管理员角色分配权限
INSERT INTO sys_role_menu (Role_id, Menu_id, Create_time)
SELECT 1, menuId, GETDATE()
FROM sys_menu WHERE menuId >= @intervalMenuId;
PRINT '✓ 时间间隔配置菜单权限已分配给管理员角色'
END
ELSE
PRINT '⚠ 时间间隔配置菜单已存在,跳过'
PRINT ''
-- ##########################################################
-- 模块3: 防沉迷规则管理菜单
-- ##########################################################
PRINT '>>> 模块3: 防沉迷规则管理菜单'
PRINT ''
IF NOT EXISTS (SELECT 1 FROM sys_menu WHERE path = 'tantiaddictionrules' AND component = 'liveforum/tantiaddictionrules/index')
BEGIN
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('防沉迷规则', 1233, 13, 'tantiaddictionrules', 'liveforum/tantiaddictionrules/index', 1, 0, 'C', '0', '0', 'tantiaddictionrules:list', 'time-range', 'admin', GETDATE(), 'admin', GETDATE(), '防沉迷规则配置管理');
DECLARE @antiAddictionMenuId BIGINT = SCOPE_IDENTITY();
PRINT '✓ 防沉迷规则管理菜单插入成功menuId: ' + CAST(@antiAddictionMenuId AS VARCHAR);
-- 权限按钮
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('查询', @antiAddictionMenuId, 1, '#', NULL, 1, 0, 'F', '0', '0', 'tantiaddictionrules:query', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('新增', @antiAddictionMenuId, 2, '#', NULL, 1, 0, 'F', '0', '0', 'tantiaddictionrules:add', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('编辑', @antiAddictionMenuId, 3, '#', NULL, 1, 0, 'F', '0', '0', 'tantiaddictionrules:edit', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
INSERT INTO sys_menu (menuName, parentId, orderNum, path, component, isFrame, isCache, menuType, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
VALUES ('删除', @antiAddictionMenuId, 4, '#', NULL, 1, 0, 'F', '0', '0', 'tantiaddictionrules:delete', '#', 'admin', GETDATE(), 'admin', GETDATE(), NULL);
PRINT '✓ 防沉迷规则权限按钮插入成功 (查询/新增/编辑/删除)'
-- 为管理员角色分配权限
INSERT INTO sys_role_menu (Role_id, Menu_id, Create_time)
SELECT 1, menuId, GETDATE()
FROM sys_menu WHERE menuId >= @antiAddictionMenuId;
PRINT '✓ 防沉迷规则菜单权限已分配给管理员角色'
END
ELSE
PRINT '⚠ 防沉迷规则管理菜单已存在,跳过'
PRINT ''
-- ##########################################################
-- 配置完成
-- ##########################################################
PRINT '=========================================='
PRINT 'v1.2.0 管理库完整菜单配置脚本执行完成!'
PRINT '完成时间: ' + CONVERT(VARCHAR, GETDATE(), 120)
PRINT '=========================================='
PRINT ''
PRINT '配置内容总结:'
PRINT ' 模块1: CDK 管理菜单 (6个权限按钮: 查询/生成/删除/导出/设置/查询设置)'
PRINT ' 模块2: 时间间隔配置菜单 (2个权限按钮: 查询/编辑)'
PRINT ' 模块3: 防沉迷规则管理菜单 (4个权限按钮: 查询/新增/编辑/删除)'
PRINT ''
PRINT '注意: 所有菜单位于"系统配置"(parentId=1233)目录下'
PRINT ' 需要刷新浏览器或重新登录才能看到新菜单'
PRINT '=========================================='

View File

@ -13,9 +13,9 @@ var Config = Config || {}
// Config.API_BASE_URL = 'http://localhost:8080'
// Config.API_BASE_URL = 'https://liveforum.api.zpc-xy.com'
// Config.API_BASE_URL = 'http://192.168.195.15:2408' // 备用地址
// Config.API_BASE_URL = 'https://api.skzhijia.com' // 现网地址
Config.API_BASE_URL = 'https://api.skzhijia.com' // 现网地址
Config.API_BASE_URL = 'https://api.xkx.shhmkjgs.cn' // 备用地址
// Config.API_BASE_URL = 'https://api.xkx.shhmkjgs.cn' // 备用地址
// Config.API_BASE_URL = 'http://175.27.168.122:82' // 备用地址
@ -45,8 +45,8 @@ Config.UPLOAD_CONFIG = {
videoMaxSize: 100 * 1024 * 1024, // 100MB
// COS域名如果使用COS上传
cosDomain: 'https://miaoyu-1308826010.cos.ap-shanghai.myqcloud.com'
// cosDomain: 'https://skzjmp-1377391978.cos.ap-nanjing.myqcloud.com'
// cosDomain: 'https://miaoyu-1308826010.cos.ap-shanghai.myqcloud.com'
cosDomain: 'https://skzjmp-1377391978.cos.ap-nanjing.myqcloud.com'
}
// 不同场景的上传配置预设