diff --git a/src/main/java/com/budwk/app/flow/controller/FlowDesignController.java b/src/main/java/com/budwk/app/flow/controller/FlowDesignController.java index 8af02627..b4a6ee5e 100644 --- a/src/main/java/com/budwk/app/flow/controller/FlowDesignController.java +++ b/src/main/java/com/budwk/app/flow/controller/FlowDesignController.java @@ -243,6 +243,27 @@ public class FlowDesignController { return Result.success(); } + /** + * 设置流程设计在流程中心的展示状态。 + * @param id 流程设计 ID + * @param centerEnabled 传 1 表示显示,传 0 表示隐藏 + * @return Result;code 为 0 表示保存成功,非 0 时 msg 说明错误,data 无业务数据 + */ + @At + @ApiOperation("设置流程中心显示状态") + @Aop(TransAop.READ_COMMITTED) + @SaCheckPermission("flow.design") + public Result updateCenterEnabled(@Param("id") Long id, @Param("centerEnabled") Integer centerEnabled) { + if (id == null || centerEnabled == null || (centerEnabled != 0 && centerEnabled != 1)) { + return Result.error("流程设计或显示状态无效"); + } + int updated = processDesignService.update(Chain.make("centerEnabled", centerEnabled), Cnd.where(ProcessDesign::getId, "=", id)); + if (updated == 0 && processDesignService.fetch(id) == null) { + return Result.error("流程设计不存在"); + } + return Result.success(); + } + @At @SaCheckLogin @ApiOperation("获取流程设计任务参与者处理类") diff --git a/src/main/java/com/budwk/app/flow/entity/ProcessDesign.java b/src/main/java/com/budwk/app/flow/entity/ProcessDesign.java index 1b63eb68..ce19f8ca 100644 --- a/src/main/java/com/budwk/app/flow/entity/ProcessDesign.java +++ b/src/main/java/com/budwk/app/flow/entity/ProcessDesign.java @@ -68,6 +68,11 @@ public class ProcessDesign extends BaseModel { @Column private Integer isDeployed; + @Comment("是否在流程中心显示(1显示,0隐藏)") + @Column + @Default("1") + private Integer centerEnabled; + @Comment("排序编码") @Column @Default("0") diff --git a/src/main/java/com/budwk/app/sys/controller/v4/SysV4ServController.java b/src/main/java/com/budwk/app/sys/controller/v4/SysV4ServController.java index 7f3e3933..8f47782f 100644 --- a/src/main/java/com/budwk/app/sys/controller/v4/SysV4ServController.java +++ b/src/main/java/com/budwk/app/sys/controller/v4/SysV4ServController.java @@ -11,6 +11,7 @@ import org.nutz.dao.Cnd; import org.nutz.dao.Dao; import org.nutz.dao.Sqls; import org.nutz.dao.sql.Sql; +import org.nutz.dao.util.cri.Static; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.lang.util.NutMap; @@ -57,6 +58,8 @@ public class SysV4ServController { $condition """); Cnd cnd = Cnd.NEW(); + // 只隐藏流程中心入口;历史流程实例及已有流程定义保持原有状态。 + cnd.and(new Static("COALESCE(d.centerEnabled, 1) = 1")); if (StrUtil.isNotBlank(keyword)) { cnd.where().andLike("t.disPlayName", keyword); } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java index 790ad4d7..f7e0fd90 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserAllUpdateServiceImpl.java @@ -23,7 +23,6 @@ import com.budwk.app.zhgh.democratic.proposal.models.ProposalConfig; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeOrigin; import com.budwk.app.zhgh.staffmanage.member.constant.MemberChangeType; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; import org.nutz.aop.interceptor.ioc.TransAop; import org.nutz.dao.Cnd; import org.nutz.dao.Dao; @@ -161,10 +160,6 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService for (Sys_user_source source : sources) { Sys_user user = userMap.get(source.getLoginname()); source.setMember(null); - String unitId = source.getUnitId(); - if (StringUtils.isNotBlank(unitId) && unitId.length() == 5) { - source.setUnitId(unitId.substring(0, 3)); - } // 创建用户对象 Sys_user u = new Sys_user(); @@ -180,6 +175,10 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService } else { // 修改现有用户 u.setId(user.getId()); + // 拉取数据未分配三级单位时写入空字符串,避免 updateIgnoreNull 保留人员原有的三级单位。 + if (StrUtil.isBlank(source.getThreeUnitId())) { + u.setThreeUnitId(""); + } /* * aidFundMember 由基金会员业务维护,数据中心源表默认值为 0。 * 全量更新已有用户时置空,避免 updateIgnoreNull 把已迁移的基金会员标识覆盖为非会员。 @@ -383,14 +382,13 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService Sql resetStatusSql = Sqls.create(""" UPDATE sys_user userInfo SET userInfo.pendingConfirmStatus = @noneStatus - WHERE userInfo.personType IN ('教职工', '劳务派遣人员') - AND userInfo.pendingConfirmStatus <> @noneStatus + WHERE userInfo.pendingConfirmStatus <> @noneStatus + AND userInfo.member='1' AND EXISTS ( SELECT 1 FROM sys_user_source sourceInfo WHERE sourceInfo.pullTime = @pullTime AND sourceInfo.loginname = userInfo.loginname - AND sourceInfo.personType IN ('教职工', '劳务派遣人员') ) """); resetStatusSql.setParam("noneStatus", PENDING_CONFIRM_STATUS_NONE); @@ -400,14 +398,13 @@ public class SysDataUserAllUpdateServiceImpl implements SysDataUserUpdateService Sql pendingStatusSql = Sqls.create(""" UPDATE sys_user userInfo SET userInfo.pendingConfirmStatus = @pendingStatus - WHERE userInfo.personType IN ('教职工', '劳务派遣人员') - AND IFNULL(userInfo.pendingConfirmStatus, @noneStatus) = @noneStatus + WHERE IFNULL(userInfo.pendingConfirmStatus, @noneStatus) = @noneStatus + AND userInfo.member='1' AND NOT EXISTS ( SELECT 1 FROM sys_user_source sourceInfo WHERE sourceInfo.pullTime = @pullTime AND sourceInfo.loginname = userInfo.loginname - AND sourceInfo.personType IN ('教职工', '劳务派遣人员') ) """); pendingStatusSql.setParam("pendingStatus", PENDING_CONFIRM_STATUS_PENDING); diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java index 894af098..565aede0 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysDataUserPullServiceImpl.java @@ -132,6 +132,39 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl Date nowDate = new Date(); + // 人员单位号先与单位表批量比对,缺失单位只同步一次,避免逐人查询单位表。 + Set sourceUnitIds = rawDataList.stream() + .map(raw -> raw.getStr("SZDWH")) + .filter(StrUtil::isNotBlank) + .collect(Collectors.toSet()); + Map unitMap = dao().query(Sys_unit.class, Cnd.NEW()).stream() + .collect(Collectors.toMap(Sys_unit::getId, unit -> unit)); + if (!unitMap.keySet().containsAll(sourceUnitIds)) { + log.info("单位需要更新,正在同步更新"); + sysDataUnitPullService.updateUnits(new ArrayList<>(unitMap.keySet())); + unitMap = dao().query(Sys_unit.class, Cnd.NEW()).stream() + .collect(Collectors.toMap(Sys_unit::getId, unit -> unit)); + } + + // 按单位表的实际等级判断:三级单位为3、直属二级单位为2;单位号位数不参与判断。 + Map tertiaryParentUnitIds = new HashMap<>(); + for (String sourceUnitId : sourceUnitIds) { + Sys_unit unit = unitMap.get(sourceUnitId); + if (unit == null) { + log.warn("人员单位号{}在单位表中不存在,保留信息中心原始单位号", sourceUnitId); + continue; + } + if (!Integer.valueOf(3).equals(unit.getUnitLevel())) { + continue; + } + Sys_unit parentUnit = unitMap.get(unit.getParentId()); + if (parentUnit == null || !Integer.valueOf(2).equals(parentUnit.getUnitLevel())) { + log.warn("三级单位{}缺少有效的二级父单位,保留信息中心原始单位号", sourceUnitId); + continue; + } + tertiaryParentUnitIds.put(sourceUnitId, parentUnit.getId()); + } + // 赋值 List latestSourceList = rawDataList.stream().map(raw -> { Sys_user_source sysUser = new Sys_user_source(); @@ -174,7 +207,10 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl } sysUser.setUnitName(raw.getStr("SZDW")); - sysUser.setUnitId(resolveSourceUnitId(raw.getStr("SZDWH"))); + String sourceUnitId = raw.getStr("SZDWH"); + String parentUnitId = tertiaryParentUnitIds.get(sourceUnitId); + sysUser.setUnitId(StrUtil.blankToDefault(parentUnitId, sourceUnitId)); + sysUser.setThreeUnitId(parentUnitId == null ? null : sourceUnitId); // 设置拉取时间 sysUser.setPullTime(nowDate); @@ -188,17 +224,6 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl dao().insert(latestSourceList); } - // 人员的单位数据和数据库的单位数据比较,如果人员里面有单位不存在,去更新单位数据 - List sourceUnitIds = latestSourceList.stream().map(Sys_user_source::getUnitId).filter(StrUtil::isNotBlank).distinct().toList(); - Sql sql = Sqls.create("select id from sys_unit group by id"); - sql.setCallback(Sqls.callback.strList()); - dao().execute(sql); - List unitIds = sql.getList(String.class); - - if (!new HashSet<>(unitIds).containsAll(sourceUnitIds)) { - log.info("单位需要更新,正在同步更新"); - sysDataUnitPullService.updateUnits(unitIds); - } return nowDate; } catch (Exception e) { throw new BaseException("数据拉取失败,{}", e.getMessage()); @@ -342,22 +367,6 @@ public class SysDataUserPullServiceImpl extends BaseServiceImpl return new ArrayList<>(userMap.values()); } - /** - * 根据接口返回的所在单位号转换数据源用户单位。 - * 入参 rawUnitId 对应人员接口 SZDWH:5位表示三级单位,需要写入其二级父单位;其他长度保持接口原值。 - * 返回值为 sys_user_source.unitId 使用的单位ID,找不到三级单位或父级为空时保留接口原始单位号,避免人员数据丢失。 - */ - private String resolveSourceUnitId(String rawUnitId) { - if (StrUtil.isBlank(rawUnitId) || rawUnitId.length() != 5) { - return rawUnitId; - } - Sys_unit unit = dao().fetch(Sys_unit.class, rawUnitId); - if (unit == null || StrUtil.isBlank(unit.getParentId())) { - return rawUnitId; - } - return unit.getParentId(); - } - @Async private void updateDict(List userSources) { //判断是否要更新在职状态字典 diff --git a/src/main/resources/static/assets/platform/css/home-portal.css b/src/main/resources/static/assets/platform/css/home-portal.css new file mode 100644 index 00000000..dbf281d6 --- /dev/null +++ b/src/main/resources/static/assets/platform/css/home-portal.css @@ -0,0 +1,202 @@ +/* 首页服务门户布局单独限定作用域,避免影响应用中心和其他业务页。 */ +#v4-home-app.home-portal { + width: 100%; + max-width: none; + margin: 0; + color: #20344d; + background: #f2f6fb; + font-family: "Microsoft YaHei", "PingFang SC", sans-serif; + font-size: 14px; +} +#v4-home-app.home-portal * { box-sizing: border-box; } +#v4-home-app .portal-top { display: grid; grid-template-columns: minmax(0, 1fr) 340px; gap: 18px; max-width: 1720px; margin: auto; padding: 18px 24px 0; } +/* 使用完整不透明背景铺满横幅,会员信息独立成卡,不再覆盖校园景观。 */ +#v4-home-app .portal-hero { position: relative; min-width: 0; min-height: 260px; overflow: hidden; border-radius: 12px; background: #e8f4ff url('/assets/platform/img/home/service-portal-banner-campus-v4.png') no-repeat right bottom / cover; } +#v4-home-app .portal-hero::after { content: ""; position: absolute; inset: 0; pointer-events: none; background: linear-gradient(90deg, #e8f4ff 0%, #e8f4ff 28%, rgba(232,244,255,.92) 39%, rgba(232,244,255,.35) 54%, rgba(232,244,255,0) 68%); } +#v4-home-app .portal-hero-inner { position: relative; z-index: 1; display: flex; align-items: center; min-height: 260px; height: 100%; padding: 32px 40px; } +#v4-home-app .portal-hero-copy { max-width: 80%; } +#v4-home-app .portal-hero-eyebrow { margin-bottom: 12px; color: #527ca1; font-size: 14px; line-height: 22px; letter-spacing: 2px; } +#v4-home-app .portal-hero-copy h1 { margin: 0 0 10px; font-size: 36px; line-height: 1.3; font-weight: 700; color: #083765; } +#v4-home-app .portal-hero-copy p { margin: 0; color: #335675; font-size: 17px; line-height: 1.8; } +#v4-home-app .portal-values { display: flex; flex-wrap: wrap; gap: 22px 36px; margin-top: 24px; } +#v4-home-app .portal-values span { display: inline-flex; align-items: center; gap: 12px; } +#v4-home-app .portal-values i { color: #3599f2; font-size: 23px; } +/* 首次渲染时分层淡入文字,只改变透明度和位移,不影响卡片布局。 */ +@keyframes portal-text-enter { + from { opacity: 0; transform: translateY(12px); } + to { opacity: 1; transform: translateY(0); } +} +#v4-home-app .portal-hero-eyebrow, +#v4-home-app .portal-hero-copy h1, +#v4-home-app .portal-hero-copy p, +#v4-home-app .portal-values > span, +#v4-home-app .portal-member-date, +#v4-home-app .portal-member-heading, +#v4-home-app .portal-member .meta-row { animation: portal-text-enter .6s cubic-bezier(.22, 1, .36, 1) backwards; } +#v4-home-app .portal-hero-copy h1 { animation-delay: .08s; } +#v4-home-app .portal-hero-copy p { animation-delay: .16s; } +#v4-home-app .portal-values > span:nth-child(1) { animation-delay: .24s; } +#v4-home-app .portal-values > span:nth-child(2) { animation-delay: .30s; } +#v4-home-app .portal-values > span:nth-child(3) { animation-delay: .36s; } +#v4-home-app .portal-values > span:nth-child(4) { animation-delay: .42s; } +#v4-home-app .portal-member-date { animation-delay: .10s; } +#v4-home-app .portal-member-heading { animation-delay: .18s; } +#v4-home-app .portal-member .meta-row:nth-child(1) { animation-delay: .26s; } +#v4-home-app .portal-member .meta-row:nth-child(2) { animation-delay: .34s; } +#v4-home-app .portal-member .meta-row:nth-child(3) { animation-delay: .42s; } +@media (prefers-reduced-motion: reduce) { + #v4-home-app .portal-hero-eyebrow, + #v4-home-app .portal-hero-copy h1, + #v4-home-app .portal-hero-copy p, + #v4-home-app .portal-values > span, + #v4-home-app .portal-member-date, + #v4-home-app .portal-member-heading, + #v4-home-app .portal-member .meta-row { animation: none; } +} +#v4-home-app .portal-content { max-width: 1720px; margin: auto; padding: 18px 24px 28px; } +/* 同行共用网格行高,统一横纵间距;待办使用紧凑两行信息,避免撑出大块留白。 */ +#v4-home-app .portal-columns { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: 18px; margin-top: 18px; align-items: stretch; } +#v4-home-app .portal-columns > * { min-width: 0; } +#v4-home-app .portal-news-wide { grid-column: 1 / -1; } +#v4-home-app .portal-panel, +#v4-home-app .entry-wrapper, +#v4-home-app .todo-center, +#v4-home-app .work-template-wrapper, +#v4-home-app .jcdt-container { background: #fff; border: 0; border-radius: 12px; padding: 20px; box-shadow: 0 3px 14px rgba(30, 66, 108, .035); } +#v4-home-app .home-section-header, +#v4-home-app .portal-todo-heading, +#v4-home-app .work-template-header, +#v4-home-app .portal-news-header { display: flex; justify-content: space-between; align-items: center; gap: 12px; min-height: 28px; margin: 0 0 16px; } +#v4-home-app .home-section-title, +#v4-home-app .work-template-title, +#v4-home-app .portal-news-title, +#v4-home-app .portal-todo-heading h3 { display: inline-flex; align-items: center; gap: 9px; margin: 0; padding: 0; border: 0; font-size: 20px; line-height: 1.4; font-weight: 600; color: #123356; } +#v4-home-app .home-section-title i, +#v4-home-app .work-template-title i, +#v4-home-app .portal-news-title > i:first-child, +#v4-home-app .portal-todo-heading i { color: #1687f5; font-size: 19px; } +#v4-home-app .portal-more { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; border: 0; padding: 4px 0; background: transparent; color: #1687f5; font: inherit; font-size: 13px; cursor: pointer; text-decoration: none; } +#v4-home-app .portal-more:hover { color: #0565c6; } +#v4-home-app button:focus-visible, +#v4-home-app a:focus-visible, +#v4-home-app [tabindex]:focus-visible { outline: 2px solid #1687f5; outline-offset: 3px; } +#v4-home-app .entry-card { min-width: 0; } +#v4-home-app .entry-wrapper { padding-bottom: 0; } +#v4-home-app .portal-entry-header { display: flex; align-items: center; justify-content: space-between; gap: 16px; border-bottom: 1px solid #e9eff6; } +#v4-home-app .portal-entry-tabs { display: flex; gap: 34px; } +#v4-home-app .portal-entry-tabs button { border: 0; border-bottom: 3px solid transparent; padding: 0 0 13px; background: transparent; font: inherit; font-size: 19px; color: #465d78; font-weight: 600; cursor: pointer; } +#v4-home-app .portal-entry-tabs button.active { color: #0784fa; border-bottom-color: #0784fa; } +#v4-home-app .entry-section + .entry-section { margin-top: 0; } +#v4-home-app .app-grid { display: flex; justify-content: flex-start; align-items: center; gap: 12px; min-height: 0; overflow-x: auto; padding: 20px 0; border: 0; border-radius: 0; box-shadow: none; } +#v4-home-app .app-item { flex: 0 0 96px; border: 0; font: inherit; padding: 0 4px; max-width: none; } +#v4-home-app .app-item:hover { background: #f4f9ff; box-shadow: none; transform: translateY(-2px); } +#v4-home-app .app-icon { background: transparent; } +#v4-home-app .app-name { display: block; width: 100%; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; font-size: 13px; line-height: 20px; min-height: 0; margin-top: 2px; } +#v4-home-app .app-empty { padding: 10px 0; } +#v4-home-app .act-card { padding: 0; border: 0; border-radius: 0; box-shadow: none; } +#v4-home-app .activity-swiper-container { padding: 0 0 4px; } +#v4-home-app .activity-swiper .swiper-slide .item { display: flex; flex-direction: column; height: 100%; } +/* 加高封面并统一裁剪容器,图片、加载态和占位图都保持相同圆角。 */ +#v4-home-app .activity-swiper .swiper-slide .item .img-box { flex-shrink: 0; height: auto; aspect-ratio: 1.5; border-radius: 10px; overflow: hidden; clip-path: inset(0 round 10px); background: #1687f5; isolation: isolate; } +#v4-home-app .img-box .el-image { display: block; width: 100%; height: 100%; position: absolute; inset: 0; border-radius: inherit; overflow: hidden; } +#v4-home-app .activity-swiper .swiper-slide .item .img-box img { height: 100% !important; max-height: none !important; object-fit: cover !important; border-radius: 10px; } +#v4-home-app .activity-swiper .swiper-slide .item .img-box .status { top: 8px; left: 8px; border-radius: 5px; padding: 4px 7px; background: #ed4859; } +#v4-home-app .activity-swiper .swiper-slide .item .img-box .status-ended { background: #8b97a7; } +#v4-home-app .activity-swiper .swiper-slide .item .img-box .status-upcoming { background: #1687f5; } +#v4-home-app .activity-swiper .swiper-slide .item h4 { flex: 1; margin: 10px 0 8px; height: auto; min-height: 22px; max-height: 44px; font-size: 15px; color: #20344d; line-height: 22px; } +#v4-home-app .activity-swiper .swiper-slide .item .time p { white-space: normal; font-size: 12px; color: #7b899d; line-height: 1.6; } +#v4-home-app .activity-swiper-container .swiper-button-next, +#v4-home-app .activity-swiper-container .swiper-button-prev { width: 44px; height: 44px; margin-top: 0; padding: 0; transform: translateY(-50%); border: 1px solid #dbeaff; background: rgba(255,255,255,.96); color: #1687f5; box-shadow: 0 3px 12px rgba(30, 66, 108, .18); } +#v4-home-app .activity-swiper-container .swiper-button-next { right: 8px; } +#v4-home-app .activity-swiper-container .swiper-button-prev { left: 8px; } +#v4-home-app .activity-swiper-container .swiper-button-next:hover, +#v4-home-app .activity-swiper-container .swiper-button-prev:hover { transform: translateY(-50%) scale(1.05); background: #1687f5; color: #fff; } +#v4-home-app .activity-swiper-container .swiper-button-next::after, +#v4-home-app .activity-swiper-container .swiper-button-prev::after { font-size: 18px; font-weight: 600; } +#v4-home-app .portal-cover-empty { height: 100%; display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 9px; color: #94a7bd; background: #f0f5fb; } +#v4-home-app .portal-cover-empty i { font-size: 28px; } +#v4-home-app .user-wrapper { background: transparent; } +#v4-home-app .user-container { display: block; width: 100%; height: 100%; margin: 0; } +#v4-home-app .todo-center { display: flex; flex-direction: column; min-width: 0; height: 100%; } +#v4-home-app .todo-center .header { display: block; margin: 0; } +#v4-home-app .todo-center .el-tabs { margin: 0 0 8px; } +#v4-home-app .todo-center .el-tabs__header { margin: 0; } +#v4-home-app .todo-center .el-tabs__nav { display: flex; width: 100%; border-color: #e9eff6; border-radius: 6px 6px 0 0; } +#v4-home-app .todo-center .el-tabs__item { flex: 1; min-width: 0; padding: 0 7px; font-size: 12px; height: 36px; line-height: 36px; text-align: center; } +#v4-home-app .todo-center .el-tabs__item.is-active { border-bottom: 2px solid #1687f5; color: #1687f5; } +#v4-home-app .portal-task-list { display: flex; flex-direction: column; justify-content: space-evenly; flex: 1; min-height: 180px; } +#v4-home-app .portal-task-row { display: flex; gap: 10px; align-items: center; padding: 8px 6px; border-bottom: 1px solid #eef3f8; } +#v4-home-app .portal-task-row:last-child { border-bottom: 0; } +#v4-home-app .portal-task-row:hover { background: #f7fbff; } +#v4-home-app .portal-task-icon { width: 34px; height: 40px; display: flex; flex: 0 0 34px; align-items: center; justify-content: center; border-radius: 8px; background: #eef7ff; color: #1687f5; font-size: 22px; } +#v4-home-app .portal-task-content { min-width: 0; flex: 1; } +#v4-home-app .portal-task-title { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: #263548; font-weight: 600; font-size: 14px; line-height: 22px; } +#v4-home-app .portal-task-meta { display: flex; align-items: baseline; gap: 10px; font-size: 12px; color: #8390a2; line-height: 21px; } +#v4-home-app .portal-task-meta span { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } +#v4-home-app .portal-task-meta > span:first-child { max-width: 45%; flex-shrink: 0; } +#v4-home-app .portal-task-date { flex-shrink: 0; font-size: 12px; color: #7b899d; } +#v4-home-app .portal-task-node { flex: 1; min-width: 0; color: #8b98a9; font-size: 11px; line-height: 17px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +#v4-home-app .portal-task-row .el-button { flex-shrink: 0; padding: 8px 14px; } +#v4-home-app .portal-task-pagination { text-align: right; margin-top: 8px; } +#v4-home-app .portal-empty { min-height: 132px; display: flex; align-items: center; justify-content: center; gap: 10px; color: #8a9aac; } +#v4-home-app .portal-empty i { font-size: 26px; color: #83b9ee; } +#v4-home-app .work-template-wrapper { width: 100%; margin: 0; } +#v4-home-app .work-template-card { min-height: 98px; padding: 0; border: 0; border-radius: 0; box-shadow: none; } +#v4-home-app .work-template-grid { display: flex; align-items: flex-start; gap: 14px; overflow-x: auto; padding: 4px 0 10px; scroll-snap-type: x proximity; } +#v4-home-app .work-template-item { flex: 0 0 88px; width: 88px; padding: 4px; border: 0; font: inherit; scroll-snap-align: start; } +#v4-home-app .work-template-item:hover { background: #f4f9ff; box-shadow: none; } +#v4-home-app .work-template-icon, +#v4-home-app .work-template-icon .el-image { width: 48px; height: 48px; } +#v4-home-app .work-template-icon img { width: 48px !important; height: 48px !important; object-fit: contain; } +#v4-home-app .work-template-icon i { font-size: 30px; line-height: 48px; color: #83b9ee; } +#v4-home-app .work-template-name { font-size: 13px !important; line-height: 20px; min-height: 40px; max-height: 40px; overflow: hidden; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; } +#v4-home-app .work-template-wrapper .no-activity-placeholder { padding: 12px; } +#v4-home-app .jcdt-container { width: 100%; max-width: none; height: 100%; margin: 0; } +#v4-home-app .portal-news-title { background: transparent; cursor: pointer; font-family: inherit; } +#v4-home-app .portal-news-title > i:last-child:not(:first-child) { color: #8092a6; font-size: 14px; } +#v4-home-app .portal-news-row { display: flex; align-items: center; gap: 12px; width: 100%; padding: 9px 0; border: 0; background: transparent; color: #42536a; font: inherit; text-align: left; cursor: pointer; } +#v4-home-app .portal-news-row time { flex-shrink: 0; padding: 3px 7px; background: #eff5fc; border-radius: 4px; color: #45698f; font-size: 13px; } +#v4-home-app .portal-news-row span { min-width: 0; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } +#v4-home-app .portal-news-row:hover span { color: #1687f5; } +@media (min-width: 1600px) { + #v4-home-app .portal-hero-copy h1 { font-size: 42px; } + #v4-home-app .app-item { flex-basis: 104px; } +} +@media (max-width: 1199px) { + #v4-home-app .portal-top { grid-template-columns: minmax(0, 1fr) 300px; padding: 18px 18px 0; } + #v4-home-app .portal-hero-inner { padding-left: 32px; } + #v4-home-app .portal-content { padding: 18px 18px 24px; } + #v4-home-app .portal-columns { grid-template-columns: minmax(0, 1.2fr) minmax(0, 1fr); } + #v4-home-app .portal-values { gap: 16px; } + #v4-home-app .portal-panel, #v4-home-app .todo-center { padding: 16px; } + #v4-home-app .portal-task-row { gap: 8px; padding: 8px 0; } + #v4-home-app .portal-task-icon { display: none; } +} +@media (max-width: 900px) { + #v4-home-app .portal-top { grid-template-columns: minmax(0, 1fr); } + #v4-home-app .portal-columns { grid-template-columns: minmax(0, 1fr); } + #v4-home-app .portal-activities { order: 1; } + #v4-home-app .portal-todo { order: 2; } + #v4-home-app .portal-templates { order: 3; } + #v4-home-app .portal-news { order: 4; } + #v4-home-app .portal-hero-copy { max-width: 68%; } + #v4-home-app .portal-hero-copy h1 { font-size: 30px; } + #v4-home-app .portal-hero-copy p { font-size: 14px; } + #v4-home-app .portal-task-icon { display: flex; } + #v4-home-app .portal-task-meta { flex-wrap: nowrap; } +} +@media (max-width: 600px) { + #v4-home-app .portal-top { padding: 10px 10px 8px; } + #v4-home-app .portal-hero-inner { padding: 24px 20px; } + #v4-home-app .portal-hero-copy { max-width: 100%; } + #v4-home-app .portal-hero-copy h1 { font-size: 28px; } + #v4-home-app .portal-values { gap: 12px 18px; font-size: 12px; } + #v4-home-app .portal-values i { font-size: 17px; } + #v4-home-app .portal-content { padding: 10px; } + #v4-home-app .entry-wrapper { padding: 16px 12px 0; } + #v4-home-app .portal-entry-tabs { gap: 20px; } + #v4-home-app .portal-entry-tabs button { font-size: 16px; } + #v4-home-app .app-item { flex-basis: 84px; } + #v4-home-app .home-section-title, #v4-home-app .portal-todo-heading h3, #v4-home-app .work-template-title, #v4-home-app .portal-news-title { font-size: 18px; } + #v4-home-app .portal-task-row .el-button { padding: 8px 10px; } +} diff --git a/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v2.png b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v2.png new file mode 100644 index 00000000..73d8f103 Binary files /dev/null and b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v2.png differ diff --git a/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v3.png b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v3.png new file mode 100644 index 00000000..b59942a8 Binary files /dev/null and b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v3.png differ diff --git a/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v4.png b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v4.png new file mode 100644 index 00000000..34b90585 Binary files /dev/null and b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus-v4.png differ diff --git a/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus.png b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus.png new file mode 100644 index 00000000..542628bd Binary files /dev/null and b/src/main/resources/static/assets/platform/img/home/service-portal-banner-campus.png differ diff --git a/src/main/resources/views/layouts/v4/baseLayout.html b/src/main/resources/views/layouts/v4/baseLayout.html index 2fa6b1a3..d3c05ffe 100644 --- a/src/main/resources/views/layouts/v4/baseLayout.html +++ b/src/main/resources/views/layouts/v4/baseLayout.html @@ -436,6 +436,8 @@ .v4-logo { height: 100%; width: auto; + /* 保留 Logo 透明轮廓,将所有可见颜色统一转换为白色。 */ + filter: brightness(0) invert(1); } .v4-nav { @@ -694,12 +696,10 @@ 应用中心 - + --> 待办中心 @@ -756,7 +756,8 @@ var currentPath = getBaseSubAppPath() var footer = $("#v4-footer") - if (currentPath === "/platform/v4/home") { + // 服务门户首页不显示版权栏,PJAX 切换时同步判断当前页面。 + if (currentPath === "/platform/v4/home" && !$("#v4-home-app").hasClass("home-portal")) { footer.show() } else { footer.hide() diff --git a/src/main/resources/views/layouts/v4/home/act.js b/src/main/resources/views/layouts/v4/home/act.js index 6e8a35be..6ae7fcb1 100644 --- a/src/main/resources/views/layouts/v4/home/act.js +++ b/src/main/resources/views/layouts/v4/home/act.js @@ -10,22 +10,23 @@ const act = {
-
+
- - + +
暂无图片
+
+ {{getStatusText(activity)}}
-

+

{{ activity.name}}

-

+

- 时间:{{ activity.startDate }}至{{ activity.endDate }} + {{ formatActivityDate(activity.startDate) }} 至 {{ formatActivityDate(activity.endDate) }}

@@ -34,15 +35,15 @@ const act = {
-
-
+ +
-
📅
+

暂无近期活动

敬请关注后续通知

@@ -57,6 +58,24 @@ const act = { } }, methods: { + updateNavigationPosition() { + const swiperElement = this.$refs.activitySwiper + const cover = swiperElement && swiperElement.querySelector('.img-box') + if (!cover) return + // 按实际封面高度定位,避免标题换行或响应式列数变化导致箭头偏移。 + const container = swiperElement.parentElement + const top = cover.getBoundingClientRect().top - container.getBoundingClientRect().top + cover.offsetHeight / 2 + ;[this.$refs.prevButton, this.$refs.nextButton].forEach(button => { + if (button) button.style.top = top + 'px' + }) + }, + formatActivityDate(value) { + return value ? this.$moment(value).format('YYYY-MM-DD') : '待定' + }, + browseNext() { + if (!this.swiper) return + this.swiper.isEnd ? this.swiper.slideTo(0) : this.swiper.slideNext() + }, /*查询活动*/ listAct() { this.$axios.post("/platform/home/listHomeActivity").then((res) => { @@ -89,13 +108,22 @@ const act = { centeredSlides: false, loop: false, watchOverflow: true, + // 双栏中的活动按容器宽度排布,避免用整个窗口宽度挤出过多卡片。 + breakpointsBase: 'container', observer: false, observeParents: false, - resizeObserver: false, + // 页面内容加载后可能出现滚动条,需重新计算列宽,避免末张封面及圆角被裁切。 + resizeObserver: true, + roundLengths: true, + on: { + init: () => this.$nextTick(() => this.updateNavigationPosition()), + resize: () => this.$nextTick(() => this.updateNavigationPosition()), + slidesUpdated: () => this.$nextTick(() => this.updateNavigationPosition()), + }, // 鼠标停留在活动区域时可横向浏览,到首尾后释放页面滚动。 mousewheel: { enabled: true, - forceToAxis: false, + forceToAxis: true, releaseOnEdges: true, sensitivity: 0.8, }, @@ -108,14 +136,11 @@ const act = { type: 'progressbar', }, breakpoints: { - 768: { + 480: { slidesPerView: 2, }, - 1024: { - slidesPerView: 4, - }, - 1200: { - slidesPerView: 5, + 740: { + slidesPerView: 3, } } }) diff --git a/src/main/resources/views/layouts/v4/home/entry.js b/src/main/resources/views/layouts/v4/home/entry.js index f27d663b..6e785051 100644 --- a/src/main/resources/views/layouts/v4/home/entry.js +++ b/src/main/resources/views/layouts/v4/home/entry.js @@ -1,18 +1,19 @@ const entry = { template: /*language=HTML*/ `
-
-
-
- - {{ section.title }} - /Applications -
+
+
+
+
全部应用 +
+
-
-
+
-
{{ item.name }}
-
+
{{ item.name }}
+ -
+ + +
-
-