主页新闻板块改成重庆工贸的;手机端主页背景logo改成读取系统参数里的logo,之前默认是地大logo

This commit is contained in:
2026-09-16 16:50:58 +08:00
parent 0cec79cd76
commit fc39bc8020
7 changed files with 135 additions and 54 deletions
+1 -1
View File
@@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<groupId>com.budwk</groupId>
<artifactId>zhgh_cug_v4</artifactId>
<artifactId>zhgh_cqgmy</artifactId>
<version>5.6.0-plus</version>
<properties>
<nutzboot.version>2.6.0-SNAPSHOT</nutzboot.version>
@@ -11,26 +11,21 @@ import com.budwk.app.base.result.Result;
import com.budwk.app.sys.models.Sys_home_activity;
import com.budwk.app.sys.models.Sys_home_template;
import com.budwk.app.sys.models.Sys_menu;
import com.budwk.app.sys.services.SysHomeNewsService;
import com.budwk.app.sys.services.SysMenuService;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.web.commons.auth.utils.AuthUtil;
import com.budwk.app.web.commons.auth.utils.SecurityUtil;
import com.budwk.app.zhgh.activity.basic.service.ActivityBasicScopeService;
import io.swagger.annotations.ApiOperation;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.FieldFilter;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Sql;
import org.nutz.dao.util.Daos;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Lang;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
@@ -42,7 +37,6 @@ import org.nutz.mvc.annotation.Param;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
@@ -58,7 +52,7 @@ public class SysHomeController {
@Inject
private SysUserService sysUserService;
@Inject
private RedisService redisService;
private SysHomeNewsService sysHomeNewsService;
@Inject
private ActivityBasicScopeService activityBasicScopeService;
@@ -289,38 +283,17 @@ public class SysHomeController {
}
/**
* 获取学校工会首页三个栏目,无需请求参数。
*
* @return Result.data 为栏目列表;label 为栏目名称,value 为文章列表,
* 每篇文章的 text、time、href 分别为标题、发布日期和完整链接。
*/
@At
@SaCheckLogin
@ApiOperation("获取新闻")
@Ok("json")
// @CacheDefaults(cacheName = RedisConstant.PLATFORM_REDIS_WKCACHE_PREFIX + "web_news", isHash = true)
// @CacheResult(cacheKey = "news", ignoreNull = true, cacheLiveTime = 60 * 60 * 24)
public Result getNews() {
try {
String url = "https://xgh.cug.edu.cn/";
Document document = Jsoup.connect(url).get();
Elements homeElements = document.select(".gh,.jc,.fc,.jg");
List<Map<String, Object>> news = homeElements.stream().map(homeElement -> {
//获取板块名称
String name = homeElement.selectFirst(".title").text();
Elements liElements = homeElement.select("li");
List<NutMap> ele = liElements.stream().map(liElement -> {
NutMap row = NutMap.NEW();
String href = liElement.selectFirst("a").attr("href");
String time = liElement.selectFirst("span").text();
String title = liElement.selectFirst("a").attr("title");
row.put("href", href);
row.put("time", time);
row.put("text", title);
return row;
}).toList();
return Map.of("label", name, "value", ele);
}).collect(Collectors.toList());
redisService.setex("gonghui_news", 60 * 60 * 24, Json.toJson(news));
return Result.success(news);
} catch (IOException e) {
throw new RuntimeException(e);
}
return Result.success(sysHomeNewsService.getNews());
}
}
@@ -0,0 +1,18 @@
package com.budwk.app.sys.services;
import java.util.List;
import java.util.Map;
/**
* 学校工会网站首页栏目服务。
*/
public interface SysHomeNewsService {
/**
* 无需参数,按工作动态、法规制度、通知公告顺序获取首页文章。
*
* @return 栏目列表:label 为栏目名称,value 为文章列表;文章的 text 为完整标题,
* time 为发布日期,href 为完整 HTTP/HTTPS 链接。无文章的栏目保留空列表。
*/
List<Map<String, Object>> getNews();
}
@@ -0,0 +1,85 @@
package com.budwk.app.sys.services.impl;
import com.budwk.app.base.exception.BaseException;
import com.budwk.app.sys.services.SysHomeNewsService;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.integration.jedis.RedisService;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.json.Json;
import org.nutz.lang.Strings;
import org.nutz.lang.util.NutMap;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 抓取重庆工贸职业技术学院工会首页,适配现有首页轮播的数据结构。
*/
@IocBean
public class SysHomeNewsServiceImpl implements SysHomeNewsService {
private static final Log log = Logs.get();
private static final String HOME_URL = "https://gh.cqgmy.edu.cn/index.htm";
@Inject
private RedisService redisService;
/**
* 无需参数,一次抓取首页中的三个栏目,并保留原有一天有效期的缓存写入。
*
* @return label/value 栏目列表,文章包含 text/time/href;正常空栏目返回空列表。
*/
@Override
@Aop(TransAop.READ_COMMITTED)
public List<Map<String, Object>> getNews() {
try {
Document document = Jsoup.connect(HOME_URL).timeout(10000).get();
List<Map<String, Object>> news = new ArrayList<>();
// 使用学校栏目编号匹配文章,避免将导航、“更多”及其他栏目内容作为新闻。
news.add(readColumn(document, "工作动态", "1139"));
news.add(readColumn(document, "法规制度", "1137"));
news.add(readColumn(document, "通知公告", "1136"));
redisService.setex("gonghui_news", 60 * 60 * 24, Json.toJson(news));
return news;
} catch (IOException e) {
log.warn("获取重庆工贸职业技术学院工会首页失败", e);
throw new BaseException("学校工会网站暂时无法访问,请稍后重试");
}
}
/**
* 从首页表格提取指定栏目的文章,保留来源顺序和空栏目。
*
* @param document 已设置学校首页基础地址的 HTML 文档
* @param label 栏目显示名称
* @param columnId 学校网站文章地址 info/{栏目编号}/{文章编号}.htm 中的栏目编号
* @return label 为栏目名称,value 为包含 text/time/href 的文章列表
*/
private Map<String, Object> readColumn(Document document, String label, String columnId) {
List<NutMap> articles = new ArrayList<>();
for (Element link : document.select("a[href*='info/" + columnId + "/']")) {
Element row = link.closest("tr");
Element date = row == null ? null : row.selectFirst("td[class^=timestyle]");
String href = link.absUrl("href");
String title = link.attr("title").trim();
// title 属性包含未截断标题;属性缺失时使用可见文字,缺少日期时保留文章。
if (Strings.isBlank(title)) {
title = link.text();
}
if (Strings.isBlank(title) || !(href.startsWith("https://") || href.startsWith("http://"))) {
continue;
}
articles.add(NutMap.NEW().setv("text", title)
.setv("time", date == null ? "" : date.text()).setv("href", href));
}
return Map.of("label", label, "value", articles);
}
}
+4 -4
View File
@@ -1,6 +1,6 @@
nutz:
application:
name: zhgh_cug_v4
name: zhgh_cqgmy
mvc:
ignore: ^(.+[.])(jsp|png|gif|jpg|js|css|jspx|jpeg|html|mp3|mp4|ico|svg|vue)$
exclusions: /favicon/*,/assets/*,/druid/*,/upload/*,/components/*
@@ -21,7 +21,7 @@ jetty:
#结合ftp使用,或用nginx代理ftp路径
#staticPath: /Users/wizzer/temp/files
#开发模式静态资源
staticPathLocal: D:/myProject/zhgh_cug_v4/src/main/resources/static
staticPathLocal: D:/myProject/zhgh_cqgmy/src/main/resources/static
security:
tokenName: saToken
@@ -71,7 +71,7 @@ redis:
#nodes=192.168.6.31:6377,192.168.6.31:6378,192.168.6.28:6377,192.168.6.28:6378,192.168.6.34:6377,192.168.6.34:6378
jdbc:
url: jdbc:mysql://192.168.21.215/zhgh_cug_v4?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
url: jdbc:mysql://192.168.21.215/zhgh_cqgmy?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true
username: root
password: root
validationQuery: select 1
@@ -87,7 +87,7 @@ xsssql:
beetl:
RESOURCE:
#本地路径,开发时设置本地路径,便于调试
rootLocal: D:/myProject/zhgh_cug_v4/src/main/resources/views/
rootLocal: D:/myProject/zhgh_cqgmy/src/main/resources/views/
root: views/
DELIMITER_STATEMENT_START: "<!--#"
DELIMITER_STATEMENT_END: "#-->"
@@ -39,7 +39,8 @@ const jcdt = {
},
methods: {
onLink(item) {
const url = this.isHttpOrHttps(item.href) ? item.href : "https://xgh.cug.edu.cn/" + item.href
// 接口返回文章完整地址;相对地址按当前学校工会域名解析。
const url = this.isHttpOrHttps(item.href) ? item.href : new URL(item.href, "https://gh.cqgmy.edu.cn/").href
window.open(url)
},
isHttpOrHttps(url) {
@@ -3,8 +3,8 @@ const home = {
<div class="home-page">
<div class="home-summary-bar" :class="{'home-summary-bar--visible': showHomeSummary}">
<img class="home-summary-bar__logo"
src="/assets/mobile/img/home/v4/中国地质大学-logo.png"
alt="中国地质大学">
v-if="appLogo" :src="appLogo"
alt="学校 Logo">
<span class="home-summary-bar__divider"></span>
<span class="home-summary-bar__title">智慧工会</span>
</div>
@@ -14,8 +14,8 @@ const home = {
<div class="home-hero__content">
<div class="home-hero__topbar">
<img class="home-hero__brand-logo"
src="/assets/mobile/img/home/v4/中国地质大学-logo.png"
alt="中国地质大学">
v-if="appLogo" :src="appLogo"
alt="学校 Logo">
</div>
<div class="home-hero__title">智慧工会</div>
<div class="home-hero__subtitle">情系职工 · 真诚服务</div>
@@ -423,18 +423,23 @@ const home = {
}).catch(() => "")
},
listHomeBrand() {
const cached = this.readHomeCache("brand")
// 两处 Logo 共用 AppLogo 配置;独立缓存键避免读取此前误用的首页背景图缓存。
const cacheKey = "brandAppLogo"
const cached = this.readHomeCache(cacheKey)
if (cached) {
this.appLogo = cached.appLogo || ""
this.appName = cached.appName || ""
this.$set(this, "appLogo", cached.appLogo || "")
this.$set(this, "appName", cached.appName || "")
}
Promise.all([
this.getConfigValue("AppLogo"),
this.getConfigValue("AppName")
]).then(([appLogo, appName]) => {
this.appLogo = appLogo
this.appName = appName
this.writeHomeCache("brand", { appLogo, appName }, this.homeCacheTtl.brand)
]).then(([logoConfig, appName]) => {
// 配置支持逗号分隔多图;过滤空地址后取首图,空配置时不显示 Logo。
const images = this.parseBannerList(logoConfig)
const appLogo = images.length > 0 ? images[0].src : ""
this.$set(this, "appLogo", appLogo)
this.$set(this, "appName", appName)
this.writeHomeCache(cacheKey, { appLogo, appName }, this.homeCacheTtl.brand)
})
},
listRecommendApp() {
@@ -751,7 +756,6 @@ const home = {
height: 36px;
object-fit: contain;
object-position: left center;
filter: brightness(0) invert(1);
}
.home-hero__title {