diff --git a/Dockerfile b/Dockerfile index 0208fd6..48d801b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -86,7 +86,7 @@ RUN test -s "/app/public/brand/header-logo.png" && \ test -f "/app/prisma/migrations/20260824_expand_ding_workflow_insights/migration.sql" && \ test -f "/app/prisma/migrations/20260826_add_ding_workflow_demand_type/migration.sql" && \ test -f "/app/prisma/migrations/20260827_add_ding_workflow_detail_fields/migration.sql" && \ - test -f "/app/prisma/migrations/20260826_add_user_video_early_access/migration.sql" + test -f "/app/prisma/migrations/20260826_add_pack_video_early_access/migration.sql" # 这两个动态路由负责兜底访问本地上传文件;如果它们在构建上下文里丢失, # 线上音频/视频就会直接 404。这里提前失败,避免再把缺路由的镜像发出去。 @@ -205,7 +205,7 @@ COPY --from=builder --chown=root:root /app/prisma/migrations/20260820_add_ding_w COPY --from=builder --chown=root:root /app/prisma/migrations/20260824_expand_ding_workflow_insights ./prisma/migrations/20260824_expand_ding_workflow_insights COPY --from=builder --chown=root:root /app/prisma/migrations/20260826_add_ding_workflow_demand_type ./prisma/migrations/20260826_add_ding_workflow_demand_type COPY --from=builder --chown=root:root /app/prisma/migrations/20260827_add_ding_workflow_detail_fields ./prisma/migrations/20260827_add_ding_workflow_detail_fields -COPY --from=builder --chown=root:root /app/prisma/migrations/20260826_add_user_video_early_access ./prisma/migrations/20260826_add_user_video_early_access +COPY --from=builder --chown=root:root /app/prisma/migrations/20260826_add_pack_video_early_access ./prisma/migrations/20260826_add_pack_video_early_access COPY --from=builder --chown=nextjs:nodejs /app/lib ./lib COPY --from=builder --chown=nextjs:nodejs /app/scripts/public-traffic-rollup-from-nginx.py ./scripts/public-traffic-rollup-from-nginx.py COPY --from=builder --chown=nextjs:nodejs /app/scripts/collapse-performance-survey-template-versions.mjs ./scripts/collapse-performance-survey-template-versions.mjs diff --git a/app/api/admin/users/route.ts b/app/api/admin/users/route.ts index a9b13ae..6cb969c 100644 --- a/app/api/admin/users/route.ts +++ b/app/api/admin/users/route.ts @@ -22,7 +22,6 @@ export async function GET() { isActive: true, // 保留,向后兼容 status: true, // 新增:用户状态(阶段一) canDownload: true, - videoEarlyAccess: true, // 视频提前访问豁免(仅超管可开关) department: true, // 保留,向后兼容 departmentId: true, // 新增:部门ID(阶段二) managedDepartment: true, // 管理员负责的部门 diff --git a/app/api/admin/users/toggle-video-early-access/route.ts b/app/api/admin/users/toggle-video-early-access/route.ts deleted file mode 100644 index a397f97..0000000 --- a/app/api/admin/users/toggle-video-early-access/route.ts +++ /dev/null @@ -1,64 +0,0 @@ -// 切换用户「视频提前访问」豁免API(跳过视频类素材 15 天保护期) -// 仅超级管理员可操作,与"设为管理员"同级的高敏感授权。 -import { NextRequest, NextResponse } from 'next/server'; -import { getServerSession } from 'next-auth'; -import { authOptions } from '@/lib/auth'; -import { prisma } from '@/lib/prisma'; - -// POST - 切换视频提前访问豁免(仅超级管理员) -export async function POST(request: NextRequest) { - try { - const session = await getServerSession(authOptions); - if (!session?.user || !(session.user as any).id) { - return NextResponse.json( - { error: '未登录' }, - { status: 401 } - ); - } - - if (!(session.user as any).isSuperAdmin) { - return NextResponse.json( - { error: '仅超级管理员可操作' }, - { status: 403 } - ); - } - - const { userId } = await request.json(); - - if (!userId) { - return NextResponse.json( - { error: '缺少用户ID' }, - { status: 400 } - ); - } - - const user = await prisma.user.findUnique({ - where: { id: userId }, - }); - - if (!user) { - return NextResponse.json( - { error: '用户不存在' }, - { status: 404 } - ); - } - - const updatedUser = await prisma.user.update({ - where: { id: userId }, - data: { videoEarlyAccess: !user.videoEarlyAccess }, - }); - - return NextResponse.json({ - message: updatedUser.videoEarlyAccess - ? '已开启视频提前访问(跳过 15 天保护期)' - : '已关闭视频提前访问(恢复 15 天保护期)', - videoEarlyAccess: updatedUser.videoEarlyAccess, - }); - } catch (error) { - console.error('Error toggling video early access:', error); - return NextResponse.json( - { error: '操作失败' }, - { status: 500 } - ); - } -} diff --git a/app/api/organization/permission-groups/route.ts b/app/api/organization/permission-groups/route.ts index 7276951..19b73c0 100644 --- a/app/api/organization/permission-groups/route.ts +++ b/app/api/organization/permission-groups/route.ts @@ -69,6 +69,7 @@ export async function GET() { id: true, slug: true, name: true, + videoEarlyAccess: true, items: { select: { materialType: true, @@ -170,6 +171,7 @@ export async function GET() { groups: packs.map((pack) => ({ slug: pack.slug, name: pack.name, + videoEarlyAccess: pack.videoEarlyAccess, permissions: packItemsToMap(pack.items), departments: (departmentsByPack.get(pack.id) || []).map((path) => ({ path, @@ -232,6 +234,15 @@ export async function PUT(request: NextRequest) { return NextResponse.json({ ok: true }) } + if (action === 'set-video-early-access') { + const enabled = body?.enabled === true + await prisma.materialPermissionPack.update({ + where: { id: pack.id }, + data: { videoEarlyAccess: enabled }, + }) + return NextResponse.json({ ok: true, videoEarlyAccess: enabled }) + } + if (action === 'delete') { await prisma.$transaction([ prisma.userPermissionInherit.deleteMany({ where: { packId: pack.id } }), diff --git a/components/department-dashboard/PermissionGroupsDashboard.tsx b/components/department-dashboard/PermissionGroupsDashboard.tsx index fb2415e..8b4c0ce 100644 --- a/components/department-dashboard/PermissionGroupsDashboard.tsx +++ b/components/department-dashboard/PermissionGroupsDashboard.tsx @@ -30,6 +30,7 @@ type Member = { type Group = { slug: string name: string + videoEarlyAccess?: boolean permissions: Record departments: Array<{ path: string; name: string }> members: Member[] @@ -464,6 +465,35 @@ export default function PermissionGroupsDashboard() { 部门进组是底子,人进组是加餐。没单独进组的下级,跟着最近的上级组走。

+
+
+

视频提前访问

+

+ 开启后,本组成员不受视频类素材 15 天保护期限制 +

+
+ +