jinxia.mo 1 mese fa
parent
commit
8c61ce450e

+ 44 - 0
back-ui/src/api/system/bWwwNews.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询资讯管理列表
+export function listBWwwNews(query) {
+  return request({
+    url: '/system/bWwwNews/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询资讯管理详细
+export function getBWwwNews(id) {
+  return request({
+    url: '/system/bWwwNews/' + id,
+    method: 'get'
+  })
+}
+
+// 新增资讯管理
+export function addBWwwNews(data) {
+  return request({
+    url: '/system/bWwwNews',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改资讯管理
+export function updateBWwwNews(data) {
+  return request({
+    url: '/system/bWwwNews',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除资讯管理
+export function delBWwwNews(id) {
+  return request({
+    url: '/system/bWwwNews/' + id,
+    method: 'delete'
+  })
+}

+ 44 - 0
back-ui/src/api/system/bWwwNewsRef.js

@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 查询通关指南列表
+export function listBWwwNewsRef(query) {
+  return request({
+    url: '/system/bWwwNewsRef/list',
+    method: 'get',
+    params: query
+  })
+}
+
+// 查询通关指南详细
+export function getBWwwNewsRef(id) {
+  return request({
+    url: '/system/bWwwNewsRef/' + id,
+    method: 'get'
+  })
+}
+
+// 新增通关指南
+export function addBWwwNewsRef(data) {
+  return request({
+    url: '/system/bWwwNewsRef',
+    method: 'post',
+    data: data
+  })
+}
+
+// 修改通关指南
+export function updateBWwwNewsRef(data) {
+  return request({
+    url: '/system/bWwwNewsRef',
+    method: 'put',
+    data: data
+  })
+}
+
+// 删除通关指南
+export function delBWwwNewsRef(id) {
+  return request({
+    url: '/system/bWwwNewsRef/' + id,
+    method: 'delete'
+  })
+}

+ 94 - 0
back-ui/src/utils/imageHelper.js

@@ -0,0 +1,94 @@
+/**
+ * 图片处理工具函数
+ * 用于处理图片URL、防盗链等问题
+ */
+
+/**
+ * 获取图片代理URL(如果需要后端代理,可以在这里实现)
+ * @param {string} imageUrl - 图片URL
+ * @returns {string} 处理后的图片URL
+ */
+export function getImageProxyUrl(imageUrl) {
+    if (!imageUrl) return ''
+
+    // 如果是相对路径或本地路径,直接返回
+    if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://') && !imageUrl.startsWith('//')) {
+        return imageUrl
+    }
+
+    // 如果需要通过后端代理访问第三方图片,可以取消下面的注释
+    // 注意:需要后端提供图片代理接口
+    // const encodedUrl = encodeURIComponent(imageUrl)
+    // return `${import.meta.env.VITE_APP_BASE_API}/common/image/proxy?url=${encodedUrl}`
+
+    // 暂时直接返回原URL,通过添加跨域属性来处理
+    return imageUrl
+}
+
+/**
+ * 格式化内容,将图片URL转换为img标签
+ * 处理HTML中的图片标签和纯文本中的图片URL
+ * @param {string} content - 需要格式化的内容
+ * @returns {string} 格式化后的内容
+ */
+export function formatContentWithImages(content) {
+    if (!content) return ''
+
+    // 如果内容已经是HTML格式(包含img标签),需要处理其中的图片URL
+    if (content.includes('<img') || content.includes('<IMG')) {
+        // 提取所有img标签中的src属性
+        const imgSrcRegex = /<img[^>]+src=["']([^"']+)["'][^>]*>/gi
+        let formattedContent = content
+
+        formattedContent = formattedContent.replace(imgSrcRegex, (match, src) => {
+            // 如果是第三方图片URL,转换为代理URL
+            let imageUrl = src
+            if (src.startsWith('http://') || src.startsWith('https://') || src.startsWith('//')) {
+                // 对于第三方图片,尝试使用代理
+                // 如果代理不可用,则使用原URL并添加跨域属性
+                imageUrl = getImageProxyUrl(src)
+                // 如果代理URL和原URL相同(代理不可用),添加跨域属性
+                if (imageUrl === src) {
+                    return match.replace(src, src).replace('<img', '<img crossorigin="anonymous" referrerpolicy="no-referrer"')
+                } else {
+                    return match.replace(src, imageUrl)
+                }
+            }
+            return match
+        })
+
+        return formattedContent
+    }
+
+    // 匹配图片URL的正则表达式
+    // 支持:https://、http://、//开头的完整URL,以及相对路径
+    const imageUrlRegex = /(https?:\/\/[^\s<>"']+\.(jpg|jpeg|png|gif|bmp|webp|svg)(\?[^\s<>"']*)?)|(\/\/[^\s<>"']+\.(jpg|jpeg|png|gif|bmp|webp|svg)(\?[^\s<>"']*)?)|(\/[^\s<>"']+\.(jpg|jpeg|png|gif|bmp|webp|svg)(\?[^\s<>"']*)?)/gi
+
+    // 将纯文本的图片URL转换为img标签
+    let formattedContent = content
+    const matches = content.match(imageUrlRegex)
+
+    if (matches) {
+        matches.forEach(url => {
+            // 确保URL是完整的
+            let imageUrl = url.trim()
+            // 如果是以//开头的,添加https:
+            if (imageUrl.startsWith('//')) {
+                imageUrl = 'https:' + imageUrl
+            }
+
+            // 对于第三方图片,尝试使用代理
+            const proxyUrl = getImageProxyUrl(imageUrl)
+            // 如果代理不可用,使用原URL并添加跨域属性
+            const finalUrl = proxyUrl !== imageUrl ? proxyUrl : imageUrl
+            const crossOriginAttr = proxyUrl === imageUrl ? 'crossorigin="anonymous" referrerpolicy="no-referrer"' : ''
+
+            // 将URL替换为img标签
+            const imgTag = `<img src="${finalUrl}" ${crossOriginAttr} alt="图片" style="max-width: 100%; height: auto; display: block; margin: 10px 0;" onerror="this.onerror=null; this.src='${imageUrl}'; this.style.border='1px solid #ddd'; this.alt='图片加载失败,点击查看原图'; this.style.cursor='pointer'; this.title='点击查看原图'; this.onclick='window.open(this.src)';" />`
+            formattedContent = formattedContent.replace(url, imgTag)
+        })
+    }
+
+    return formattedContent
+}
+

+ 1 - 80
back-ui/src/views/learn/questions/index.vue

@@ -621,6 +621,7 @@ import {ElMessage, ElLoading} from "element-plus";
 import DictTag from '@/components/DictTag/index.vue'
 import Editor from '@/components/Editor/index.vue'
 import { computed } from 'vue'
+import { getImageProxyUrl, formatContentWithImages } from '@/utils/imageHelper'
 
 const {proxy} = getCurrentInstance()
 const {question_type} = proxy.useDict('question_type')
@@ -1314,86 +1315,6 @@ function submitKnowledgeQuestionForm() {
     })
 }
 
-/** 获取图片代理URL(如果需要后端代理,可以在这里实现) */
-function getImageProxyUrl(imageUrl) {
-    if (!imageUrl) return ''
-
-    // 如果是相对路径或本地路径,直接返回
-    if (!imageUrl.startsWith('http://') && !imageUrl.startsWith('https://') && !imageUrl.startsWith('//')) {
-        return imageUrl
-    }
-
-    // 如果需要通过后端代理访问第三方图片,可以取消下面的注释
-    // 注意:需要后端提供图片代理接口
-    // const encodedUrl = encodeURIComponent(imageUrl)
-    // return `${import.meta.env.VITE_APP_BASE_API}/common/image/proxy?url=${encodedUrl}`
-
-    // 暂时直接返回原URL,通过添加跨域属性来处理
-    return imageUrl
-}
-
-/** 格式化内容,将图片URL转换为img标签 */
-function formatContentWithImages(content) {
-    if (!content) return ''
-
-    // 如果内容已经是HTML格式(包含img标签),需要处理其中的图片URL
-    if (content.includes('<img') || content.includes('<IMG')) {
-        // 提取所有img标签中的src属性
-        const imgSrcRegex = /<img[^>]+src=["']([^"']+)["'][^>]*>/gi
-        let formattedContent = content
-
-        formattedContent = formattedContent.replace(imgSrcRegex, (match, src) => {
-            // 如果是第三方图片URL,转换为代理URL
-            let imageUrl = src
-            if (src.startsWith('http://') || src.startsWith('https://') || src.startsWith('//')) {
-                // 对于第三方图片,尝试使用代理
-                // 如果代理不可用,则使用原URL并添加跨域属性
-                imageUrl = getImageProxyUrl(src)
-                // 如果代理URL和原URL相同(代理不可用),添加跨域属性
-                if (imageUrl === src) {
-                    return match.replace(src, src).replace('<img', '<img crossorigin="anonymous" referrerpolicy="no-referrer"')
-                } else {
-                    return match.replace(src, imageUrl)
-                }
-            }
-            return match
-        })
-
-        return formattedContent
-    }
-
-    // 匹配图片URL的正则表达式
-    // 支持:https://、http://、//开头的完整URL,以及相对路径
-    const imageUrlRegex = /(https?:\/\/[^\s<>"']+\.(jpg|jpeg|png|gif|bmp|webp|svg)(\?[^\s<>"']*)?)|(\/\/[^\s<>"']+\.(jpg|jpeg|png|gif|bmp|webp|svg)(\?[^\s<>"']*)?)|(\/[^\s<>"']+\.(jpg|jpeg|png|gif|bmp|webp|svg)(\?[^\s<>"']*)?)/gi
-
-    // 将纯文本的图片URL转换为img标签
-    let formattedContent = content
-    const matches = content.match(imageUrlRegex)
-
-    if (matches) {
-        matches.forEach(url => {
-            // 确保URL是完整的
-            let imageUrl = url.trim()
-            // 如果是以//开头的,添加https:
-            if (imageUrl.startsWith('//')) {
-                imageUrl = 'https:' + imageUrl
-            }
-
-            // 对于第三方图片,尝试使用代理
-            const proxyUrl = getImageProxyUrl(imageUrl)
-            // 如果代理不可用,使用原URL并添加跨域属性
-            const finalUrl = proxyUrl !== imageUrl ? proxyUrl : imageUrl
-            const crossOriginAttr = proxyUrl === imageUrl ? 'crossorigin="anonymous" referrerpolicy="no-referrer"' : ''
-
-            // 将URL替换为img标签
-            const imgTag = `<img src="${finalUrl}" ${crossOriginAttr} alt="图片" style="max-width: 100%; height: auto; display: block; margin: 10px 0;" onerror="this.onerror=null; this.src='${imageUrl}'; this.style.border='1px solid #ddd'; this.alt='图片加载失败,点击查看原图'; this.style.cursor='pointer'; this.title='点击查看原图'; this.onclick='window.open(this.src)';" />`
-            formattedContent = formattedContent.replace(url, imgTag)
-        })
-    }
-
-    return formattedContent
-}
-
 getKnowledgeTreeList()
 getSubjectList()
 getList()

+ 608 - 0
back-ui/src/views/system/bWwwNews/index.vue

@@ -0,0 +1,608 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="类别" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择类别" clearable style="width: 160px">
+          <el-option
+            v-for="dict in news_type"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="标题" prop="title">
+        <el-input
+          v-model="queryParams.title"
+          placeholder="请输入标题"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+<!--      <el-form-item label="来源" prop="f">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.f"-->
+<!--          placeholder="请输入来源"-->
+<!--          clearable-->
+<!--          @keyup.enter="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+<!--      <el-form-item label="日期" prop="sendDate">-->
+<!--        <el-date-picker clearable-->
+<!--          v-model="queryParams.sendDate"-->
+<!--          type="date"-->
+<!--          value-format="YYYY-MM-DD"-->
+<!--          placeholder="请选择日期">-->
+<!--        </el-date-picker>-->
+<!--      </el-form-item>-->
+<!--      <el-form-item label="点击数" prop="clicked">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.clicked"-->
+<!--          placeholder="请输入点击数"-->
+<!--          clearable-->
+<!--          @keyup.enter="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+<!--      <el-form-item label="状态" prop="status">-->
+<!--        <el-select v-model="queryParams.status" placeholder="请选择状态" clearable>-->
+<!--          <el-option-->
+<!--            v-for="dict in bool_values"-->
+<!--            :key="dict.value"-->
+<!--            :label="dict.label"-->
+<!--            :value="dict.value"-->
+<!--          />-->
+<!--        </el-select>-->
+<!--      </el-form-item>-->
+<!--      <el-form-item label="关键词" prop="keywords">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.keywords"-->
+<!--          placeholder="请输入关键词"-->
+<!--          clearable-->
+<!--          @keyup.enter="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+      <el-form-item label="置顶显示" prop="isTop">
+        <el-select v-model="queryParams.isTop" placeholder="请选择置顶显示"  clearable style="width: 160px">
+          <el-option
+            v-for="dict in bool_values"
+            :key="dict.value"
+            :label="dict.label"
+            :value="dict.value"
+          />
+        </el-select>
+      </el-form-item>
+<!--      <el-form-item label="创建时间" prop="createTime">-->
+<!--        <el-date-picker clearable-->
+<!--          v-model="queryParams.createTime"-->
+<!--          type="date"-->
+<!--          value-format="YYYY-MM-DD"-->
+<!--          placeholder="请选择创建时间">-->
+<!--        </el-date-picker>-->
+<!--      </el-form-item>-->
+      <el-form-item label="省份" prop="location">
+        <el-input
+          v-model="queryParams.location"
+          placeholder="请输入省份"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+<!--      <el-form-item label="原id" prop="originId">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.originId"-->
+<!--          placeholder="请输入原id"-->
+<!--          clearable-->
+<!--          @keyup.enter="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+<!--      <el-form-item label="source" prop="source">-->
+<!--        <el-input-->
+<!--          v-model="queryParams.source"-->
+<!--          placeholder="请输入source"-->
+<!--          clearable-->
+<!--          @keyup.enter="handleQuery"-->
+<!--        />-->
+<!--      </el-form-item>-->
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          @click="handleAdd"
+          v-hasPermi="['system:bWwwNews:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="Edit"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:bWwwNews:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="Delete"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:bWwwNews:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="Download"
+          @click="handleExport"
+          v-hasPermi="['system:bWwwNews:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="bWwwNewsList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="id" align="center" prop="id" />
+      <el-table-column label="类别" align="center" prop="type">
+        <template #default="scope">
+          <dict-tag :options="news_type" :value="scope.row.type"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="标题" align="center" prop="title" />
+      <el-table-column label="内容(可点击)" align="center" prop="content" show-overflow-tooltip>
+        <template #default="scope">
+          <el-link type="primary" @click="handlePreviewContent(scope.row)" :underline="false">
+            <div class="table-cell-content" v-html="formatContentWithImages(scope.row.content)"></div>
+          </el-link>
+        </template>
+      </el-table-column>
+<!--      <el-table-column label="来源" align="center" prop="f" />-->
+      <el-table-column label="日期" align="center" prop="sendDate" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.sendDate, '{y}-{m}-{d}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="点击数" align="center" prop="clicked" />
+<!--      <el-table-column label="状态" align="center" prop="status">-->
+<!--        <template #default="scope">-->
+<!--          <dict-tag :options="bool_values" :value="scope.row.status"/>-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+<!--      <el-table-column label="关键词" align="center" prop="keywords" />-->
+<!--      <el-table-column label="描述" align="center" prop="description" />-->
+      <el-table-column label="置顶显示" align="center" prop="isTop">
+        <template #default="scope">
+          <dict-tag :options="bool_values" :value="scope.row.isTop"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="创建时间" align="center" prop="createTime" width="180">
+        <template #default="scope">
+          <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="省份" align="center" prop="location" />
+<!--      <el-table-column label="原id" align="center" prop="originId" />-->
+<!--      <el-table-column label="source" align="center" prop="source" />-->
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:bWwwNews:edit']">修改</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:bWwwNews:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total>0"
+      :total="total"
+      v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改资讯管理对话框 -->
+    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
+      <el-form ref="bWwwNewsRef" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="类别" prop="type">
+          <el-select v-model="form.type" placeholder="请选择类别">
+            <el-option
+              v-for="dict in news_type"
+              :key="dict.value"
+              :label="dict.label"
+              :value="dict.value"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="标题" prop="title">
+          <el-input v-model="form.title" placeholder="请输入标题" />
+        </el-form-item>
+        <el-form-item label="内容">
+          <editor v-model="form.content" :min-height="192" type="url"/>
+          <!-- 预览内容(只读模式,用于查看已保存的内容) -->
+<!--          <div v-if="form.content && form.id" class="readonly-content-preview" style="margin-top: 10px; padding: 10px; background-color: #f5f7fa; border-radius: 4px;">-->
+            <!-- <div style="font-size: 12px; color: #909399; margin-bottom: 5px;">内容预览:</div> -->
+<!--            <div class="readonly-content" v-html="formatContentWithImages(form.content)"></div>-->
+<!--          </div>-->
+        </el-form-item>
+<!--        <el-form-item label="来源" prop="f">-->
+<!--          <el-input v-model="form.f" placeholder="请输入来源" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="日期" prop="sendDate">
+          <el-date-picker clearable
+            v-model="form.sendDate"
+            type="date"
+            value-format="YYYY-MM-DD"
+            placeholder="请选择日期">
+          </el-date-picker>
+        </el-form-item>
+<!--        <el-form-item label="点击数" prop="clicked">-->
+<!--          <el-input v-model="form.clicked" placeholder="请输入点击数" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="状态" prop="status">-->
+<!--          <el-select v-model="form.status" placeholder="请选择状态">-->
+<!--            <el-option-->
+<!--              v-for="dict in bool_values"-->
+<!--              :key="dict.value"-->
+<!--              :label="dict.label"-->
+<!--              :value="parseInt(dict.value)"-->
+<!--            ></el-option>-->
+<!--          </el-select>-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="关键词" prop="keywords">-->
+<!--          <el-input v-model="form.keywords" placeholder="请输入关键词" />-->
+<!--        </el-form-item>-->
+        <el-form-item label="描述" prop="description">
+          <el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="置顶显示" prop="isTop">
+          <el-select v-model="form.isTop" placeholder="请选择置顶显示">
+            <el-option
+              v-for="dict in bool_values"
+              :key="dict.value"
+              :label="dict.label"
+              :value="parseInt(dict.value)"
+            ></el-option>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="省份" prop="location">
+          <el-input v-model="form.location" placeholder="请输入省份" />
+        </el-form-item>
+<!--        <el-form-item label="原id" prop="originId">-->
+<!--          <el-input v-model="form.originId" placeholder="请输入原id" />-->
+<!--        </el-form-item>-->
+<!--        <el-form-item label="source" prop="source">-->
+<!--          <el-input v-model="form.source" placeholder="请输入source" />-->
+<!--        </el-form-item>-->
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 内容预览弹窗 -->
+    <el-dialog v-model="previewOpen" title="内容预览" width="80%" append-to-body>
+      <div class="preview-content-wrapper">
+        <div class="preview-header" v-if="previewData.title">
+          <h3>{{ previewData.title }}</h3>
+          <div class="preview-meta" v-if="previewData.sendDate">
+            <span>发布时间:{{ parseTime(previewData.sendDate, '{y}-{m}-{d}') }}</span>
+          </div>
+        </div>
+        <div class="preview-content" v-html="formatContentWithImages(previewData.content)"></div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="previewOpen = false">关 闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="BWwwNews">
+import { listBWwwNews, getBWwwNews, delBWwwNews, addBWwwNews, updateBWwwNews } from "@/api/system/bWwwNews"
+import { getImageProxyUrl, formatContentWithImages } from '@/utils/imageHelper'
+
+const { proxy } = getCurrentInstance()
+const { bool_values, news_type } = proxy.useDict('bool_values', 'news_type')
+
+const bWwwNewsList = ref([])
+const open = ref(false)
+const loading = ref(true)
+const showSearch = ref(true)
+const ids = ref([])
+const single = ref(true)
+const multiple = ref(true)
+const total = ref(0)
+const title = ref("")
+const previewOpen = ref(false)
+const previewData = ref({
+  title: '',
+  content: '',
+  sendDate: null
+})
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    type: null,
+    title: null,
+    content: null,
+    f: null,
+    sendDate: null,
+    clicked: null,
+    status: null,
+    keywords: null,
+    description: null,
+    isTop: null,
+    createTime: null,
+    location: null,
+    originId: null,
+    source: null
+  },
+  rules: {
+    clicked: [
+      { required: true, message: "点击数不能为空", trigger: "blur" }
+    ],
+    isTop: [
+      { required: true, message: "置顶显示不能为空", trigger: "change" }
+    ],
+    originId: [
+      { required: true, message: "原id不能为空", trigger: "blur" }
+    ],
+  }
+})
+
+const { queryParams, form, rules } = toRefs(data)
+
+/** 查询资讯管理列表 */
+function getList() {
+  loading.value = true
+  listBWwwNews(queryParams.value).then(response => {
+    bWwwNewsList.value = response.rows
+    total.value = response.total
+    loading.value = false
+  })
+}
+
+// 取消按钮
+function cancel() {
+  open.value = false
+  reset()
+}
+
+// 表单重置
+function reset() {
+  form.value = {
+    id: null,
+    type: null,
+    title: null,
+    content: null,
+    f: null,
+    sendDate: null,
+    clicked: null,
+    status: null,
+    keywords: null,
+    description: null,
+    isTop: null,
+    createTime: null,
+    location: null,
+    originId: null,
+    source: null
+  }
+  proxy.resetForm("bWwwNewsRef")
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  handleQuery()
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.id)
+  single.value = selection.length != 1
+  multiple.value = !selection.length
+}
+
+/** 新增按钮操作 */
+function handleAdd() {
+  reset()
+  open.value = true
+  title.value = "添加资讯管理"
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  reset()
+  const _id = row.id || ids.value
+  getBWwwNews(_id).then(response => {
+    form.value = response.data
+    open.value = true
+    title.value = "修改资讯管理"
+  })
+}
+
+/** 提交按钮 */
+function submitForm() {
+  proxy.$refs["bWwwNewsRef"].validate(valid => {
+    if (valid) {
+      if (form.value.id != null) {
+        updateBWwwNews(form.value).then(response => {
+          proxy.$modal.msgSuccess("修改成功")
+          open.value = false
+          getList()
+        })
+      } else {
+        addBWwwNews(form.value).then(response => {
+          proxy.$modal.msgSuccess("新增成功")
+          open.value = false
+          getList()
+        })
+      }
+    }
+  })
+}
+
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _ids = row.id || ids.value
+  proxy.$modal.confirm('是否确认删除资讯管理编号为"' + _ids + '"的数据项?').then(function() {
+    return delBWwwNews(_ids)
+  }).then(() => {
+    getList()
+    proxy.$modal.msgSuccess("删除成功")
+  }).catch(() => {})
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('system/bWwwNews/export', {
+    ...queryParams.value
+  }, `bWwwNews_${new Date().getTime()}.xlsx`)
+}
+
+/** 预览内容 */
+function handlePreviewContent(row) {
+  previewData.value = {
+    title: row.title || '',
+    content: row.content || '',
+    sendDate: row.sendDate || null
+  }
+  previewOpen.value = true
+}
+
+getList()
+</script>
+
+<style scoped>
+/* 表格单元格内容样式 */
+.table-cell-content {
+    word-break: break-word;
+    line-height: 1.6;
+    max-height: 100px;
+    overflow: hidden;
+}
+
+.table-cell-content :deep(img) {
+    max-width: 100%;
+    height: auto;
+    display: block;
+    margin: 5px 0;
+    border-radius: 4px;
+    object-fit: contain;
+}
+
+.table-cell-content :deep(img[src=""]) {
+    display: none;
+}
+
+.table-cell-content :deep(img:not([src])) {
+    display: none;
+}
+
+/* 只读内容预览样式 */
+.readonly-content {
+    color: #606266;
+    word-break: break-word;
+    white-space: pre-wrap;
+    line-height: 1.6;
+    min-height: 20px;
+}
+
+.readonly-content :deep(img) {
+    max-width: 100%;
+    height: auto;
+    display: block;
+    margin: 10px 0;
+    border-radius: 4px;
+    object-fit: contain;
+}
+
+.readonly-content :deep(img[src=""]) {
+    display: none;
+}
+
+.readonly-content :deep(img:not([src])) {
+    display: none;
+}
+
+/* 预览弹窗样式 */
+.preview-content-wrapper {
+    max-height: 70vh;
+    overflow-y: auto;
+}
+
+.preview-header {
+    margin-bottom: 20px;
+    padding-bottom: 15px;
+    border-bottom: 1px solid #e5e5e5;
+}
+
+.preview-header h3 {
+    margin: 0 0 10px 0;
+    font-size: 18px;
+    font-weight: 600;
+    color: #303133;
+}
+
+.preview-meta {
+    font-size: 14px;
+    color: #909399;
+}
+
+.preview-content {
+    color: #606266;
+    word-break: break-word;
+    white-space: pre-wrap;
+    line-height: 1.8;
+    font-size: 14px;
+}
+
+.preview-content :deep(img) {
+    max-width: 100%;
+    height: auto;
+    display: block;
+    margin: 15px 0;
+    border-radius: 4px;
+    object-fit: contain;
+}
+
+.preview-content :deep(img[src=""]) {
+    display: none;
+}
+
+.preview-content :deep(img:not([src])) {
+    display: none;
+}
+
+.preview-content :deep(p) {
+    margin: 10px 0;
+}
+
+.preview-content :deep(div) {
+    margin: 10px 0;
+}
+</style>

+ 511 - 0
back-ui/src/views/system/bWwwNewsRef/index.vue

@@ -0,0 +1,511 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+      <el-form-item label="类别" prop="type">
+        <el-input
+          v-model="queryParams.type"
+          placeholder="请输入类别"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <!-- <el-form-item label="子类别" prop="subType">
+        <el-input
+          v-model="queryParams.subType"
+          placeholder="请输入子类别"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item label="引用资讯ID" prop="refIds">
+        <el-input
+          v-model="queryParams.refIds"
+          placeholder="请输入引用资讯ID"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item> -->
+      <el-form-item label="地区" prop="location">
+        <el-input
+          v-model="queryParams.location"
+          placeholder="请输入地区"
+          clearable
+          @keyup.enter="handleQuery"
+        />
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
+        <el-button icon="Refresh" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button
+          type="primary"
+          plain
+          icon="Plus"
+          @click="handleAdd"
+          v-hasPermi="['system:bWwwNewsRef:add']"
+        >新增</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="success"
+          plain
+          icon="Edit"
+          :disabled="single"
+          @click="handleUpdate"
+          v-hasPermi="['system:bWwwNewsRef:edit']"
+        >修改</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="danger"
+          plain
+          icon="Delete"
+          :disabled="multiple"
+          @click="handleDelete"
+          v-hasPermi="['system:bWwwNewsRef:remove']"
+        >删除</el-button>
+      </el-col>
+      <el-col :span="1.5">
+        <el-button
+          type="warning"
+          plain
+          icon="Download"
+          @click="handleExport"
+          v-hasPermi="['system:bWwwNewsRef:export']"
+        >导出</el-button>
+      </el-col>
+      <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table v-loading="loading" :data="bWwwNewsRefList" @selection-change="handleSelectionChange">
+      <el-table-column type="selection" width="55" align="center" />
+      <el-table-column label="ID" align="center" prop="id" />
+      <el-table-column label="类别" align="center" prop="type" />
+      <el-table-column label="子类别" align="center" prop="subType" />
+      <el-table-column label="内容" align="center" prop="description" />
+      <el-table-column label="引用资讯ID" align="center" prop="refIds">
+        <template #default="scope">
+          <el-tooltip
+            :content="getRefNewsTooltip(scope.row)"
+            placement="top"
+            :disabled="!scope.row.refIds"
+            :show-after="200"
+          >
+            <el-link type="primary" @click="handlePreviewRefNews(scope.row)" :underline="false">
+              {{ scope.row.refIds }}
+            </el-link>
+          </el-tooltip>
+        </template>
+      </el-table-column>
+      <el-table-column label="地区" align="center" prop="location" />
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
+        <template #default="scope">
+          <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['system:bWwwNewsRef:edit']">修改</el-button>
+          <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['system:bWwwNewsRef:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+    
+    <pagination
+      v-show="total>0"
+      :total="total"
+      v-model:page="queryParams.pageNum"
+      v-model:limit="queryParams.pageSize"
+      @pagination="getList"
+    />
+
+    <!-- 添加或修改通关指南对话框 -->
+    <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+      <el-form ref="bWwwNewsRefRef" :model="form" :rules="rules" label-width="80px">
+        <el-form-item label="类别" prop="type">
+          <el-input v-model="form.type" placeholder="请输入类别" />
+        </el-form-item>
+        <el-form-item label="子类别" prop="subType">
+          <el-input v-model="form.subType" placeholder="请输入子类别" />
+        </el-form-item>
+        <el-form-item label="内容" prop="description">
+          <el-input v-model="form.description" type="textarea" placeholder="请输入内容" />
+        </el-form-item>
+        <el-form-item label="引用资讯ID" prop="refIds">
+          <el-input v-model="form.refIds" placeholder="请输入引用资讯ID" />
+        </el-form-item>
+        <el-form-item label="地区" prop="location">
+          <el-input v-model="form.location" placeholder="请输入地区" />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitForm">确 定</el-button>
+          <el-button @click="cancel">取 消</el-button>
+        </div>
+      </template>
+    </el-dialog>
+
+    <!-- 内容预览弹窗 -->
+    <el-dialog v-model="previewOpen" title="引用资讯内容预览" width="80%" append-to-body>
+      <div class="preview-content-wrapper">
+        <div v-if="previewNewsList.length === 0" class="preview-loading">
+          <el-icon class="is-loading"><Loading /></el-icon>
+          <span>加载中...</span>
+        </div>
+        <div v-else>
+          <div v-for="(news, index) in previewNewsList" :key="news.id || index" class="preview-news-item">
+            <div class="preview-header" v-if="news.title">
+              <h3>{{ news.title }}</h3>
+              <div class="preview-meta" v-if="news.sendDate">
+                <span>发布时间:{{ parseTime(news.sendDate, '{y}-{m}-{d}') }}</span>
+              </div>
+            </div>
+            <div class="preview-content" v-html="formatContentWithImages(news.content)"></div>
+            <el-divider v-if="index < previewNewsList.length - 1" />
+          </div>
+        </div>
+      </div>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button @click="previewOpen = false">关 闭</el-button>
+        </div>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup name="BWwwNewsRef">
+import { listBWwwNewsRef, getBWwwNewsRef, delBWwwNewsRef, addBWwwNewsRef, updateBWwwNewsRef } from "@/api/system/bWwwNewsRef"
+import { getBWwwNews } from "@/api/system/bWwwNews"
+import { formatContentWithImages } from '@/utils/imageHelper'
+import { Loading } from '@element-plus/icons-vue'
+
+const { proxy } = getCurrentInstance()
+const { bool_values, news_type } = proxy.useDict('bool_values', 'news_type')
+
+const bWwwNewsRefList = ref([])
+const open = ref(false)
+const loading = ref(true)
+const showSearch = ref(true)
+const ids = ref([])
+const single = ref(true)
+const multiple = ref(true)
+const total = ref(0)
+const title = ref("")
+const previewOpen = ref(false)
+const previewNewsList = ref([])
+// 缓存资讯标题,避免重复请求
+const newsTitleCache = reactive(new Map())
+// 正在加载的ID集合,避免重复请求
+const loadingIds = ref(new Set())
+
+const data = reactive({
+  form: {},
+  queryParams: {
+    pageNum: 1,
+    pageSize: 10,
+    type: null,
+    subType: null,
+    description: null,
+    refIds: null,
+    location: null
+  },
+  rules: {
+  }
+})
+
+const { queryParams, form, rules } = toRefs(data)
+
+/** 查询通关指南列表 */
+function getList() {
+  loading.value = true
+  listBWwwNewsRef(queryParams.value).then(response => {
+    bWwwNewsRefList.value = response.rows
+    total.value = response.total
+    loading.value = false
+  })
+}
+
+// 取消按钮
+function cancel() {
+  open.value = false
+  reset()
+}
+
+// 表单重置
+function reset() {
+  form.value = {
+    id: null,
+    type: null,
+    subType: null,
+    description: null,
+    refIds: null,
+    location: null
+  }
+  proxy.resetForm("bWwwNewsRefRef")
+}
+
+/** 搜索按钮操作 */
+function handleQuery() {
+  queryParams.value.pageNum = 1
+  getList()
+}
+
+/** 重置按钮操作 */
+function resetQuery() {
+  proxy.resetForm("queryRef")
+  handleQuery()
+}
+
+// 多选框选中数据
+function handleSelectionChange(selection) {
+  ids.value = selection.map(item => item.id)
+  single.value = selection.length != 1
+  multiple.value = !selection.length
+}
+
+/** 新增按钮操作 */
+function handleAdd() {
+  reset()
+  open.value = true
+  title.value = "添加通关指南"
+}
+
+/** 修改按钮操作 */
+function handleUpdate(row) {
+  reset()
+  const _id = row.id || ids.value
+  getBWwwNewsRef(_id).then(response => {
+    form.value = response.data
+    open.value = true
+    title.value = "修改通关指南"
+  })
+}
+
+/** 提交按钮 */
+function submitForm() {
+  proxy.$refs["bWwwNewsRefRef"].validate(valid => {
+    if (valid) {
+      if (form.value.id != null) {
+        updateBWwwNewsRef(form.value).then(response => {
+          proxy.$modal.msgSuccess("修改成功")
+          open.value = false
+          getList()
+        })
+      } else {
+        addBWwwNewsRef(form.value).then(response => {
+          proxy.$modal.msgSuccess("新增成功")
+          open.value = false
+          getList()
+        })
+      }
+    }
+  })
+}
+
+/** 删除按钮操作 */
+function handleDelete(row) {
+  const _ids = row.id || ids.value
+  proxy.$modal.confirm('是否确认删除通关指南编号为"' + _ids + '"的数据项?').then(function() {
+    return delBWwwNewsRef(_ids)
+  }).then(() => {
+    getList()
+    proxy.$modal.msgSuccess("删除成功")
+  }).catch(() => {})
+}
+
+/** 导出按钮操作 */
+function handleExport() {
+  proxy.download('system/bWwwNewsRef/export', {
+    ...queryParams.value
+  }, `bWwwNewsRef_${new Date().getTime()}.xlsx`)
+}
+
+/** 获取引用资讯的提示内容 */
+function getRefNewsTooltip(row) {
+  if (!row.refIds) {
+    return '无引用资讯'
+  }
+  
+  // 解析 refIds
+  const ids = String(row.refIds).split(',').map(id => id.trim()).filter(id => id)
+  
+  if (ids.length === 0) {
+    return '引用资讯ID格式错误'
+  }
+  
+  // 尝试从缓存中获取标题
+  const titles = ids.map(id => {
+    const cached = newsTitleCache.get(id)
+    return cached ? cached : `资讯ID: ${id}`
+  })
+  
+  // 如果缓存中有部分标题缺失,异步加载缺失的标题
+  const missingIds = ids.filter(id => !newsTitleCache.has(id) && !loadingIds.value.has(id))
+  if (missingIds.length > 0) {
+    // 标记为正在加载
+    missingIds.forEach(id => loadingIds.value.add(id))
+    // 异步加载标题(不阻塞显示)
+    loadNewsTitles(missingIds)
+  }
+  
+  const content = titles.join('\n')
+  return content + '\n\n点击查看详情'
+}
+
+/** 异步加载资讯标题 */
+async function loadNewsTitles(ids) {
+  try {
+    const promises = ids.map(id => {
+      return getBWwwNews(id)
+        .then(res => {
+          if (res.data && res.data.title) {
+            newsTitleCache.set(id, res.data.title)
+          }
+        })
+        .catch(() => {
+          // 加载失败,不缓存
+        })
+        .finally(() => {
+          // 移除加载标记
+          loadingIds.value.delete(id)
+        })
+    })
+    
+    await Promise.all(promises)
+  } catch (error) {
+    // 清除所有加载标记
+    ids.forEach(id => loadingIds.value.delete(id))
+  }
+}
+
+/** 预览引用资讯内容 */
+async function handlePreviewRefNews(row) {
+  if (!row.refIds) {
+    proxy.$modal.msgWarning('引用资讯ID为空')
+    return
+  }
+  
+  // 解析 refIds(可能是逗号分隔的ID列表)
+  const ids = String(row.refIds).split(',').map(id => id.trim()).filter(id => id)
+  
+  if (ids.length === 0) {
+    proxy.$modal.msgWarning('引用资讯ID格式错误')
+    return
+  }
+  
+  // 打开预览弹窗
+  previewOpen.value = true
+  previewNewsList.value = []
+  
+  // 批量获取资讯内容
+  try {
+    const promises = ids.map(id => {
+      return getBWwwNews(id).then(res => {
+        // 更新标题缓存
+        if (res.data && res.data.title) {
+          newsTitleCache.set(id, res.data.title)
+        }
+        return res.data
+      }).catch(err => {
+        console.error(`获取资讯 ${id} 失败:`, err)
+        return {
+          id: id,
+          title: `资讯ID: ${id} (获取失败)`,
+          content: '获取内容失败,请检查资讯ID是否正确',
+          sendDate: null
+        }
+      })
+    })
+    
+    const newsList = await Promise.all(promises)
+    previewNewsList.value = newsList
+  } catch (error) {
+    console.error('批量获取资讯失败:', error)
+    proxy.$modal.msgError('获取资讯内容失败')
+    previewOpen.value = false
+  }
+}
+
+getList()
+</script>
+
+<style scoped>
+/* 预览弹窗样式 */
+.preview-content-wrapper {
+    max-height: 70vh;
+    overflow-y: auto;
+}
+
+.preview-loading {
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    padding: 40px;
+    color: #909399;
+}
+
+.preview-loading .el-icon {
+    margin-right: 8px;
+    font-size: 20px;
+}
+
+.preview-news-item {
+    margin-bottom: 30px;
+}
+
+.preview-news-item:last-child {
+    margin-bottom: 0;
+}
+
+.preview-header {
+    margin-bottom: 20px;
+    padding-bottom: 15px;
+    border-bottom: 1px solid #e5e5e5;
+}
+
+.preview-header h3 {
+    margin: 0 0 10px 0;
+    font-size: 18px;
+    font-weight: 600;
+    color: #303133;
+}
+
+.preview-meta {
+    font-size: 14px;
+    color: #909399;
+}
+
+.preview-content {
+    color: #606266;
+    word-break: break-word;
+    white-space: pre-wrap;
+    line-height: 1.8;
+    font-size: 14px;
+}
+
+.preview-content :deep(img) {
+    max-width: 100%;
+    height: auto;
+    display: block;
+    margin: 15px 0;
+    border-radius: 4px;
+    object-fit: contain;
+}
+
+.preview-content :deep(img[src=""]) {
+    display: none;
+}
+
+.preview-content :deep(img:not([src])) {
+    display: none;
+}
+
+.preview-content :deep(p) {
+    margin: 10px 0;
+}
+
+.preview-content :deep(div) {
+    margin: 10px 0;
+}
+</style>

+ 105 - 0
ie-admin/src/main/java/com/ruoyi/web/controller/dz/BWwwNewsController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.web.controller.dz;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.syzy.domain.BWwwNews;
+import com.ruoyi.syzy.service.IBWwwNewsService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 资讯管理Controller
+ *
+ * @author ie
+ * @date 2026-01-20
+ */
+@RestController
+@RequestMapping("/system/bWwwNews")
+public class BWwwNewsController extends BaseController
+{
+    @Autowired
+    private IBWwwNewsService bWwwNewsService;
+
+    /**
+     * 查询资讯管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNews:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BWwwNews bWwwNews)
+    {
+        startPage();
+        List<BWwwNews> list = bWwwNewsService.selectBWwwNewsList(bWwwNews);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出资讯管理列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNews:export')")
+    @Log(title = "资讯管理", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BWwwNews bWwwNews)
+    {
+        List<BWwwNews> list = bWwwNewsService.selectBWwwNewsList(bWwwNews);
+        ExcelUtil<BWwwNews> util = new ExcelUtil<BWwwNews>(BWwwNews.class);
+        util.exportExcel(response, list, "资讯管理数据");
+    }
+
+    /**
+     * 获取资讯管理详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNews:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bWwwNewsService.selectBWwwNewsById(id));
+    }
+
+    /**
+     * 新增资讯管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNews:add')")
+    @Log(title = "资讯管理", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BWwwNews bWwwNews)
+    {
+        return toAjax(bWwwNewsService.insertBWwwNews(bWwwNews));
+    }
+
+    /**
+     * 修改资讯管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNews:edit')")
+    @Log(title = "资讯管理", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BWwwNews bWwwNews)
+    {
+        return toAjax(bWwwNewsService.updateBWwwNews(bWwwNews));
+    }
+
+    /**
+     * 删除资讯管理
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNews:remove')")
+    @Log(title = "资讯管理", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bWwwNewsService.deleteBWwwNewsByIds(ids));
+    }
+}

+ 105 - 0
ie-admin/src/main/java/com/ruoyi/web/controller/dz/BWwwNewsRefController.java

@@ -0,0 +1,105 @@
+package com.ruoyi.web.controller.dz;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.syzy.domain.BWwwNewsRef;
+import com.ruoyi.syzy.service.IBWwwNewsRefService;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.common.core.page.TableDataInfo;
+
+/**
+ * 通关指南Controller
+ *
+ * @author ie
+ * @date 2026-01-20
+ */
+@RestController
+@RequestMapping("/system/bWwwNewsRef")
+public class BWwwNewsRefController extends BaseController
+{
+    @Autowired
+    private IBWwwNewsRefService bWwwNewsRefService;
+
+    /**
+     * 查询通关指南列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNewsRef:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(BWwwNewsRef bWwwNewsRef)
+    {
+        startPage();
+        List<BWwwNewsRef> list = bWwwNewsRefService.selectBWwwNewsRefList(bWwwNewsRef);
+        return getDataTable(list);
+    }
+
+    /**
+     * 导出通关指南列表
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNewsRef:export')")
+    @Log(title = "通关指南", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, BWwwNewsRef bWwwNewsRef)
+    {
+        List<BWwwNewsRef> list = bWwwNewsRefService.selectBWwwNewsRefList(bWwwNewsRef);
+        ExcelUtil<BWwwNewsRef> util = new ExcelUtil<BWwwNewsRef>(BWwwNewsRef.class);
+        util.exportExcel(response, list, "通关指南数据");
+    }
+
+    /**
+     * 获取通关指南详细信息
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNewsRef:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id)
+    {
+        return success(bWwwNewsRefService.selectBWwwNewsRefById(id));
+    }
+
+    /**
+     * 新增通关指南
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNewsRef:add')")
+    @Log(title = "通关指南", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody BWwwNewsRef bWwwNewsRef)
+    {
+        return toAjax(bWwwNewsRefService.insertBWwwNewsRef(bWwwNewsRef));
+    }
+
+    /**
+     * 修改通关指南
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNewsRef:edit')")
+    @Log(title = "通关指南", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody BWwwNewsRef bWwwNewsRef)
+    {
+        return toAjax(bWwwNewsRefService.updateBWwwNewsRef(bWwwNewsRef));
+    }
+
+    /**
+     * 删除通关指南
+     */
+    @PreAuthorize("@ss.hasPermi('system:bWwwNewsRef:remove')")
+    @Log(title = "通关指南", businessType = BusinessType.DELETE)
+	@DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids)
+    {
+        return toAjax(bWwwNewsRefService.deleteBWwwNewsRefByIds(ids));
+    }
+}

+ 9 - 10
ie-admin/src/main/java/com/ruoyi/web/controller/front/FrontUniversitiesController.java

@@ -60,15 +60,14 @@ public class FrontUniversitiesController extends BaseController {
     private IBBusiWishUniversitySubmitRecruitPlanService wishUniversitySubmitRecruitPlanService;
     @Autowired
     private CommService commService;
-    private final Map<String, String> tierDescMap = Maps.newHashMap();
-
-    public FrontUniversitiesController() {
-        tierDescMap.put("1", "文化分280分以上");
-        tierDescMap.put("2", "文化分270分以上");
-        tierDescMap.put("3", "文化分260分以上");
-        tierDescMap.put("4", "文化分250分以上");
-        tierDescMap.put("5", "文化分240分以上");
-        tierDescMap.put("6", "文化分230分以上");
+
+    /**
+     * 获取梯次描述
+     * @param tierValue 梯次值
+     * @return 梯次描述
+     */
+    private String getTierDesc(String tierValue) {
+        return dictTypeService.getDictDataByType("tier_desc", tierValue);
     }
 
     @GetMapping("filters")
@@ -207,7 +206,7 @@ public class FrontUniversitiesController extends BaseController {
             JSONObject tierUniversities = new JSONObject();
             tierUniversities.put("typeName", dd.getDictLabel());
             tierUniversities.put("typeValue", dd.getDictValue());
-            tierUniversities.put("desc", tierDescMap.get(dd.getDictValue()));
+            tierUniversities.put("desc", getTierDesc(dd.getDictValue()));
             tierUniversities.put("list", uList.size() > 10 ? uList.subList(0, 10) : uList);
             tierList.add(tierUniversities);
         }