gongxiangp2/components/UpdateLogModal.tsx
2026-08-16 11:33:42 +08:00

1278 lines
52 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

'use client'
import { useEffect, useRef, useState } from 'react'
// 更新日志配置 - 每次有新功能或优化时更新这个版本号
const CURRENT_VERSION = '2026.07.04'
const STORAGE_KEY = 'update_log_viewed_version_20260704'
interface UpdateItem {
type: 'feature' | 'improvement' | 'fix' // 新功能、优化、修复
title: string
description: string
}
interface UpdateLog {
version: string
date: string
title: string
items: UpdateItem[]
}
// 更新日志内容 - 通俗易懂,面向客户
// 注意:只有经过测试验证的功能才会添加到更新记录中
const UPDATE_LOGS: UpdateLog[] = [
{
version: '2026.07.04',
date: '2026-07-04',
title: '系统更新',
items: [
{
type: 'feature',
title: '新增公网流量统计看板',
description:
'超级管理员后台新增“公网流量”入口,可以按今天、近 7 天、近 30 天或自定义日期查看外网入口流量,包含总流量、请求次数、访问域名、每日趋势和高消耗资源,方便核对按流量计费服务器的使用情况。'
},
{
type: 'improvement',
title: '流量来源改成人能看懂的用途',
description:
'流量明细不再只展示接口路径,会自动识别素材下载、图片直链访问、历史上传资源、直传资源、后台管理、账号登录、产品设计平台和外部接口等用途。需要排查时仍可展开查看原始路径。'
},
{
type: 'improvement',
title: '高流量资源更容易定位',
description:
'高消耗资源从普通表格改为排行展示,会显示用途名称、资源类型、流量占比和请求次数,方便快速判断是哪类图片、下载或接口消耗了公网流量。'
},
{
type: 'improvement',
title: '流量统计结果会自动缓存',
description:
'公网流量统计结果会固化在系统内,重复打开页面时优先读取缓存,不再每次重新扫描全部入口日志;缓存过期时会在后台刷新,页面打开速度更稳定。'
},
{
type: 'improvement',
title: '流量看板前端重新整理',
description:
'公网流量页面改为看板式布局,顶部展示总量和峰值日,中间展示来源分布,底部展示每日趋势。信息层级更清楚,减少“表格堆在一起”的阅读压力。'
},
{
type: 'improvement',
title: '网速显示统一优化',
description:
'上传面板、白底图上传、网络诊断和系统性能气泡中的速度、容量、剩余大小统一改成类似“21.3 MB/s、42.6 MB/967 MB”的显示方式,读起来更直观。'
}
]
},
{
version: '2026.07.03',
date: '2026-07-03',
title: '系统更新',
items: [
{
type: 'feature',
title: '考核调研接入素材库',
description:
'头像菜单新增“考核调研”入口,原来的独立考核页面开始改造成素材库原生页面,使用素材库当前登录状态进入,不再保留单独的邮箱密码登录和独立管理员登录。'
},
{
type: 'feature',
title: '考核流程支持待评价、发起和结果查看',
description:
'考核调研首页新增“待我评价”“我发起的”“我的结果”“管理”视图。普通员工可以填写分配给自己的评价,发起人和管理员可以发布、关闭并查看结果。'
},
{
type: 'feature',
title: '支持人员考核和事项调研',
description:
'创建调研时可以选择人员周期考核,也可以创建课程、事项或活动类调研。一个调研可包含多个被评价对象,每个对象独立统计评价结果。'
},
{
type: 'improvement',
title: '考核人员资料更准确',
description:
'考核模块新增独立人员档案,从花名册和钉钉相关资料中同步花名、真实姓名、部门、岗位、P/M 职级、在职状态等信息,不再直接依赖素材库里不准确的旧人员资料。'
},
{
type: 'improvement',
title: '部门快选改为组织层级',
description:
'创建考核调研时,部门选择不再把所有部门平铺展示,会按组织路径整理,方便从部门结构里快速选择评价对象或评价人。'
},
{
type: 'feature',
title: '考核调研支持钉钉工作通知',
description:
'发布调研、结果可查看、发起人需要跟进时,会生成钉钉工作通知投递记录;后台可以查看通知状态,并对失败通知进行补发。'
},
{
type: 'fix',
title: '人员同步范围更克制',
description:
'考核人员同步会优先匹配素材库已有账号,只同步当前系统里有关联账号的人员,避免把花名册里的所有人员都一次性拉进素材库。'
},
{
type: 'fix',
title: '清除缓存范围更安全',
description:
'头像菜单中的“清除缓存并刷新”只清理素材库相关缓存,避免影响用户浏览器里的其他网站数据。'
}
]
},
{
version: '2026.07.01',
date: '2026-07-01',
title: '系统更新',
items: [
{
type: 'feature',
title: '新增视频素材查询接口',
description:
'外部系统可以通过一个关键词查询视频素材,系统会依次按产品条码、SKU 名称和 SPU 型号查找,返回封面、预览、时长、上传时间和下载链接,方便其它业务平台接入视频素材。'
},
{
type: 'improvement',
title: '视频素材保护期规则补齐',
description:
'脉象素材接口和新的视频查询接口都补上 15 天保护期规则。保护期内会返回“还需约几天可用”的说明,不再直接给出下载链接。'
},
{
type: 'improvement',
title: '视频查询结果更完整',
description:
'视频查询结果会区分可下载和暂不可下载状态,并返回封面图、预览片段、完整预览、文件大小和素材类型,调用方不用再自己拼接素材地址。'
},
{
type: 'fix',
title: '外部接口查询记录更清楚',
description:
'视频查询接口会记录调用结果、查询关键词、耗时和错误原因,管理员后续排查外部平台调用问题时更容易定位。'
}
]
},
{
version: '2026.06.27',
date: '2026-06-27',
title: '系统更新',
items: [
{
type: 'improvement',
title: '数据统计趋势展示升级',
description:
'后台数据统计增加趋势折线图,可以按日或按月查看上传量变化,快速看出近期上传是否增长、下降或集中在某几天。'
},
{
type: 'improvement',
title: '统计图表支持更清晰的阅读',
description:
'趋势图支持高亮数据点和悬停查看明细,搭配部门、人员和素材类型统计,管理员可以更快判断上传来源和变化趋势。'
},
{
type: 'improvement',
title: '部署过程的异常提示更明确',
description:
'优化发布脚本的异常输出方式,部署时如果出现问题,会更容易看到真实错误信息,减少排查时间。'
}
]
},
{
version: '2026.06.26',
date: '2026-06-26',
title: '系统更新',
items: [
{
type: 'improvement',
title: '数据统计面板重新整理',
description:
'后台数据统计页面重新梳理了顶部汇总、部门分布、素材类型分布和人员明细,管理员查看数据时不用在多个区域之间来回找重点。'
},
{
type: 'feature',
title: '统计支持按部门继续下钻',
description:
'部门和素材类型统计可以进一步展开查看对应人员明细,方便定位是哪个部门、哪些人员贡献了上传量。'
},
{
type: 'fix',
title: '操作日志搜索更完整',
description:
'修复后台操作日志关键词搜索结果被截断的问题,搜索素材型号、人员或操作内容时能看到更完整的匹配记录。'
}
]
},
{
version: '2026.06.22',
date: '2026-06-22',
title: '系统更新',
items: [
{
type: 'fix',
title: '标准模型白底图预览补齐',
description:
'修复部分标准模型白底图只有原图、没有预览图的问题。后续上传白底图时会同步生成适合页面展示的预览图,外部接口和详情页看到的图片更稳定。'
},
{
type: 'improvement',
title: 'SPU 缺少预览图时自动补上',
description:
'标准模型 SPU 如果还没有预览图,系统会优先使用右前 45° 白底图作为 SPU 预览图,让新建的标准模型在首页和列表里不再空白。'
},
{
type: 'improvement',
title: '白底图预览和下载分工更清楚',
description:
'白底图会同时保留原图级下载文件和页面预览图,页面加载更轻,下载时仍能拿到完整质量的文件。'
}
]
},
{
version: '2026.06.15',
date: '2026-06-15',
title: '系统更新',
items: [
{
type: 'feature',
title: '产品设计平台白底图录入',
description:
'新增产品设计平台回传白底图的接口,当前只处理“标准模型”素材类型下的白底图。产品平台传入 SPU、SKU、产品条码、出图方式和图片后,素材库会把图片录入到对应 SKU 下。'
},
{
type: 'feature',
title: '已有 SPU 和新 SPU 都能处理',
description:
'如果标准模型里已经有对应 SPU,会在该 SPU 下查找或新建 SKU 后录入白底图;如果没有该 SPU,会要求传入产品品类,先新建标准模型 SPU,再新建 SKU。'
},
{
type: 'fix',
title: 'SPU、SKU 和条码关系校验更严格',
description:
'接口会检查产品条码是否已经绑定到其它 SKU,也会避免同名 SKU 被错误写入到别的标准模型里,减少 SPU 和 SKU 混用导致的数据错乱。'
},
{
type: 'improvement',
title: '外部录入支持重复请求保护',
description:
'产品平台重复提交同一个请求时,素材库可以识别并返回已有处理结果,降低网络重试造成重复写入的风险。'
}
]
},
{
version: '2026.06.08',
date: '2026-06-08',
title: '系统更新',
items: [
{
type: 'feature',
title: '产品条码白底图接口',
description:
'标准模型白底图新增按产品条码录入能力,外部系统只要传入产品条码、出图方式和白底图,就能定位到对应 SKU 并写入白底图。'
},
{
type: 'feature',
title: '支持固定视角和补充图片',
description:
'白底图接口支持右前 45°、左前 45°、正视图、背视图等固定视角,也支持额外补充图片,方便一次性保存更完整的 SKU 白底图资产。'
},
{
type: 'improvement',
title: '白底图上传逻辑统一',
description:
'后台手动上传和外部接口上传开始复用同一套白底图处理逻辑,上传记录、出图方式、预览图和完整度统计保持一致。'
},
{
type: 'fix',
title: '接口重试不再重复写入',
description:
'外部系统如果因为网络原因重试同一笔白底图上传,素材库会按请求编号识别重复请求,避免同一批图片被重复录入。'
}
]
},
{
version: '2026.05.29',
date: '2026-05-29',
title: '系统更新',
items: [
{
type: 'fix',
title: '视频预览访问同步保护',
description:
'修复受保护视频仍可能通过预览地址访问的问题。视频卡片、分享页、详情接口和直链访问都会统一遵守保护期规则,未到期的视频不会提前展示预览。'
},
{
type: 'fix',
title: '受保护视频不再暴露源文件',
description:
'保护期内的视频会隐藏源文件地址、预览片段和播放地址,只保留必要的素材信息和可用时间提示。'
}
]
},
{
version: '2026.05.27',
date: '2026-05-27',
title: '系统更新',
items: [
{
type: 'fix',
title: '公网分片上传更稳定',
description:
'优化公网环境下的大文件分片上传,调整分片大小、超时时间和并发策略,降低弱网、穿透网络或长时间上传时失败的概率。'
},
{
type: 'improvement',
title: '批量上传进度更可靠',
description:
'批量上传时会更稳定地维护每个文件的上传状态,减少上传中断后进度错乱、重复上传或状态不更新的问题。'
},
{
type: 'improvement',
title: '上传异常更容易恢复',
description:
'上传遇到网络抖动时,系统会更合理地重试和续传,避免一个分片失败就影响整批素材上传。'
}
]
},
{
version: '2026.05.25',
date: '2026-05-25',
title: '系统更新',
items: [
{
type: 'feature',
title: '视频素材下载保护',
description:
'新上传的视频素材增加 15 天下载保护期,保护期内下载按钮会给出明确提示,避免还未确认或还在流转中的视频被提前下载使用。'
},
{
type: 'fix',
title: '任务详情打包文件名更稳定',
description:
'修复任务详情素材打包下载时不同目录里同名文件相互覆盖的问题,系统会自动处理重复名称,解压后文件更完整。'
},
{
type: 'improvement',
title: '下载限制提示更明确',
description:
'受保护视频无法下载时会显示剩余等待时间,让使用者知道不是系统故障,而是素材还没到开放下载时间。'
}
]
},
{
version: '2026.05.21',
date: '2026-05-21',
title: '系统更新',
items: [
{
type: 'fix',
title: '脉象素材查询更准确',
description:
'脉象平台查询素材时会更贴近素材库首页的搜索规则,按 SPU、素材类型、权限范围和可见状态统一过滤,减少首页能搜到、接口却查不到的情况。'
},
{
type: 'improvement',
title: '脉象接口返回内容更贴近日常使用',
description:
'脉象接口会按素材库现有可下载规则返回素材,不再把被删除、无权限或不适合外部下载的素材混进结果里。'
},
{
type: 'fix',
title: '外部查询和首页搜索口径统一',
description:
'把外部查询和首页查询的底层筛选逻辑统一到同一套规则,后续维护权限和素材类型时更不容易出现两边结果不一致。'
}
]
},
{
version: '2026.05.15',
date: '2026-05-15',
title: '系统更新',
items: [
{
type: 'improvement',
title: '首页筛选与权限保持一致',
description:
'首页筛选项会根据当前用户真正能看到的素材范围生成,分类、场景、平台、产品品类和素材类型都不再简单展示全部选项,减少点了筛选却没有结果的情况。'
},
{
type: 'feature',
title: '筛选数量和结果统计更准确',
description:
'新增专门的筛选项统计能力,筛选面板可以展示各筛选项对应的素材数量,帮助用户更快判断应该点哪个条件。'
},
{
type: 'improvement',
title: '首页查询逻辑统一整理',
description:
'首页素材列表、搜索建议、统计数量和可见素材类型统一使用同一套查询规则,减少列表、筛选和统计之间互相对不上的情况。'
}
]
},
{
version: '2026.05.14',
date: '2026-05-14',
title: '系统更新',
items: [
{
type: 'fix',
title: '源文件下载权限继承修复',
description:
'修复部门权限继承后“源文件下载”没有跟随继承的问题。管理员在配置上级部门权限后,下级部门能正确继承查看、下载、分享和源文件下载能力。'
},
{
type: 'improvement',
title: '权限配置页面提示更清楚',
description:
'部门权限页面补齐源文件下载相关展示,让管理员能直接看到各部门是否具备下载源文件的权限。'
},
{
type: 'fix',
title: '批量和复制权限保持一致',
description:
'批量设置、复制权限和继承权限都补齐源文件下载字段,避免不同配置入口保存出来的权限不一致。'
}
]
},
{
version: '2026.05.13',
date: '2026-05-13',
title: '系统更新',
items: [
{
type: 'feature',
title: '新增脉象 SPU 素材接口',
description:
'新增面向脉象平台的 SPU 素材查询接口,外部平台可以按 SPU 获取素材库里的可用素材,用于业务系统自动取图、下载或分析。'
},
{
type: 'feature',
title: '按素材类型返回可下载资源',
description:
'接口会返回素材类型、文件信息、预览图和下载地址,调用方可以根据素材类型决定后续使用方式。'
},
{
type: 'improvement',
title: '外部接口文档同步补齐',
description:
'同步补充脉象平台对接文档,明确请求方式、字段含义、返回内容和常见错误,减少对接时反复沟通。'
}
]
},
{
version: '2026.05.11',
date: '2026-05-11',
title: '系统更新',
items: [
{
type: 'feature',
title: '任务详情支持无条码开关',
description:
'任务详情上传流程增加“无条码”场景支持,遇到暂时没有产品条码的素材也可以先完成入库,后续再补齐条码信息。'
},
{
type: 'improvement',
title: '上传面板信息更紧凑',
description:
'任务详情上传面板重新整理了任务号、SPU、条码、主图、SKU 图、详情图等区域的信息密度,减少重复说明,让上传人员更容易按步骤完成录入。'
},
{
type: 'improvement',
title: '历史素材导入能力补全',
description:
'补充历史素材扫描、导入、校验和结果复核工具,方便把旧目录里的主图、SKU 图、详情图和预览图按新的任务详情规则逐步迁入素材库。'
},
{
type: 'improvement',
title: '远端上传文件同步更稳',
description:
'任务详情上传流程补齐远端文件同步和路径整理能力,减少文件已经上传但素材记录缺失、路径不统一导致的下载问题。'
}
]
},
{
version: '2026.04.22',
date: '2026-04-22',
title: '系统更新',
items: [
{
type: 'feature',
title: '产品平台条码图片对接',
description:
'任务详情素材新增产品条码图片对接能力,可以把任务详情里的条码图片、主图和相关预览提供给产品平台使用,减少产品平台重复找图和手动上传。'
},
{
type: 'feature',
title: '新增淘宝链接查询入口',
description:
'顶部栏新增淘宝商品链接查询入口,粘贴商品链接后可以快速获取关联信息,方便运营或素材整理人员从商品链接反查素材线索。'
},
{
type: 'improvement',
title: '任务详情条码保存更完整',
description:
'任务详情上传时会保存条码、条码图片和关联的任务信息,为后续产品平台按条码拉取图片提供稳定数据。'
},
{
type: 'improvement',
title: '外部通知事件更细分',
description:
'自动通知能力新增面向产品平台的条码图片更新事件,外部系统可以区分整套任务详情完成和条码图片更新这两类通知。'
}
]
},
{
version: '2026.03.25',
date: '2026-03-25',
title: '系统更新',
items: [
{
type: 'feature',
title: 'AI 生图白底图回传能力',
description:
'标准模型白底图链路支持 AI 生图平台回传,外部平台可以把生成好的白底图写入素材库,并按固定视角和补充图片分类保存。'
},
{
type: 'feature',
title: '自动上架平台通知',
description:
'任务详情整套素材完成后可以自动通知外部上架平台,管理员可以在后台配置通知目标、查看投递记录,并对失败通知手动补发。'
},
{
type: 'improvement',
title: '白底图下载和预览链路完善',
description:
'白底图相关接口、详情页、分享页、下载和预览逻辑进一步统一,减少不同入口看到的白底图数量、视角和下载结果不一致的问题。'
},
{
type: 'feature',
title: '外部素材导入任务可查询',
description:
'新增外部素材导入任务记录,外部系统提交导入后可以查询处理状态,方便确认素材是否已经进入素材库。'
},
{
type: 'improvement',
title: 'AI 生成素材标记更完整',
description:
'素材数据补齐 AI 生成标记,后续可以在筛选、接口返回和业务统计中区分人工上传与 AI 生成素材。'
}
]
},
{
version: '2026.03.14',
date: '2026-03-14',
title: '系统更新',
items: [
{
type: 'fix',
title: '标准模型白底图上传修复',
description:
'修复标准模型 SKU 白底图上传、下载和批量下载中的异常情况,SKU 下的白底图、模型文件和压缩包可以更稳定地保存和下载。'
},
{
type: 'improvement',
title: '标准模型分享页体验补齐',
description:
'标准模型分享页补齐 SKU 列表、白底图展示和批量下载能力,分享给同事后也能按 SKU 查看和下载对应白底图。'
},
{
type: 'fix',
title: 'SKU 名称唯一性校验补齐',
description:
'标准模型下的 SKU 名称校验更严格,避免不同标准模型之间出现重复 SKU 后导致外部查询和下载时无法判断归属。'
},
{
type: 'improvement',
title: '登录和访问地址更稳定',
description:
'优化登录后的访问地址识别,内网、公网和分享页之间跳转更稳定,减少跳到错误域名或地址的情况。'
}
]
},
{
version: '2026.02.03',
date: '2026-02-03',
title: '系统更新',
items: [
{
type: 'fix',
title: '批量上传稳定性修复',
description:
'修复批量上传流程中的若干问题,多文件连续上传时更稳定,单个文件失败后不会轻易影响整批任务,失败提示也更明确。'
},
{
type: 'fix',
title: '视频文件扩展名识别修复',
description:
'修复部分视频文件因为扩展名识别不准确而无法正确上传、预览或播放的问题,视频素材入库更稳。'
},
{
type: 'feature',
title: '搜索建议体验增强',
description:
'首页搜索增加建议提示和关键词高亮,查找 SPU、素材名称、分类等内容时更容易定位到目标素材。'
},
{
type: 'improvement',
title: '后台素材管理更适合批量操作',
description:
'后台素材管理页补齐批量删除和列表状态处理能力,管理员处理大量素材时更省事,也更容易看到操作结果。'
},
{
type: 'improvement',
title: '临时文件清理能力增强',
description:
'上传和处理中产生的临时文件会更及时地被识别和清理,减少无用文件长期占用服务器空间。'
}
]
},
{
version: '2026.01.28',
date: '2026-01-28',
title: '系统更新',
items: [
{
type: 'improvement',
title: '上传界面和性能优化',
description:
'优化多种素材上传界面的交互和性能,3D 原图、AI 原图、实拍图、视频截图、任务页和商品套包等上传入口的状态显示更一致。'
},
{
type: 'improvement',
title: '分片上传更适合大文件',
description:
'优化分片大小、上传会话保留时间和网络传输策略,大文件上传更可靠,长时间上传或中途重试时更容易续上。'
},
{
type: 'improvement',
title: '网速显示更平稳',
description:
'上传过程中的速度显示降低刷新频率,减少数字快速跳动,上传进度、剩余时间和当前速度更容易看清。'
},
{
type: 'feature',
title: '系统健康检查增强',
description:
'系统健康检查补齐磁盘、配置、存储连接、转码队列等状态,管理员排查上传、下载或转码异常时能更快知道问题位置。'
},
{
type: 'fix',
title: '下载和转码异常更容易恢复',
description:
'优化下载、点赞、转码、预览生成等环节的错误处理,异常时会给出更稳定的提示,并减少处理中断后的残留状态。'
}
]
},
{
version: '2.2.41',
date: '2026-01-21',
title: '系统更新',
items: [
{
type: 'feature',
title: '任务-详情素材类型',
description:
'新增"任务-详情"素材类型,用于整合一个产品的完整电商视觉资产。支持上传主图、SKU图、详情预览图和PSD源文件,可按类型分类下载(全部/主图/SKU图/详情图/PSD)。上传时需填写任务号和SPU型号,详情页支持拖拽排序调整详情图顺序。任务-详情图片保持原图质量,不做压缩处理,确保素材完整性。'
},
{
type: 'feature',
title: '外部接口对接功能',
description:
'任务-详情支持外部系统对接,任务系统可通过任务号查询、下载和删除任务-详情素材。管理员可在后台管理API密钥,查看接口调用日志,方便监控和管理外部访问。'
},
{
type: 'fix',
title: '退出登录后正确跳转到登录页',
description:
'修复退出登录后跳转到 localhost 的问题,现在退出登录会正确返回到当前域名的登录页面,无论是内网还是外网访问都能正常工作。'
}
]
},
{
version: '2.2.4',
date: '2025-12-29',
title: '系统更新',
items: [
{
type: 'feature',
title: '性能监控面板',
description:
'在"公网/内网"按钮上新增性能监控功能,鼠标悬停即可查看系统实时性能。显示CPU使用率、内存使用情况、上传队列和转码队列状态,转码队列还会显示任务详情(文件名、类型、上传人、进度等),方便了解系统运行状态。'
},
{
type: 'feature',
title: '标准模型素材类型',
description:
'新增"标准模型"素材类型,支持上传标准模型素材。标准模型素材文件可选,但必须上传预览图,支持后续添加SKU进行扩展。'
},
{
type: 'feature',
title: '统一批量上传功能',
description:
'统一了所有素材类型的批量上传逻辑,无论是通过"选择文件"按钮还是拖拽文件,都使用相同的批量上传流程。支持音乐、视频、3D场景、品牌VI等多种素材类型的批量上传,每个文件可独立设置SPU型号,上传进度清晰可见。'
},
{
type: 'improvement',
title: '上传体验大幅提升',
description:
'所有素材类型的上传流程优化,上传完成后立即关闭上传弹窗,不再等待后台处理(如视频转码)。转码等后台任务在后台异步进行,首页素材卡片会显示转码状态和进度,上传和转码完全分离,体验更流畅。'
},
{
type: 'improvement',
title: '上传进度显示优化',
description:
'修复了上传弹窗中进度条重复显示的问题,现在单文件上传只显示一个进度条,批量上传显示总进度和当前文件进度,界面更清晰。'
},
{
type: 'improvement',
title: '转码任务自动清理',
description:
'视频转码任务入队失败时,系统会自动清理源视频文件,避免产生大体积垃圾文件占用存储空间。'
},
{
type: 'fix',
title: '性能监控数据更准确',
description:
'修复了性能监控中CPU使用率和内存统计不准确的问题,现在使用更精确的计算方法,数据与系统实际状态一致。修复了上传队列显示已完成任务的问题,现在只显示真正进行中的上传任务。'
}
]
},
{
version: '2.2.32',
date: '2025-12-19',
title: '系统更新',
items: [
{
type: 'feature',
title: '标准模型 SKU 功能',
description:
'新增标准模型素材类型,支持以产品型号(SPU)为基准创建模型合集。每个标准模型可添加多个 SKU(如不同颜色、尺寸的款式),支持单选、多选或全选下载。上传时只需填写 SPU 型号和预览图,SKU 可后续添加。详情页右侧显示 SKU 列表,支持拖拽上传、排序调整,操作更便捷。'
},
{
type: 'improvement',
title: '上传超大原图自动优化',
description:
'上传预览图时,系统会自动处理超大原图(如相机拍摄的照片)。自动调整到合适大小并压缩,上传更快,加载更流畅,显示效果不变。'
}
]
},
{
version: '2.2.31',
date: '2025-12-18',
title: '系统更新',
items: [
{
type: 'fix',
title: '模特类素材支持正常下载',
description:
'修复模特类素材卡片下载按钮可点但无法下载的问题,现在会自动将模特素材的展示图打包成压缩包,老数据也会补齐可下载文件。'
},
{
type: 'fix',
title: '首页按素材类型筛选后返回不再错乱',
description:
'修复在首页选择“模特”等素材类型后进入详情再返回时,后续瀑布流会混入其他类型素材的问题,现在返回后会完整恢复原来的筛选条件和浏览位置。'
}
]
},
{
version: '2.2.3',
date: '2025-12-17',
title: '系统更新',
items: [
{
type: 'feature',
title: '新增"提交反馈"入口',
description:
'在头像下拉菜单中新增"提交反馈"入口,点击可直接跳转到钉钉文档提交功能建议、优化意见或Bug反馈,帮助我们持续改进系统。'
},
{
type: 'feature',
title: '首页筛选项可折叠收起',
description:
'首页筛选区域新增折叠功能,默认收起,点击可展开。收起时显示已选筛选数量,界面更简洁,浏览素材更专注。'
},
{
type: 'feature',
title: '新增产品类别筛选',
description: '首页新增"产品类别"筛选项,支持按书桌、书架、椅子等产品类型筛选素材,查找更精准。'
},
{
type: 'fix',
title: '详情页返回后不再跳到顶部',
description: '修复从素材详情页返回首页后自动跳到顶部的问题,现在会保持原来的浏览位置。'
},
{
type: 'fix',
title: '搜索输入不再频繁刷新',
description: '修复搜索栏输入一个字就刷新页面的问题,现在输入完成后才会触发搜索,体验更流畅。'
},
{
type: 'fix',
title: '滚动后素材预览图正常显示',
description: '修复向下滚动一段距离后部分素材卡片预览图不显示的问题,现在所有卡片都能正常加载预览图。'
}
]
},
{
version: '2.2.2',
date: '2025-12-10',
title: '系统更新',
items: [
{
type: 'fix',
title: '瀑布流返回定位更精准',
description: '修复浏览多页后进入素材详情返回会跳到错误位置或顶部的问题,返回时自动补拉数据并定位到原卡片。'
},
{
type: 'improvement',
title: '瀑布流单一模式与筛选显示优化',
description: '首页固定使用瀑布流布局,移除分页切换;“当前筛选”不再展示素材类型,筛选提示更简洁。'
},
{
type: 'feature',
title: '排序支持正/倒序切换',
description: '“最新上传 / 下载最多”均可切换正序或倒序,满足不同浏览习惯。'
},
{
type: 'improvement',
title: '默认标签改为“3D场景”',
description: '首页默认展示 3D 场景素材,方便快速浏览核心内容。'
}
]
},
{
version: '2.2.1',
date: '2025-12-09',
title: '系统更新',
items: [
{
type: 'feature',
title: '网络诊断功能',
description: '新增网络诊断功能,支持下载和上传测速,自动检测存储服务连通性,结果可复制分享,方便排查网络问题。'
},
{
type: 'improvement',
title: '下载体验大幅提升',
description: '大文件下载支持断点续传,下载更稳定、速度更快。下载后下载数立即更新,无需刷新页面即可看到最新数据,排行榜面板也会自动刷新。'
},
{
type: 'improvement',
title: '收藏功能体验优化',
description: '收藏/取消收藏操作后显示气泡提示,操作反馈更清晰。收藏状态在所有素材列表中正确显示,方便快速识别已收藏内容。'
},
{
type: 'improvement',
title: '素材卡片头像显示优化',
description: '作者头像尺寸增大,改为圆角方形样式,显示更清晰。优化显示逻辑,头像完整显示不被裁切,同时保持卡片高度不变。'
},
{
type: 'improvement',
title: '个人中心卡片更清晰',
description: '个人中心改为上下大卡片,分开展示"我的素材""我的收藏",信息一目了然。'
},
{
type: 'improvement',
title: '榜单悬浮窗体验优化',
description: '支持拖动、关闭后出现可拖动的迷你按钮可再打开,位置会记忆。拖拽无延迟,拖动更流畅。'
},
{
type: 'improvement',
title: '头像加载更稳定',
description: '优化头像加载与处理,解决头像不显示/加载慢的问题,统一压缩为 WebP 格式,优先加载。'
},
{
type: 'improvement',
title: '转码任务自动恢复',
description: '部署中断后自动恢复转码任务,清理残留文件,避免存储浪费。恢复时保持队列顺序,确保转码任务按顺序执行。'
},
{
type: 'fix',
title: '登录退出后能正常回到登录页',
description: '修正退出后偶尔跳到 localhost 的问题,现在会正确返回登录页。'
}
]
},
{
version: '2.2.0',
date: '2025-12-08',
title: '系统更新',
items: [
{
type: 'feature',
title: '个人中心上线',
description: '新增“我的素材 / 我的收藏”两个入口,卡片支持预览与视频弹窗,常用信息更聚合。'
},
{
type: 'feature',
title: '收藏(书签)按钮',
description: '卡片新增“收藏/取消收藏”书签按钮,和点赞清晰区分;收藏列表可在个人中心查看。'
},
{
type: 'feature',
title: '回收站与批量操作(管理员)',
description: '删除默认进入回收站;支持批量恢复与永久删除,关键操作留痕,误删可挽回。'
},
{
type: 'feature',
title: '头像上传与即时刷新',
description: '头像选择-预览-上传一体化,提交后标题栏头像即时更新,无需整页刷新。'
},
{
type: 'feature',
title: '一键复制分享链接',
description: '卡片操作区支持复制分享链接,便于把素材快速发给同事协作。'
},
{
type: 'improvement',
title: '收藏按钮样式与反馈优化',
description: '采用书签样式,未收藏/已收藏状态对比明显;悬停与点击反馈更清晰。'
},
{
type: 'improvement',
title: '转码失败一键重试',
description: '在卡片上即可重试转码,结合实时进度提示,处理更直观。'
},
{
type: 'improvement',
title: '预览视频编码与清晰度升级',
description: '预览视频改用 H.265 (HEVC) 编码,并提升分辨率与质量;画质更清晰。由于分辨率与质量目标提升,网络带宽占用与转码耗时会相应增加(弱网环境建议暂停自动播放)。'
},
{
type: 'fix',
title: '首页卡片稳定性修复',
description: '修复极端情况下预览区不渲染的问题,提升卡片加载稳定性。'
}
]
},
{
version: '2.1.6',
date: '2025-12-06',
title: '系统更新',
items: [
{
type: 'feature',
title: '素材类型标签',
description: '现在每个素材卡片的右上角都会显示素材类型标签(如"3DMAX"、"视频"等),不同颜色区分,让您一眼就能看出是什么类型的素材。'
},
{
type: 'feature',
title: '素材ID快速复制',
description: '素材卡片底部现在会显示完整的素材ID,点击ID就能一键复制到剪贴板,再也不用手动选择复制了!复制成功后会显示提示,非常方便。'
},
{
type: 'feature',
title: '视频素材卡片预览',
description: '视频素材在首页卡片上会自动播放10秒预览片段,转码完成后会显示预览视频而不是静态封面图。还会显示视频时长和转码进度,让您实时了解处理状态。'
},
{
type: 'improvement',
title: '视频转码速度大幅提升',
description: '优化了存储服务连接方式,视频转码速度更快了!之前转码可能会卡住的问题已经解决,现在转码过程更加稳定可靠。'
},
{
type: 'feature',
title: '新增"更新记录"菜单',
description: '在头像下拉菜单中新增了"更新记录"入口,您可以随时查看系统所有的历史更新,了解系统都做了哪些改进。'
},
{
type: 'improvement',
title: '优化复制提示位置',
description: '复制素材ID时的提示消息现在显示在页面顶部居中位置,不会再和标题栏重叠了,提示更加清晰明显。'
}
]
},
{
version: '2.1.5',
date: '2025-12-06',
title: '系统更新',
items: [
{
type: 'feature',
title: '视频转码实时进度显示',
description: '现在上传视频后,可以实时看到转码进度了!进度条会准确显示当前转码状态,让您清楚知道视频处理到哪一步了。'
},
{
type: 'improvement',
title: '视频上传稳定性大幅提升',
description: '优化了视频上传机制,即使网络不稳定也能可靠完成上传。系统会自动重试,确保您的视频素材不会丢失。'
},
{
type: 'improvement',
title: '视频预览播放更流畅',
description: '优化了视频预览播放体验,加载速度更快,播放更流畅。现在可以更顺畅地查看和预览视频素材了。'
},
{
type: 'fix',
title: '修复视频转码卡顿问题',
description: '修复了视频转码过程中可能出现的卡顿问题,现在转码过程更加稳定可靠,不会中途失败。'
},
{
type: 'feature',
title: '更新日志弹窗',
description: '新增了更新日志功能,每次系统有新功能或优化时,会自动弹出更新说明,让您及时了解系统改进。'
}
]
}
]
interface UpdateLogModalProps {
isOpen: boolean
onClose: () => void
updateLog?: UpdateLog // 可选,如果不传则显示所有历史记录
showAllHistory?: boolean // 是否显示所有历史记录
}
function UpdateLogModal({ isOpen, onClose, updateLog, showAllHistory = false }: UpdateLogModalProps) {
const dialogRef = useRef<HTMLDivElement>(null)
const closeButtonRef = useRef<HTMLButtonElement>(null)
useEffect(() => {
if (!isOpen) return
const previousOverflow = document.body.style.overflow
const previousFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null
const handleKeyDown = (event: KeyboardEvent) => {
if (event.key === 'Escape') {
onClose()
return
}
if (event.key !== 'Tab' || !dialogRef.current) return
const focusableElements = Array.from(
dialogRef.current.querySelectorAll<HTMLElement>('button:not([disabled]), [href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"])'),
)
const firstElement = focusableElements[0]
const lastElement = focusableElements[focusableElements.length - 1]
if (event.shiftKey && document.activeElement === firstElement) {
event.preventDefault()
lastElement?.focus()
} else if (!event.shiftKey && document.activeElement === lastElement) {
event.preventDefault()
firstElement?.focus()
}
}
document.body.style.overflow = 'hidden'
document.addEventListener('keydown', handleKeyDown)
closeButtonRef.current?.focus()
return () => {
document.body.style.overflow = previousOverflow
document.removeEventListener('keydown', handleKeyDown)
previousFocus?.focus()
}
}, [isOpen, onClose])
if (!isOpen) return null
// 如果showAllHistory为true,显示所有历史记录;否则只显示指定的updateLog
const logsToShow = showAllHistory ? UPDATE_LOGS : (updateLog ? [updateLog] : [])
// 如果没有可显示的内容,不渲染弹窗
if (logsToShow.length === 0) return null
const getTypeLabel = (type: UpdateItem['type']) => {
switch (type) {
case 'feature':
return '新增'
case 'improvement':
return '优化'
case 'fix':
return '修复'
}
}
const getTypeDotColor = (type: UpdateItem['type']) => {
switch (type) {
case 'feature':
return 'bg-[#6e79c8]'
case 'improvement':
return 'bg-[#157a4b]'
case 'fix':
return 'bg-[#1a1c1d]'
}
}
return (
<div className="fixed inset-0 z-[100] flex items-center justify-center p-3 sm:p-6">
{/* 背景遮罩 */}
<div
className="absolute inset-0 bg-[#1a1c1d]/40 transition-opacity"
onClick={onClose}
aria-hidden="true"
/>
{/* 弹窗内容 */}
<div
ref={dialogRef}
role="dialog"
aria-modal="true"
aria-labelledby="update-log-title"
aria-describedby="update-log-summary"
className="relative flex max-h-[88dvh] w-full max-w-[760px] flex-col overflow-hidden rounded-xl border border-[#e7e8ea] bg-[#fafafa] text-[#1a1c1d] selection:bg-[#eef0fa]"
>
{/* 头部 */}
<header className="relative flex flex-shrink-0 items-start justify-between gap-6 overflow-hidden border-b border-[#e7e8ea] px-5 py-5 sm:px-8 sm:py-7">
<div aria-hidden="true" className="pointer-events-none absolute -right-12 -top-16 h-40 w-40 rounded-full bg-[#6e79c8]/15 blur-3xl" />
<div className="relative min-w-0">
<h2 id="update-log-title" className="font-display text-[clamp(1.5rem,4vw,2.25rem)] font-semibold leading-tight tracking-[-0.03em]">
{showAllHistory ? '更新记录' : updateLog?.title || '系统更新'}
</h2>
<p id="update-log-summary" className="font-en mt-2 text-[11px] uppercase tracking-[0.14em] text-[#86898e] sm:text-xs">
{showAllHistory ? 'Product changelog · 全部历史版本' : `Version ${updateLog?.version || ''} · ${updateLog?.date || ''}`}
</p>
</div>
<button
ref={closeButtonRef}
type="button"
onClick={onClose}
className="relative inline-flex h-11 w-11 flex-shrink-0 items-center justify-center rounded-lg border border-[#e7e8ea] bg-white text-[#6b7075] transition-colors hover:border-[#1a1c1d] hover:bg-[#1a1c1d] hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-[#1a1c1d]/70 focus-visible:ring-offset-2 focus-visible:ring-offset-[#fafafa]"
aria-label="关闭"
>
<svg aria-hidden="true" className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.75} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</header>
{/* 内容区域 */}
<div className="min-h-0 flex-1 overflow-y-auto px-5 py-2 [scrollbar-color:#c9ccd1_transparent] [scrollbar-width:thin] sm:px-8">
<div>
{logsToShow.map((log, logIndex) => (
<section key={`${log.version}-${log.date}`} aria-label={`版本 ${log.version}`} className={logIndex > 0 ? 'pt-10' : ''}>
{/* 版本标题(仅在显示所有历史时显示) */}
{showAllHistory && (
<div className="sticky top-0 z-10 flex items-baseline justify-between gap-4 border-b border-[#e7e8ea] bg-[#fafafa] py-4">
<h3 className="font-display text-base font-semibold tracking-[-0.02em] sm:text-lg">
{log.version}
</h3>
<p className="font-en text-[11px] uppercase tracking-[0.14em] text-[#86898e]">
{log.date}
</p>
</div>
)}
{/* 更新项列表 */}
<div className={showAllHistory ? '' : 'border-t border-[#e7e8ea]'}>
{log.items.map((item, itemIndex) => (
<article
key={`${item.type}-${item.title}`}
className="grid grid-cols-[42px_minmax(0,1fr)] gap-x-2 border-b border-[#e7e8ea] py-6 sm:grid-cols-[58px_minmax(0,1fr)_80px] sm:gap-x-4 sm:py-7"
>
<span className="font-en pt-0.5 text-xs tabular-nums text-[#86898e]">
{String(itemIndex + 1).padStart(2, '0')}
</span>
<div className="min-w-0">
<div className="mb-2">
<h3 className="font-display text-base font-semibold leading-snug tracking-[-0.02em] sm:text-lg">
{item.title}
</h3>
</div>
<p className="max-w-[70ch] text-sm leading-[1.8] text-[#6b7075] sm:text-[15px]">
{item.description}
</p>
</div>
<span className="col-start-2 mt-3 inline-flex items-center gap-2 text-[11px] text-[#6b7075] sm:col-start-3 sm:row-start-1 sm:mt-0 sm:justify-end sm:pt-1 sm:text-xs">
<span aria-hidden="true" className={`h-1.5 w-1.5 rounded-full ${getTypeDotColor(item.type)}`} />
{getTypeLabel(item.type)}
</span>
</article>
))}
</div>
</section>
))}
</div>
</div>
{/* 底部按钮 */}
<footer className="flex flex-shrink-0 border-t border-[#e7e8ea] bg-[#fafafa] px-5 py-4 sm:px-8 sm:py-5">
<button
type="button"
onClick={onClose}
className="min-h-11 w-full rounded-lg bg-[#1a1c1d] px-8 text-sm font-medium text-white transition-opacity hover:opacity-80 active:scale-[0.98] focus:outline-none focus-visible:ring-2 focus-visible:ring-[#1a1c1d]/70 focus-visible:ring-offset-2 focus-visible:ring-offset-[#fafafa] sm:ml-auto sm:w-auto sm:min-w-40"
>
知道了
</button>
</footer>
</div>
</div>
)
}
// Hook: 检查是否需要显示更新弹窗
export function useUpdateLog() {
const [showModal, setShowModal] = useState(false)
const [currentLog, setCurrentLog] = useState<UpdateLog | null>(null)
const [showAllHistory, setShowAllHistory] = useState(false)
useEffect(() => {
// 监听自定义事件,用于手动触发显示更新日志
const handleShowUpdateLog = (event: CustomEvent) => {
if (event.detail?.log) {
setCurrentLog(event.detail.log)
setShowAllHistory(false)
setShowModal(true)
} else if (event.detail?.showAll) {
setCurrentLog(null)
setShowAllHistory(true)
setShowModal(true)
}
}
window.addEventListener('showUpdateLog', handleShowUpdateLog as EventListener)
// 检查是否已查看过当前版本(仅在首次加载时自动弹出)
// 注意:只有经过测试验证的功能更新才会添加到UPDATE_LOGS中
const viewedVersion = localStorage.getItem(STORAGE_KEY)
if (viewedVersion !== CURRENT_VERSION) {
// 找到当前版本的更新日志
const log = UPDATE_LOGS.find(log => log.version === CURRENT_VERSION)
if (log) {
setCurrentLog(log)
setShowAllHistory(false)
setShowModal(true)
}
}
return () => {
window.removeEventListener('showUpdateLog', handleShowUpdateLog as EventListener)
}
}, [])
const handleClose = () => {
setShowModal(false)
// 如果显示的是当前版本,标记已查看
if (!showAllHistory && currentLog?.version === CURRENT_VERSION) {
localStorage.setItem(STORAGE_KEY, CURRENT_VERSION)
}
}
return {
showModal,
currentLog,
showAllHistory,
handleClose,
}
}
// 更新日志管理器 - 用于手动触发显示更新日志
export function showUpdateLog(version?: string) {
if (version === 'all' || version === undefined) {
// 显示所有历史记录
const event = new CustomEvent('showUpdateLog', { detail: { showAll: true } })
window.dispatchEvent(event)
} else {
// 显示指定版本
const log = UPDATE_LOGS.find(log => log.version === version)
if (log) {
const event = new CustomEvent('showUpdateLog', { detail: { log } })
window.dispatchEvent(event)
}
}
}
export default UpdateLogModal