大数跨境

SpringBoot+Vue3 节日主题换肤实战:一条参数换全站配色,节后自动还原

SpringBoot+Vue3 节日主题换肤实战:一条参数换全站配色,节后自动还原 企业软件源码
2026-09-20
4
导读:中秋国庆想让系统有点节日气氛,多数团队的做法是临时改 CSS 再发一次版,节后还得记得改回来。本文用一条后台参数描述节日主题,前端读到后走偏好设置改主色、注入淡色变量,欢迎卡文案与装饰同步替换,过期自

SpringBoot+Vue3 节日主题换肤实战:一条参数换全站配色,节后自动还原

🌐 文档地址:https://ruoyioffice.com
 👇👇👇 文章底部获取源码和演示地址 👇👇👇
 💬 :17156169080(获取产品咨询)

每年中秋国庆前,行政都会问同一句话:「系统能不能也有点节日气氛?」技术上最省事的答案是改一版 CSS 再发布,但这句话每年会问两三次,每次都要发版、节后还要记得改回来。更划算的做法是把节日主题变成一条可配置的数据:管理员在参数配置里改一条 JSON,欢迎卡文案、装饰素材和全站主色一起换,到期自动退回默认。

▲ 中秋主题下的真实工作台:参数里的主色推出侧边栏淡底、按钮链接色阶与日期选择器高亮,欢迎卡文案和装饰也来自同一条参数

引言:节日皮肤为什么总要动代码

节日换肤看起来是件小事,真做起来最容易变成技术债。常见的四种做法各有代价。

做法
怎么实现
代价
临时改样式表
直接把主色和欢迎卡背景写进 CSS
每个节日发一次版,节后还要发一次版改回来
做一套完整主题包
引入多套皮肤文件,运行时切换
为一年几天的氛围维护多套样式,回归测试成本高
后台上传背景图
加一张配置表、一个上传表单
只能换图,换不了文案和配色;表和菜单都要新建
干脆不做
——
员工每天第一眼看到的还是和上季度一样的界面

真正要解决的问题有四个:

  • 不发版
    :节日前一天临时决定要不要上,不应该触发前端构建和发布流程;
  • 能过期
    :假期结束后没人会记得手工改回来,必须自动退场;
  • 别只换一个角
    :只有欢迎卡变色、按钮和日期选择器还是原来的蓝,看起来像样式坏了;
  • 不能覆盖用户自己的偏好
    :有人把主题色调成了自己习惯的绿色,节日主题不该把它抹掉,节后更不能把他的绿色"还原"成平台默认蓝。

RuoYi Office 的做法是:一条参数描述一个节日,前端读到后走框架的偏好设置改主色,再注入一层极淡的 CSS 变量;不新建表、不加后端代码。 下面按真实实现拆开讲。

一、产品能力与特点

节日主题是一条后台参数,管理员改完刷新页面即生效。 它不是独立菜单,也没有专门的管理界面——复用的是系统本来就有的参数配置中心。

能力
面向角色
和「临时改 CSS」差在哪
节日文案(主副标题)
管理员
换文案不用改组件默认值,也不用翻译文件
全站主色
管理员
按钮、链接、标签、日期选择器由组件库统一派生色阶
侧边栏与顶栏淡色
管理员
只覆盖几个 CSS 变量,不改布局组件
装饰素材与收起图标
管理员
换节日只换两个文件名,前端代码不动
生效区间
管理员
到期自动退场,不依赖人工或定时任务
保留用户偏好
全体员工
自己调过主题色的人不被覆盖,节后也不会被改成平台默认色

一条参数,九个字段

参数键名固定为 system.festival.welcome,值是一段 JSON。字段刻意克制,因为参数值长度有限,能省的都省掉了。

字段
必填
含义
示例
code
节日编码,用于识别「这是哪个节日」
mid_autumn
name
备注用的中文名
中秋
start
 / end
生效区间,含当天;缺省表示不限
2026-09-19
 / 2026-09-27
primary
节日主色,HSL 写法
hsl(28 72% 48%)
title
欢迎卡主标题,覆盖默认的时段问候
中秋团圆,阖家安康
subtitle
欢迎卡副标题
月满中秋
banner
欢迎卡右侧装饰素材
/static/festival/mid-autumn-banner.webp
icon
收起后显示的小图标
/static/festival/mid-autumn-icon.webp

▲ 效果:管理员在「基础设施 → 配置管理」里编辑同一条参数。注意此时页面里的「搜索」「新增参数」按钮和左侧菜单高亮已经是中秋的暖橙色——主色是全局生效的,不只作用于首页

code 是唯一不能省的字段。它不参与渲染,但决定了两件事:用户手工收起装饰后,这个"收起"只对当前节日有效;以及主题色备份属于哪个节日,换节日时能识别出"当前色是上一个节日的残留,不是用户自己选的颜色"。

七个法定节日的预设

配置的自由度越高,实施时越容易配得难看。 所以七个法定节日的主色与文案都预置好了,实施只需要复制对应一段,再按当年日期改生效区间。

节日
编码
主色
主标题 / 副标题
元旦
new_year hsl(215 68% 50%)
元旦启新,万象更新 / 新年第一天
春节
spring_festival hsl(0 72% 50%)
新春大吉,万事顺遂 / 恭贺新春
清明
qingming hsl(160 30% 42%)
清明时节,慎终追远 / 春和景明
劳动节
labor_day hsl(24 76% 50%)
致敬劳动,向阳而行 / 五一假期愉快
端午
dragon_boat hsl(155 42% 40%)
端午安康,粽叶飘香 / 五月初五
中秋
mid_autumn hsl(28 72% 48%)
中秋团圆,阖家安康 / 月满中秋
国庆
national_day hsl(4 72% 50%)
普天同庆,盛世华诞 / 祝您假期愉快

两条容易被忽略的文案禁忌,写进了预设注释里:端午用「安康」不用「快乐」;清明是祭扫节气,不用任何庆祝、祝福类措辞。 这不是技术问题,但配错会被全公司看到,所以宁可把默认文案定死。

元旦、劳动节、国庆的公历日期固定;春节、清明、端午、中秋按农历或节气走,换年份要改 start / end。对照表也一并放在预设文件里:

节日
2027
2028
2029
2030
2031
春节
02-06
01-26
02-13
02-03
01-23
清明
04-05
04-04
04-04
04-05
04-05
端午
06-09
05-28
06-16
06-05
06-24
中秋
09-15
10-03
09-22
09-12
10-01

生效期建议比节日本身宽一两天:节前就能看到氛围,假期结束后再自动退场。结束日以正式放假通知为准。

二、从改一条参数到全站变色

整条链路只有四步,其中三步是系统本来就有的能力。

第一步:改参数,顺手把缓存清掉

参数配置支持按键名搜索,节日主题的参数在 ui 分类下。

▲ 入口:参数列表按键名过滤,节日主题只有一条记录。用界面保存会自动清掉后端缓存;如果是直接执行 SQL 改库,需要额外删一次 Redis 键

这里有个必须说清的坑:参数查询接口带 Redis 缓存。走管理界面保存,服务端会自己清缓存;但批量上线常常是直接跑 SQL,这时缓存里还是旧值,页面看起来"改了没生效"。两种处理方式都可以:

-- 切到中秋主题(2026-09-25 中秋,生效期覆盖节前节后)UPDATE `infra_config`SET `value` = '{"code":"mid_autumn","name":"中秋","start":"2026-09-19","end":"2026-09-27","primary":"hsl(28 72% 48%)","title":"中秋团圆,阖家安康","subtitle":"月满中秋","banner":"/static/festival/mid-autumn-banner.webp","icon":"/static/festival/mid-autumn-icon.webp"}',    `visible` = b'1',    `update_time` = NOW()WHERE `config_key` = 'system.festival.welcome'  AND `deleted` = b'0';-- 执行完删一次缓存键,键里的 1 是租户号-- redis-cli del "infra_config:1:system.festival.welcome"

改完 SQL 不想碰 Redis 的,进管理界面把同一条参数点开再保存一次,效果一样。

第二步:员工刷新页面,看到中秋版

前端在进入主布局时读一次参数,判断当天是否落在生效区间内。命中就套用,不命中就走还原分支。

▲ 效果:同一个工作台在国庆主题下。左侧菜单高亮、待办表格里的单据编号与「办理」链接、右下角日历的今日红框,都来自参数里的 primary,没有一处是页面里单独写死的颜色

值得对比的是没有节日主题时的样子:欢迎卡是默认的蓝色渐变,菜单高亮和链接是平台默认主色。所有这些颜色在换肤前后都不需要逐个页面去改。

第三步:换节日,还是改同一条参数

中秋和国庆之间只隔几天,切换时改的仍是这一条记录:换 code、换生效区间、换主色、换两行文案、换两个素材路径。

▲ 效果:同一页面切到中秋主题。对比上一张图可以看到,变化的只是色相与装饰素材,布局、组件和数据完全没动

七个法定节日的参数都预置好了,上线时复制对应的 JSON 即可。装饰素材同样按节日命名,一共 14 个文件(7 张横幅 + 7 枚图标),总体积 143KB,单张横幅最大 23.6KB。

第四步:过期自动退场

到了 end 的第二天,前端判断不在区间内,会读备份把主题色还原,并清掉注入的淡色变量。这一步不需要管理员做任何操作,也没有定时任务在跑——判断发生在每次前端初始化时。

参数被删除、值写坏(JSON 解析失败)、value 被清空,都走同一条还原路径。这是刻意设计的:节日主题属于锦上添花,任何异常都不能影响系统正常使用。

三、设计怎么落地

3.1 五个关键决策

决策点
方案
理由
配置放哪
复用参数配置中心,不新建表
一个节日只需一条记录;权限、缓存、审计、管理界面全都是现成的
主色怎么改
调框架的 updatePreferences,不写 CSS
组件库会自己派生按钮、链接、日期选择器的色阶,不用逐个组件覆盖样式
淡色层怎么做
覆盖 --sidebar / --header / --menu 等 CSS 变量
只染底色不改布局;用独立样式表 id,与框架自身的样式表隔离
用户改过色怎么办
备份用户原色,捕获到真实改动后标记 userOverride,之后不再覆盖
不靠「当前色和节日色不一致」去猜,否则任何残留状态都会让节日配色套不上
生效判断放哪
前端每次初始化时按日期字符串比较
不需要后端定时任务,也不需要为「节日结束」写一次数据变更

第四条是这套方案里最容易做错的地方,单独说明:如果用"当前主题色 ≠ 节日色,说明用户改过"来判断,那么第一次套用节日色之前的状态也满足这个条件,节日主题永远套不上去。正确做法是监听主题色的真实变更事件,并排除掉节日主题自己写入的那一次。

3.2 参数怎么变成配色

▲ 管理员改参数在最上一层,后端只提供已有的参数查询接口,判断区间、备份、套色和注入变量都发生在前端 Store;命中与过期是两条不同的分支

调用顺序是:主布局挂载 → Store 初始化 → 参数接口 → 判断区间 → 套用或还原。其中参数接口这一层有三级缓存,首页反复进入不会压到数据库。

位置
有效期
作用
前端内存缓存
参数 API 封装
60 秒
同一页面多个组件读同一个键,只发一次请求
并发去重
参数 API 封装
单次请求期间
同时发起的相同键名请求共用一个 Promise
后端 Redis
参数服务
直到参数更新
首页每次进入不查库;改库后需要主动失效

初始化被刻意放在主布局 onMounted 的第一行,而不是塞进空闲队列。原因很实际:如果晚一步执行,用户会先看到默认蓝色再突然变成节日色,闪一下比不换肤更难看。

3.3 套用主色时先把用户的颜色存起来

这段对应第二步。逻辑的重点不是"改颜色",而是改之前先判断该不该改、以及把什么存进备份

function applyPrimary(config: FestivalConfig{  if (!config.primary) return;  const current = preferences.theme.colorPrimary;  const backup readBackup();  // 用户在节日期间自己改过色,让路,不再覆盖  if (backup?.userOverride && backup.code === config.code) return;  if (current === config.primary) {    // 已是节日色。备份可能被手工清过,补一条兜底,    // 否则节日过了就再也回不到用户原来的配色    if (!backup) {      writeBackup({        code: config.code,        festivalPrimary: config.primary,        userPrimary: preferencesManager.getInitialPreferences().theme.colorPrimary,      });    }    return;  }  // 当前色若还是上一个节日的颜色,说明是上次没还原干净的残留,  // 真正的用户色在备份里;否则当前色就是用户自己的配色  const userPrimary =    backup && current === backup.festivalPrimary ? backup.userPrimary : current;  writeBackup({ code: config.code, festivalPrimary: config.primary, userPrimary });  updatePreferences({ theme: { colorPrimary: config.primary } });}

updatePreferences 是框架偏好系统的入口。走它而不是自己写 CSS,是为了让 Ant Design Vue 的按钮、链接、Tag、日期选择器一起按新主色派生色阶——这也是上面第二张截图里日历今日高亮能同步变色的原因。

3.4 节日过了要还原,但不能改用户自己选的颜色

这段对应第四步。有两个细节值得注意:备份不删,以及还原前要先确认当前色确实是节日色。

function restorePrimary() {  const backup readBackup();  if (!backup) return;  // 只有当前色确实还是节日色才动,用户自己选的颜色一律不碰  if (    !backup.userOverride &&    preferences.theme.colorPrimary === backup.festivalPrimary  ) {    updatePreferences({ theme: { colorPrimary: backup.userPrimary } });  }}

备份不清除是有意的:只要它还在,哪怕过了很久、主题色又被别处残留成节日色,也能认出来并还原。反过来,还原成功后立刻删备份,会让"再次出现残留"变成无法修复的状态。

配套的还有一个监听,用来识别用户的真实改动:

watch(  () => preferences.theme.colorPrimary,  (color) => {    if (!festival.value?.primaryreturn;    const backup = readBackup();    // 与备份里的节日色一致说明是节日主题自己写的,不算用户改动    if (!backup || color === backup.festivalPrimaryreturn;    writeBackup({ ...backup, userOverridetrueuserPrimary: color });  },);

3.5 侧边栏只染一层极淡的底色

主色管控件,底色管氛围,两者分开。淡色层通过覆盖 CSS 变量实现,并且只在浅色模式注入:暗色模式下侧边栏本来就是深色,再染节日色会脏。

function applyTint() {  const hsl = hslParts(festival.value?.primary);  if (!hsl || isDark.value) {    updateCSSVariables({}, STYLE_ID':root, .light');    return;  }  const { h, s } = hsl;  // 饱和度压到很低,只留一点暖意,避免喧宾夺主  const soft = Math.min(s, 52);  updateCSSVariables(    {      '--background-deep'`{soft}% 96.5%`,      '--sidebar'`{soft}% 97.8%`,      '--header'`{soft}% 98.4%`,      '--menu'`{soft}% 97.8%`,    },    STYLE_ID,    ':root, .light',  );}

亮度全部压在 96% 以上、饱和度上限 52,是反复调出来的结果:再深一点,长期盯着列表页的人会觉得刺眼;再浅一点,肉眼分辨不出换过肤。深浅模式切换时这个函数会重新执行一次。

欢迎卡的渐变和文字色同样由主色推导,浅色取高亮度配深字,暗色取低亮度并沿用组件原本的白字:

const cardGradient = computed(() => {  const hsl = hslParts(festival.value?.primary);  if (!hsl) return '';  const { h, s } = hsl;  const soft = Math.min(s, 78);  return isDark.value    ? `linear-gradient(120deg, hsl({soft}% 26%) 0%, ` +        `hsl({soft}% 21%) 46%, hsl({soft}% 17%) 100%)`    : `linear-gradient(120deg, hsl({soft}% 97%) 0%, ` +        `hsl({soft}% 93.5%) 46%, hsl({soft}% 89%) 100%)`;});

参数里只给一个主色,浅色渐变、暗色渐变、卡片文字色三套值全部由它算出来。这是"字段必须克制"的另一个原因:能算的就不要让管理员填。

3.6 文案按三级回落,没配节日也不会空着

欢迎卡本来就支持在首页组件里配置问候语,节日参数是加在它前面的一层,而不是替换它。三级回落保证任何一层缺失都有兜底。

/** 主标题:节日文案 > 组件配置 > 时段问候 */const displayTitle = computed(() => {  if (festivalStore.festival?.title) {    return festivalStore.festival.title;  }  if (props.greetingTitle) {    return props.greetingTitle;  }  const name = userStore.userInfo?.realName || userStore.userInfo?.username;  return `{name}`;});/** 副标题:节日文案 > 组件配置 */const displaySubtitle = computed(  () => festivalStore.festival?.subtitle || props.greeting,);
优先级
来源
典型内容
1
节日参数
中秋团圆,阖家安康
2
首页组件配置
公司季度目标标语
3
组件默认
早上好,张三 + 欢迎回来,开始您的工作吧!

时段问候按小时切换(凌晨好 / 早上好 / 上午好 / 中午好 / 下午好 / 晚上好 / 夜深了),配合真实姓名。节日期间这一层被盖住,节后自动回来。

3.7 整套东西的运行开销

节日氛围属于锦上添花,代价必须小到可以忽略,否则不值得做。实际开销可以逐项数清:

后端零新增。 没有新表、新接口、新定时任务,只是往 infra_config 加了一行数据。读取走已有的 /infra/config/get-value-by-key,配置服务本身带 Redis 缓存。

前端一次请求。 store 的 init() 在布局里调用,带 initialized 幂等标记,整个会话只请求一次;路由切换、组件重挂载都不会重复拉。

async function init() {  if (initialized) return;  initialized = true;  try {    const config = parseConfig(await getConfigKey(CONFIG_KEY));    if (config && inRange(config)) {      festival.value = config;      collapsed.value = localStorage.getItem(COLLAPSE_KEY) === config.code;      applyPrimary(config);      applyTint();    } else {      restorePrimary();      applyTint();    }  } catch (error) {    // 节日主题属于锦上添花,任何异常都不应影响系统使用    console.warn('加载节日主题失败:', error);  }}

注意 catch 里只打一条 warn。参数读不到、JSON 格式错、网络超时,全都退回默认欢迎卡,不弹错、不阻塞渲染。

素材两个文件。 每个节日一张横幅加一个收起后的小图标,都是 WebP,且只加载当前生效的那个节日:

素材
体积区间
横幅 *-banner.webp
7.8 ~ 23.1 KB
图标 *-icon.webp
2.3 ~ 5.9 KB

最大的春节横幅 23.1 KB,比首页任何一个图表库的增量都小。非节日期间(参数为 {} 或不在生效期)一个字节都不加载,也不注入任何 CSS 变量。

3.8 怎么回滚

回滚有三档,按影响面从小到大:

场景
操作
效果
临时关掉节日主题
把参数值改成 {},或把 visible 置为否
装饰与配色一起退场,欢迎卡回默认蓝
彻底移除
删除该参数记录
同上;前端判断为「未配置」
用户自己不想看装饰
点欢迎卡右上角关闭
只收起装饰,配色保留;状态记在本地

三档都不需要发版。需要注意的是:改完参数值后仍要清一次后端缓存,否则页面拿到的是旧 JSON。

四、边界与对照

这套方案换的是"氛围",不是完整的白标定制。 写清边界比夸能力更有用。

维度
本方案
改 CSS 发版
完整主题包
上线成本
改一条参数
前端构建 + 发布
维护多套样式文件
节后还原
到期自动
再发一次版
手工切换
组件覆盖面
按钮、链接、标签、日期选择器等由色阶派生
改到哪算哪
全覆盖
用户偏好
用户改过就不再覆盖
直接盖掉
取决于实现
适用范围
节日、纪念日、活动周
一次性需求
多品牌长期并存

诚实的边界有四条:

  • 全局生效,不按用户或部门区分
    。参数是平台级的,不支持"研发部看中秋、销售部看国庆";员工侧只有"收起装饰"这一个开关。
  • 参数值长度有限
    。这条参数是普通配置项,值的长度受字段限制,所以字段被压到九个,也不能往里塞多语言文案或多张素材。
  • 素材要跟着节日换
    。参数只存路径,文件本身需要提前按规格产出——这部分的规格和坑另文详述。
  • 暗色模式只换卡片深调
    。侧边栏和顶栏在暗色模式下不注入节日色,避免深色底上再叠色相导致发灰。

反过来说,有三种需求不该硬塞进这套参数里:

  1. 长期并存的多品牌外观
    。集团下面几家子公司要各自的 LOGO 与配色,那是白标能力,应该做成租户级的品牌配置,而不是共用一条全局节日参数。
  2. 按角色差异化的首页
    。销售看销售看板、财务看财务看板,这属于首页组件与权限的组合,不是换肤能解决的。
  3. 强制全员统一配色
    。这套实现刻意让用户偏好优先,如果企业要求"所有人必须用同一个主题色",就得反过来禁掉偏好设置,那是另一个产品决策。

判断标准很简单:需求是不是有明确的起止时间。 有时限的用节日参数,长期存在的应该落到各自的功能里。

五、快速体验

在线演示地址:

https://ruoyioffice.com/web/

账号:admin
 密码:admin123

推荐体验路径:

  1. 登录后进入工作台,观察欢迎卡的文案、日期农历与右侧装饰;
  2. 打开「基础设施 → 配置管理」,按键名搜索 festival
  3. 点开这条参数,把 title 和 subtitle 改成自己公司的口号,保存;
  4. 回到工作台刷新,确认文案已变;
  5. 再把 primary 改成别的色相(例如 hsl(210 72% 48%)),刷新后观察侧边栏、按钮、日历高亮是否一起变;
  6. 把 end 改成昨天,刷新页面,确认主题自动退回默认;
  7. 点顶栏偏好设置,把主题色调成自己喜欢的颜色,再把参数生效期改回来,确认自己选的颜色没有被节日色覆盖。

第 6 和第 7 步是这套设计的核心,建议都试一遍。

常见问题(FAQ)

改完参数为什么页面没变化?

大概率是缓存。参数查询接口有 Redis 缓存,直接改库需要删一次 infra_config:{租户号}:{键名},或者进管理界面把同一条参数重新保存一次。前端还有 60 秒的内存缓存,刷新页面即可。

节日过了必须手工改回来吗?

不需要。参数里的 end 是生效截止日(含当天),第二天前端会自动读备份还原主题色,并清掉注入的淡色变量。装饰同时不再渲染。

员工自己调过主题色,会被节日主题覆盖吗?

不会。系统会记录"用户真实改过主题色"这个标记,此后节日主题不再覆盖他的配色;节后也不会把他的颜色改成平台默认色。

支持按部门或角色显示不同的节日皮肤吗?

不支持。这条参数是平台级配置,全体员工一致。员工侧只有一个开关:点欢迎卡右上角把装饰收起,收起状态按节日编码记在本地,换节日会重新出现。

换一个新节日需要改代码吗?

不需要改代码,但需要准备素材。参数里换 code、生效区间、主色、两行文案和两个素材路径即可;素材要按固定规格产出白底 WebP,否则装饰会在卡片上拼出可见的边界。

这套换肤会影响性能吗?

主要开销是一次参数请求(带三级缓存)和一次 CSS 变量写入,都发生在主布局挂载阶段。装饰素材是 WebP,单张最大 23.1KB,七个节日全部素材合计约 143KB,且只加载当前节日那两张。详见正文 3.7。

装饰素材为什么没有拼贴边界?

欢迎卡使用白底 WebP、mix-blend-mode: multiply 与双向渐隐合成,素材规格和自动校验方法会在同批另一篇《节日装饰素材实战》中完整拆解。

两篇分别解决“主题如何配置”和“素材如何生产”,可以独立阅读。

结语

节日换肤的技术含量不高,难点在于把一次性需求做成可配置的数据,而不是每年重复一次发版。这套实现里真正花时间的不是变色,而是三件容易被忽略的事:到期自动退场、用户偏好不被覆盖、以及异常情况下悄悄退回默认而不影响系统使用。

同样的思路可以复制到其他"氛围型"需求上:公司周年庆的专属配色、重大活动期间的工作台标语、季度目标冲刺时的首页提示。都是一条参数加一段推导,不必为每个活动新建一张表和一套菜单。

你们团队是怎么处理节日氛围这类需求的,是每次改样式发版,还是干脆不做?欢迎在评论区聊聊。

如果这篇对你有用,点个「在看」或收藏。

🌐 演示地址
 https://ruoyioffice.com/web
 📦 GitHub 源码
 https://github.com/yuqing2026/ruoyi-office
 📦 Gitee 源码
 https://gitee.com/yqzy1688/ruoyi-office
 💬 微信:17156169080(获取产品咨询)

打开演示地址直接查看系统。

【声明】内容源于网络
0
0
企业软件源码
RuoyiOffice 是一套基于 Spring Boot + Vue3 +Uniapp 的企业一体化管理平台,集 OA、CRM、ERP、工作流、HR、资产、合同、项目、AI应用等业务于一体,帮助企业用一个系统协同管理多类核心业务。
内容 130
粉丝 0
企业软件源码 RuoyiOffice 是一套基于 Spring Boot + Vue3 +Uniapp 的企业一体化管理平台,集 OA、CRM、ERP、工作流、HR、资产、合同、项目、AI应用等业务于一体,帮助企业用一个系统协同管理多类核心业务。
总阅读1.8k
粉丝0
内容130