diff --git a/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java b/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java index a0b3dc6..da51fc2 100644 --- a/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java +++ b/src/main/java/com/budwk/app/sys/services/SysHomeNewsService.java @@ -5,20 +5,20 @@ import org.nutz.lang.util.NutMap; import java.util.List; /** - * 首页工会网站新闻服务。 + * 首页风采墙新闻服务。 */ public interface SysHomeNewsService { /** - * 获取学校工会网站首页新闻。 + * 获取风采墙可见栏目下的已发布新闻。 * * @return 新闻栏目集合;每个栏目包含 label 栏目名称和 value 新闻列表, - * 新闻项包含 href 跳转地址、time 发布时间、text 新闻标题和 thumbUrl 缩略图绝对地址(无图时为空) + * 新闻项包含 href 跳转地址、time 发布时间、text 新闻标题和 thumbUrl 缩略图地址(无图时为空) */ List getWebsiteNews(); /** - * href 必须是工会首页返回的新闻链接;返回正文首图的绝对地址,无图或不可访问时为空字符串。 + * href 必须是首页返回的风采墙新闻链接;返回封面或正文首图地址,无图时为空字符串。 */ String getNewsImage(String href); } diff --git a/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java b/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java index 5407818..6c0e7ef 100644 --- a/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java +++ b/src/main/java/com/budwk/app/sys/services/impl/SysHomeNewsServiceImpl.java @@ -1,159 +1,108 @@ package com.budwk.app.sys.services.impl; import cn.hutool.core.util.StrUtil; +import cn.hutool.core.date.DateUtil; import com.budwk.app.sys.services.SysHomeNewsService; +import com.budwk.app.zhgh.spread.models.SpreadCategory; +import com.budwk.app.zhgh.spread.models.SpreadContent; +import com.budwk.app.zhgh.spread.service.SpreadCategoryService; +import com.budwk.app.zhgh.spread.service.SpreadContentService; import org.jsoup.Jsoup; -import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; -import org.jsoup.select.Elements; -import org.nutz.integration.jedis.RedisService; +import org.nutz.dao.Cnd; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.json.Json; import org.nutz.lang.util.NutMap; -import java.io.IOException; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.util.UUID; import java.util.Map; import java.util.ArrayList; -import java.util.Collections; import java.util.List; /** - * 首页工会网站新闻服务实现,统一为PC端和移动端提供同一份新闻数据。 + * 首页风采墙新闻服务实现,沿用首页新闻数据结构。 */ @IocBean public class SysHomeNewsServiceImpl implements SysHomeNewsService { - private static final String WEBSITE_URL = "https://xgh.cug.edu.cn/"; - private static final String NEWS_CACHE_KEY = "gonghui_news"; - private static final int NEWS_CACHE_SECONDS = 60 * 60 * 24; + @Inject + private SpreadCategoryService categoryService; @Inject - private RedisService redisService; + private SpreadContentService contentService; /** - * 抓取学校工会网站首页的工会要闻、基层动态等栏目。 - * 外部网站暂时不可用时优先返回最近一次缓存,避免PC端和移动端同时显示为空。 - * - * @return 新闻栏目集合;栏目 value 中的新闻项包含 href、time、text + * 按风采墙顶级栏目返回已发布内容,保留首页现有新闻数据结构。 */ @Override public List getWebsiteNews() { - try { - Document document = Jsoup.connect(WEBSITE_URL).timeout(10000).get(); - List news = parseWebsiteNews(document.select(".gh,.jc,.fc,.jg")); - if (!news.isEmpty()) { - redisService.setex(NEWS_CACHE_KEY, NEWS_CACHE_SECONDS, Json.toJson(news)); - return news; - } - return getCachedNews(); - } catch (IOException e) { - List cachedNews = getCachedNews(); - if (!cachedNews.isEmpty()) { - return cachedNews; - } - throw new RuntimeException("学校工会网站新闻获取失败", e); - } - } - - /** - * 将外部网站栏目节点转换为前端统一使用的栏目和新闻结构。 - */ - private List parseWebsiteNews(Elements homeElements) { + List categories = categoryService.listCategories(true); List sections = new ArrayList<>(); - for (Element homeElement : homeElements) { - Element titleElement = homeElement.selectFirst(".title"); - if (titleElement == null || StrUtil.isBlank(titleElement.text())) { - continue; + for (SpreadCategory category : categories) { + if (!"0".equals(category.getParentId())) continue; + List categoryIds = new ArrayList<>(); + categoryIds.add(category.getId()); + for (SpreadCategory child : categories) { + if (category.getId().equals(child.getParentId())) categoryIds.add(child.getId()); } + List contents = contentService.query(Cnd.where("delFlag", "=", false) + .and("isPublished", "=", 1).and("categoryId", "in", categoryIds) + .desc("isTop").desc("publishedAt").asc("sortOrder").desc("createdAt")); List rows = new ArrayList<>(); - for (Element itemElement : homeElement.select("li")) { - Element linkElement = itemElement.selectFirst("a"); - if (linkElement == null || StrUtil.isBlank(linkElement.attr("href"))) { - continue; - } - Element timeElement = itemElement.selectFirst("span"); - // 仅使用当前新闻条目的缩略图,按网页基址补全相对路径。 - Element imageElement = itemElement.selectFirst("img"); - String thumbUrl = imageElement == null ? "" : imageElement.absUrl("src"); - if (!thumbUrl.startsWith("https://") && !thumbUrl.startsWith("http://")) { - thumbUrl = ""; - } - String title = StrUtil.blankToDefault(linkElement.attr("title"), linkElement.text()); + for (SpreadContent content : contents) { + Long publishedAt = content.getPublishedAt(); rows.add(NutMap.NEW() - .addv("href", linkElement.attr("href")) - .addv("time", timeElement == null ? "" : timeElement.text()) - .addv("text", title) - .addv("thumbUrl", thumbUrl)); + .addv("href", "/platform/spread/display?id=" + content.getId()) + .addv("time", publishedAt == null ? "" : DateUtil.format(new java.util.Date(publishedAt), "yyyy-MM-dd")) + .addv("text", content.getTitle()) + .addv("thumbUrl", getContentImage(content))); } - sections.add(NutMap.NEW().addv("label", titleElement.text()).addv("value", rows)); + sections.add(NutMap.NEW().addv("label", category.getName()).addv("value", rows)); } return sections; } - /** - * 读取最近一次成功抓取的数据;缓存为空或内容异常时返回空集合。 - */ - private List getCachedNews() { - String cached = redisService.get(NEWS_CACHE_KEY); - if (StrUtil.isBlank(cached)) { - return Collections.emptyList(); + private String getContentImage(SpreadContent content) { + String image = ""; + if (StrUtil.isNotBlank(content.getThumbUrl())) { + Object value = content.getThumbUrl().trim(); + if (value.toString().startsWith("[") || value.toString().startsWith("{")) { + try { + value = Json.fromJson(value.toString()); + } catch (RuntimeException e) { + value = ""; + } + } + if (value instanceof List) { + List files = (List) value; + value = files.isEmpty() ? "" : files.get(0); + } + if (value instanceof Map) { + Map file = (Map) value; + value = file.get("src") != null ? file.get("src") : file.get("url"); + } + image = value == null ? "" : value.toString().split(",", 2)[0].trim(); } - try { - return Json.fromJsonAsList(NutMap.class, cached); - } catch (RuntimeException e) { - return Collections.emptyList(); + if (StrUtil.isBlank(image) && StrUtil.isNotBlank(content.getContentBody())) { + Element first = Jsoup.parse(content.getContentBody()).selectFirst("img[src]"); + if (first != null) image = first.attr("src"); } + return image.startsWith("/") && !image.startsWith("//") + || image.startsWith("https://") || image.startsWith("http://") ? image : ""; } /** - * 仅补取缓存新闻列表中已存在的公开文章,禁止任意地址抓取和自动重定向。 - * 正文首图独立缓存;无图短暂缓存,防止每次栏目切换重复访问外站。 + * 仅返回首页已发布风采内容的图片,不再请求外部新闻网站。 */ @Override public String getNewsImage(String href) { - if (StrUtil.isBlank(href) || href.length() > 2048) return ""; - boolean listed = false; - for (NutMap section : getCachedNews()) { - Object values = section.get("value"); - if (!(values instanceof List)) continue; - for (Object value : (List) values) { - if (value instanceof Map && href.equals(((Map) value).get("href"))) { - listed = true; - break; - } + if (StrUtil.isBlank(href)) return ""; + for (NutMap section : getWebsiteNews()) { + for (Object value : (List) section.get("value")) { + NutMap news = (NutMap) value; + if (href.equals(news.getString("href"))) return news.getString("thumbUrl"); } } - if (!listed) return ""; - try { - URI uri = URI.create(WEBSITE_URL).resolve(href); - String host = uri.getHost(); - // 来源限制为学校公开网站和微信公众号,端口及凭据均不接受自定义。 - if (host == null || !(host.equals("cug.edu.cn") || host.endsWith(".cug.edu.cn") - || host.equals("mp.weixin.qq.com")) || uri.getUserInfo() != null - || uri.getPort() != -1 || !("https".equals(uri.getScheme()) || "http".equals(uri.getScheme()))) return ""; - String cacheKey = "gonghui_news_image:" + UUID.nameUUIDFromBytes(uri.toString().getBytes(StandardCharsets.UTF_8)); - String cached = redisService.get(cacheKey); - if (cached != null) return "-".equals(cached) ? "" : cached; - String image = ""; - try { - Document article = Jsoup.connect(uri.toString()).timeout(5000).maxBodySize(2 * 1024 * 1024) - .followRedirects(false).get(); - Element first = article.selectFirst(".v_news_content img, #js_content img"); - if (first != null) { - image = first.hasAttr("data-src") ? first.absUrl("data-src") : first.absUrl("src"); - } - if (!image.startsWith("https://") && !image.startsWith("http://")) image = ""; - } catch (IOException ignored) { - // 外站失败不影响首页新闻文字和栏目切换,五分钟后允许再次补取。 - } - redisService.setex(cacheKey, image.isEmpty() ? 300 : NEWS_CACHE_SECONDS, image.isEmpty() ? "-" : image); - return image; - } catch (IllegalArgumentException e) { - return ""; - } + return ""; } } diff --git a/src/main/java/com/budwk/app/zhgh/spread/controller/SpreadDisplayController.java b/src/main/java/com/budwk/app/zhgh/spread/controller/SpreadDisplayController.java index 3ec323f..c44a779 100644 --- a/src/main/java/com/budwk/app/zhgh/spread/controller/SpreadDisplayController.java +++ b/src/main/java/com/budwk/app/zhgh/spread/controller/SpreadDisplayController.java @@ -44,6 +44,15 @@ public class SpreadDisplayController { return Result.success(contentService.pagePublished(pageForm, categoryId)); } + @At + @ApiOperation("热门内容分页") + @SaCheckPermission("spread.display") + public Result hotData(PageForm pageForm) { + pageForm.setPageNumber(pageForm.getPageNumber() == null ? 1 : Math.max(1, pageForm.getPageNumber())); + pageForm.setPageSize(10); + return Result.success(contentService.pagePublished(pageForm, null, null, "views", null, null)); + } + @At @ApiOperation("内容详情") @SaCheckPermission("spread.display") diff --git a/src/main/java/com/budwk/app/zhgh/spread/service/impl/SpreadContentServiceImpl.java b/src/main/java/com/budwk/app/zhgh/spread/service/impl/SpreadContentServiceImpl.java index c1f806e..73d9740 100644 --- a/src/main/java/com/budwk/app/zhgh/spread/service/impl/SpreadContentServiceImpl.java +++ b/src/main/java/com/budwk/app/zhgh/spread/service/impl/SpreadContentServiceImpl.java @@ -97,6 +97,19 @@ public class SpreadContentServiceImpl extends BaseServiceImpl imp query.setTitle(title); query.setIsPublished(1); Cnd cnd = buildCondition(query); + List visibleCategories = dao().query(SpreadCategory.class, + Cnd.where("delFlag", "=", false).and("visible", "=", 1)); + List visibleIds = new ArrayList<>(); + for (SpreadCategory category : visibleCategories) { + if ("0".equals(category.getParentId()) || visibleCategories.stream() + .anyMatch(parent -> parent.getId().equals(category.getParentId()) && "0".equals(parent.getParentId()))) { + visibleIds.add(category.getId()); + } + } + if (visibleIds.isEmpty()) { + return new Pagination<>(pageForm.getPageNumber(), pageForm.getPageSize(), 0, Collections.emptyList()); + } + cnd.and("c.categoryId", "in", visibleIds); if (publishDays != null && publishDays > 0) { cnd.and("c.publishedAt", ">=", System.currentTimeMillis() - publishDays * 24L * 60L * 60L * 1000L); } @@ -139,7 +152,7 @@ public class SpreadContentServiceImpl extends BaseServiceImpl imp return "c.publishedAt DESC, c.createdAt DESC"; } if ("views".equals(sortType)) { - return "c.viewCount DESC, c.publishedAt DESC, c.createdAt DESC"; + return "c.viewCount DESC, c.publishedAt DESC, c.id DESC"; } return "c.isTop DESC, c.publishedAt DESC, c.sortOrder ASC, c.createdAt DESC"; } @@ -222,6 +235,8 @@ public class SpreadContentServiceImpl extends BaseServiceImpl imp LEFT JOIN spread_category parent ON parent.id = child.parentId WHERE c.delFlag = 0 AND c.isPublished = 1 + AND c.thumbUrl IS NOT NULL + AND TRIM(c.thumbUrl) <> '' AND child.delFlag = 0 AND child.visible = 1 AND child.slider = 1 @@ -273,7 +288,7 @@ public class SpreadContentServiceImpl extends BaseServiceImpl imp } /** - * 校验并规范每张轮播图的标题,轮播图统一继承内容所属工会。 + * 校验每张轮播图的标题和所属工会,兼容未单独设置工会的历史图片。 */ private void validateSliderImages(SpreadContent content) { if (StrUtil.isBlank(content.getSliderImages())) { @@ -301,6 +316,10 @@ public class SpreadContentServiceImpl extends BaseServiceImpl imp JSONObject normalizedItem = new JSONObject(); normalizedItem.set("src", item.getStr("src")); normalizedItem.set("title", item.getStr("title").trim()); + Sys_union imageUnion = requireSelectableUnion(StrUtil.isBlank(item.getStr("unionId")) + ? content.getUnionId() : item.getStr("unionId")); + normalizedItem.set("unionId", imageUnion.getId()); + normalizedItem.set("unionName", imageUnion.getName()); normalizedArray.add(normalizedItem); } content.setSliderImages(JSONUtil.toJsonStr(normalizedArray)); diff --git a/src/main/resources/application-dev.yaml b/src/main/resources/application-dev.yaml index 6e4d1d5..ba4d1b6 100644 --- a/src/main/resources/application-dev.yaml +++ b/src/main/resources/application-dev.yaml @@ -9,10 +9,11 @@ contextPath: "" staticPathLocal: '' redis: - host: 127.0.0.1 + host: 175.27.165.74 port: 6379 - database: 1 + database: 4 mode: normal + password: ddss@2025 jdbc: url: jdbc:mysql://127.0.0.1:10086/zhgh_zjnu?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true username: root diff --git a/src/main/resources/static/assets/mobile/img/home/v4/spread-news-empty.png b/src/main/resources/static/assets/mobile/img/home/v4/spread-news-empty.png new file mode 100644 index 0000000..ea583b5 Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/home/v4/spread-news-empty.png differ diff --git a/src/main/resources/static/assets/mobile/img/home/v4/spread-news-header.png b/src/main/resources/static/assets/mobile/img/home/v4/spread-news-header.png new file mode 100644 index 0000000..7804c5e Binary files /dev/null and b/src/main/resources/static/assets/mobile/img/home/v4/spread-news-header.png differ diff --git a/src/main/resources/static/assets/platform/img/spread-culture-banner.png b/src/main/resources/static/assets/platform/img/spread-culture-banner.png new file mode 100644 index 0000000..7d18a19 Binary files /dev/null and b/src/main/resources/static/assets/platform/img/spread-culture-banner.png differ diff --git a/src/main/resources/static/assets/platform/js/spread-back-button.js b/src/main/resources/static/assets/platform/js/spread-back-button.js new file mode 100644 index 0000000..d9dd780 --- /dev/null +++ b/src/main/resources/static/assets/platform/js/spread-back-button.js @@ -0,0 +1,152 @@ + + +Vue.component("spread-back-button", { + template: `
+ +
+ + + + + +
+ +
+
`, + props: { + path: { + type: String, + default: '/platform/h5/home' + } + }, + data() { + return { + x: 20, + y: 200, + dragging: false, + offsetX: 0, + offsetY: 0, + + startX: 0, + startY: 0, + moved: false, + + ripples: [], + rippleId: 0 + } + }, + + mounted() { + const pos = localStorage.getItem("float-btn-pos") + if (pos) { + const { x, y } = JSON.parse(pos) + this.x = x + this.y = y + } + + window.addEventListener("mousemove", this.onDrag) + window.addEventListener("mouseup", this.endDrag) + + window.addEventListener("touchmove", this.onDrag, { passive: false }) + window.addEventListener("touchend", this.endDrag) + }, + + beforeDestroy() { + window.removeEventListener("mousemove", this.onDrag) + window.removeEventListener("mouseup", this.endDrag) + + window.removeEventListener("touchmove", this.onDrag) + window.removeEventListener("touchend", this.endDrag) + }, + + methods: { + startDrag(e) { + const point = e.touches ? e.touches[0] : e + + this.dragging = true + this.moved = false + + this.startX = point.clientX + this.startY = point.clientY + + this.offsetX = point.clientX - this.x + this.offsetY = point.clientY - this.y + }, + + onDrag(e) { + if (!this.dragging) return + + if (e.cancelable) e.preventDefault() + + const point = e.touches ? e.touches[0] : e + + let newX = point.clientX - this.offsetX + let newY = point.clientY - this.offsetY + + const btnSize = 54 + const maxX = window.innerWidth - btnSize + const maxY = window.innerHeight - btnSize + + this.x = Math.max(0, Math.min(newX, maxX)) + this.y = Math.max(0, Math.min(newY, maxY)) + + const dx = Math.abs(point.clientX - this.startX) + const dy = Math.abs(point.clientY - this.startY) + + if (dx > 5 || dy > 5) { + this.moved = true + } + }, + + endDrag() { + if (!this.dragging) return + + this.dragging = false + + localStorage.setItem( + "float-btn-pos", + JSON.stringify({ + x: this.x, + y: this.y + }) + ) + }, + + handleClick(e) { + + if (this.moved) return + + const point = e.changedTouches ? e.changedTouches[0] : e + + const rect = this.$el.getBoundingClientRect() + const id = this.rippleId++ + + this.ripples.push({ + id, + x: point.clientX - rect.left, + y: point.clientY - rect.top + }) + + setTimeout(() => { + this.ripples = this.ripples.filter(r => r.id !== id) + }, 600) + if (this.path === '-1') { + window.history.back() + } else { + this.$pjaxReplace(this.path) + } + } + } +}) \ No newline at end of file diff --git a/src/main/resources/views/layouts/v4/home/jcdt.js b/src/main/resources/views/layouts/v4/home/jcdt.js index 365fe0a..dbe61a6 100644 --- a/src/main/resources/views/layouts/v4/home/jcdt.js +++ b/src/main/resources/views/layouts/v4/home/jcdt.js @@ -60,7 +60,7 @@ const jcdt = { this.pageNumber = 1 }, onLink(item) { - const url = this.isHttpOrHttps(item.href) ? item.href : "https://xgh.cug.edu.cn/" + item.href + const url = item.href window.open(url) }, isHttpOrHttps(url) { diff --git a/src/main/resources/views/platform/zhgh/spread/creation/index.html b/src/main/resources/views/platform/zhgh/spread/creation/index.html index f06e37a..fabafe6 100644 --- a/src/main/resources/views/platform/zhgh/spread/creation/index.html +++ b/src/main/resources/views/platform/zhgh/spread/creation/index.html @@ -80,7 +80,7 @@ layout("/layouts/platform.html"){ upload_mode="image" upload_result_category="interval">
建议使用横版图片,单张不超过 10MB。
- +
点击下方“+”新增轮播图片 已添加 {{sliderMeta.length}} / 10 张 @@ -88,7 +88,7 @@ layout("/layouts/platform.html"){ -
仅栏目开启“参与轮播”后生效,最多上传 10 张;每张图片只需填写标题,工会名称沿用内容所属工会。
+
用于内容详情页轮播,最多上传 10 张;请填写每张图片的标题和所属工会。首页轮播使用内容封面图。
可调整顺序,轮播将按当前顺序展示。 @@ -105,6 +105,10 @@ layout("/layouts/platform.html"){ * 图片标题 + * 所属工会 + + +
@@ -160,23 +164,6 @@ layout("/layouts/platform.html"){ } } }, - computed: { - // 仅所选末级栏目及其上级栏目都开启轮播时,显示轮播图片配置。 - sliderEnabled() { - if (!this.formData.categoryId) return false - const findPath = (nodes, categoryId, parents) => { - for (const node of nodes || []) { - const path = parents.concat(node) - if (node.id === categoryId) return path - const childPath = findPath(node.children, categoryId, path) - if (childPath) return childPath - } - return null - } - const categoryPath = findPath(this.categoryOptions, this.formData.categoryId, []) - return !!categoryPath && categoryPath.every(item => Number(item.slider) === 1) - } - }, methods: { // 生成新增内容时使用的默认表单。 defaultForm() { @@ -214,6 +201,9 @@ layout("/layouts/platform.html"){ contentUnionChanged(unionId) { const union = this.unionOptions.find(item => item.id === unionId) this.formData.unionName = union ? union.name : "" + this.sliderMeta.forEach(item => { + if (!item.unionId) item.unionId = unionId + }) }, // 分工会人员只有一个可选工会时自动带入,校工会管理员仍需主动选择。 @@ -240,7 +230,7 @@ layout("/layouts/platform.html"){ } }).finally(() => this.loading = false) }, - // 兼容历史图片地址数组,并转换为只包含图片地址和标题的轮播对象。 + // 兼容历史图片地址数组,未设置工会的图片默认使用内容所属工会。 parseSliderImages(value) { if (!value) return [] let items = value @@ -254,11 +244,12 @@ layout("/layouts/platform.html"){ if (!Array.isArray(items)) return [] return items.map(item => { if (typeof item === "string") { - return {src: item, title: ""} + return {src: item, title: "", unionId: this.formData.unionId || ""} } return { src: item.src || item.url || item.data || (item.response && item.response.data) || "", - title: item.title || "" + title: item.title || "", + unionId: item.unionId || this.formData.unionId || "" } }).filter(item => item.src) }, @@ -272,7 +263,7 @@ layout("/layouts/platform.html"){ const oldItems = {} this.sliderMeta.forEach(item => oldItems[item.src] = item) this.sliderMeta = (this.sliderFiles || []).map(item => this.getSliderFileUrl(item)).filter(Boolean).map(src => { - return oldItems[src] || {src: src, title: ""} + return oldItems[src] || {src: src, title: "", unionId: this.formData.unionId || ""} }) this.applyUnionDefaults() }, @@ -301,20 +292,21 @@ layout("/layouts/platform.html"){ this.$message.success("轮播图片已清空") }).catch(() => {}) }, - // 将轮播图片地址和标题转换为可持久化 JSON。 + // 将轮播图片地址、标题和所属工会转换为可持久化 JSON。 buildSliderImages() { this.syncSliderMeta() return JSON.stringify(this.sliderMeta.map(item => ({ src: item.src, - title: item.title + title: item.title, + unionId: item.unionId }))) }, - // 校验每张轮播图的标题。 + // 校验每张轮播图的标题和所属工会。 validateSliderMeta() { this.syncSliderMeta() - const invalidIndex = this.sliderMeta.findIndex(item => !item.title) + const invalidIndex = this.sliderMeta.findIndex(item => !item.title || !item.unionId) if (invalidIndex < 0) return true - this.$message.warning("请输入第" + (invalidIndex + 1) + "张轮播图标题") + this.$message.warning("请完善第" + (invalidIndex + 1) + "张轮播图的标题和所属工会") return false }, // 重置新增表单;编辑状态下恢复数据库内容。 @@ -334,14 +326,9 @@ layout("/layouts/platform.html"){ submit() { this.$refs.contentForm.validate(valid => { if (!valid) return - if (this.sliderEnabled && !this.validateSliderMeta()) return + if (!this.validateSliderMeta()) return const data = Object.assign({}, this.formData) - if (this.sliderEnabled) { - data.sliderImages = this.buildSliderImages() - } else { - // 未开启轮播的栏目不提交隐藏字段,编辑时保留已有数据,避免切换栏目造成误删。 - delete data.sliderImages - } + data.sliderImages = this.buildSliderImages() // 推荐和头条没有对应业务逻辑,提交时不再携带这两个字段。 delete data.isRecommend delete data.isHeadline diff --git a/src/main/resources/views/platform/zhgh/spread/display/index.html b/src/main/resources/views/platform/zhgh/spread/display/index.html index 971e129..3902448 100644 --- a/src/main/resources/views/platform/zhgh/spread/display/index.html +++ b/src/main/resources/views/platform/zhgh/spread/display/index.html @@ -2,161 +2,1229 @@ layout("/layouts/platform.html"){ #-->
-
-
- - 风采墙 -
- -
- - -
- -
-
-
- {{item.unionName || item.categoryName || '风采展示'}}{{item.title}} -
-
-
-
-
-
-
榜样引领 · 风采绽放
-
-
- -
- - -
- - -
+
+
+ 工会信息传播与文化展示:凝聚职工力量,传播工会声音
+
+ +
+
+

热门内容

+
+ +
加载中...
+ + + + +
已显示全部内容
+
+
+
+
+ +
+
+ +
+ +
+
+ +
+
+ +
+ + +
+
+ + + + +
+
+
+ {{ item.title }} +
+ 置顶 +
+
{{ item.summary }}
+
+ 发布时间:{{ datePart(item.publishedAt, 'YYYY-MM-DD') }} + 所属栏目:{{ item.categoryName }} + 所属工会:{{ item.unionName }} +
+
+
+ + + +
+ +
+
+ +
+
+ + + 返回列表 + +
+ +
+

{{ detail.title }}

+ + +
+
+ + + + + +
+
{{ image.title }}
+
{{ image.unionName }}
+
+
+
+ + + + +
+
+
+ +
+
+
+
+
+
+
+
diff --git a/src/main/resources/views/platform/zhghh5/spread/display/detail.html b/src/main/resources/views/platform/zhghh5/spread/display/detail.html index c59b0db..9bfb60c 100644 --- a/src/main/resources/views/platform/zhghh5/spread/display/detail.html +++ b/src/main/resources/views/platform/zhghh5/spread/display/detail.html @@ -2,60 +2,252 @@ layout("/layouts/platform_h5.html"){ #--> -
+
- -
- - - +
+
+ +
+ + + +
+ + +
+ +
+
+
+

{{ detail.title }}

+ +
{{ detail.summary }}
+ + + + + +
+
- -
-

{{detail.title}}

-
- {{formatDate(detail.publishedAt || detail.createdAt)}} {{detail.categoryName}}  - {{detail.viewCount || 0}} -
- -
{{detail.summary}}
- - -
- -
{{slide.title}}
-
-
-
-
-
- -
动态不存在或已下架
+ +
diff --git a/src/main/resources/views/platform/zhghh5/sys/home/home.js b/src/main/resources/views/platform/zhghh5/sys/home/home.js index a8b6a79..f961184 100644 --- a/src/main/resources/views/platform/zhghh5/sys/home/home.js +++ b/src/main/resources/views/platform/zhghh5/sys/home/home.js @@ -3,8 +3,8 @@ const home = {
+ :src="appLogo" + :alt="appName"> 智慧工会
@@ -14,8 +14,8 @@ const home = {
+ :src="appLogo" + :alt="appName">
智慧工会
情系职工 · 真诚服务
@@ -70,25 +70,12 @@ const home = {
- +
工会动态
全部动态
-
-
-
+
- -
- -
{{ formatSpreadDate(item.publishedAt || item.createdAt) }} - + - {{ item.viewCount }} + {{ item.viewCount || 0 }}
@@ -265,10 +247,6 @@ const home = { classroomRecommendOptions: [], showHomeSummary: false, homeScrollContainer: null, - spreadSections: [], - spreadMenuVisible: false, - spreadHistoryToken: null, - spreadActiveIndex: 0, spreadDynamics: [], spreadLoading: true, spreadLoadSeq: 0, @@ -298,14 +276,14 @@ const home = { className: "feature-card--model", href: "/platform/honor/manage/h5" }, - { + /* { name: "普惠信息", desc: "普惠服务信息", action: "查看信息", asset: "/assets/mobile/img/home/v4/feature-inclusive-v8.png", className: "feature-card--inclusive", href: "/platform/h5/inclusive" - } + } */ ], appLogo: "", appName: "", @@ -333,10 +311,6 @@ const home = { } }, computed: { - spreadHasImages() { - // 按当前栏目统一保留图片列;异步补图及加载失败都会重新计算,全部无图时文字占满行宽。 - return this.spreadDynamics.some(item => item.thumbUrl && !item.imageFailed) - }, currentBanner() { return this.bannerList[this.activeBannerIndex] || this.bannerList[0] || {} } @@ -542,29 +516,18 @@ const home = { listSpreadHomeContent() { const loadSeq = ++this.spreadLoadSeq this.spreadLoading = true - this.$axios.post("/platform/home/getNews").then((res) => { + this.$axios.post("/platform/h5/spread/pageData", { + sortType: "latest", + pageNumber: 1, + pageSize: 10 + }).then((res) => { if (loadSeq === this.spreadLoadSeq && res.code === 0) { - // 接口按栏目返回 href/time/text,移动端保存全部栏目供切换,并映射为现有动态卡片字段。 - const sections = (Array.isArray(res.data) ? res.data : []).map(section => ({ - label: section.label || "工会动态", - value: (Array.isArray(section.value) ? section.value : []).slice(0, 10).map(item => ({ - href: item.href || "", - thumbUrl: /^https?:\/\//i.test(item.thumbUrl || "") ? item.thumbUrl : "", - imageFailed: false, - imageRequested: false, - title: item.text || "", - publishedAt: item.time || "", - categoryName: section.label || "工会动态" - })).filter(item => item.title) - })) - const firstAvailableIndex = sections.findIndex(section => section.value.length) - this.$set(this, "spreadSections", sections) - this.selectSpreadSection(firstAvailableIndex >= 0 ? firstAvailableIndex : 0) + const data = res.data || {} + this.spreadDynamics = data.list || [] } }).catch(() => { if (loadSeq === this.spreadLoadSeq) { - this.$set(this, "spreadSections", []) - this.$set(this, "spreadDynamics", []) + this.spreadDynamics = [] } }).finally(() => { if (loadSeq === this.spreadLoadSeq) { @@ -572,48 +535,6 @@ const home = { } }) }, - selectSpreadSection(index) { - // 切换栏目后回到横向卡片列表开头,等待新栏目列表渲染完成。 - // 新闻样式锚定 home-page 根节点作用域,动态行无需等待 styleMixin 异步补属性。 - const section = this.spreadSections[index] || {} - this.$set(this, "spreadActiveIndex", index) - this.$set(this, "spreadDynamics", section.value || []) - this.$nextTick(() => { - if (this.$refs.spreadViewport) this.$refs.spreadViewport.scrollLeft = 0 - }) - this.loadSpreadImages() - }, - loadSpreadImages() { - // href 传原始新闻链接;data 为正文首图地址。每条只补取一次,回填原对象避免快速切换串图。 - const missing = this.spreadDynamics.filter(item => !item.thumbUrl && !item.imageRequested) - missing.forEach(item => this.$set(item, "imageRequested", true)) - // 串行补图限制外站并发;切换后仍可缓存到对应栏目,不阻塞新闻展示。 - missing.reduce((pending, item) => pending.then(() => { - return this.$axios.post("/platform/home/getNewsImage", {href: item.href}).then(res => { - if (res.code === 0 && /^https?:\/\//i.test(res.data || "")) { - this.$set(item, "thumbUrl", res.data) - this.$set(item, "imageFailed", false) - } - }).catch(() => {}) - }), Promise.resolve()) - }, - openSpreadMenu() { - // 栏目选择弹层交由全局历史栈管理,系统返回键仅关闭当前弹层。 - if (this.spreadMenuVisible) { - this.closeSpreadMenu() - return - } - if (this.spreadSections.length < 2) return - window.h5PopupHistory.open(this.spreadHistoryToken, "news-section") - this.$set(this, "spreadMenuVisible", true) - }, - closeSpreadMenu() { - if (this.spreadMenuVisible) window.h5PopupHistory.close(this.spreadHistoryToken, "news-section") - }, - chooseSpreadSection(index) { - this.selectSpreadSection(index) - this.closeSpreadMenu() - }, getSpreadCategoryLabels(item) { const labels = [item.parentCategoryName, item.childCategoryName].filter(Boolean) return labels.length ? labels : (item.categoryName ? [item.categoryName] : []) @@ -647,22 +568,10 @@ const home = { return Number.isNaN(numberValue) ? String(value) : this.$moment(numberValue).format("YYYY-MM-DD") }, enterSpreadDetail(item) { - const url = this.resolveUnionNewsUrl(item.href) - if (url) { - window.location.href = url - } + this.$pjaxReplace("/platform/h5/spread/detail?id=" + encodeURIComponent(item.id) + "&from=home") }, enterSpreadList() { - window.location.href = "https://xgh.cug.edu.cn/" - }, - resolveUnionNewsUrl(href) { - if (!href) { - return "" - } - if (/^https?:\/\//i.test(href)) { - return href - } - return new URL(href, "https://xgh.cug.edu.cn/").href + this.$pjaxReplace("/platform/h5/spread") }, menuClick(item) { this.$pjaxReplace(item.href) @@ -701,10 +610,6 @@ const home = { } }, created() { - // 注册弹层返回回调,关闭状态由历史回退同步,避免留下多余历史记录。 - this.spreadHistoryToken = window.h5PopupHistory.register(() => { - this.$set(this, "spreadMenuVisible", false) - }) this.listHomeBrand() this.listRecommendApp() this.listClassroomCourses() @@ -722,8 +627,6 @@ const home = { } }, beforeDestroy() { - const token = this.spreadHistoryToken - window.h5PopupHistory.clear(token).then(() => window.h5PopupHistory.unregister(token)) if (this.homeScrollContainer) { this.homeScrollContainer.removeEventListener("scroll", this.handleHomeScroll) } @@ -997,7 +900,8 @@ const home = { margin: 0 12px 7px; display: grid; grid-template-columns: 1.08fr 1fr; - grid-template-rows: 86px 86px 92px; + grid-template-rows: 86px 86px; + grid-auto-rows: 92px; gap: 8px; }