feat(news): 支持新闻中心多站点隔离功能
新增站点编码配置,支持新闻分类与文章按站点隔离。主要变更包括: - 数据库表增加 site_code 字段及索引 - 后台管理界面支持按站点筛选 - 前台接口支持通过查询参数或请求头指定站点 - 新增站点配置与解析逻辑
This commit is contained in:
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
4
client/env.d.ts
vendored
4
client/env.d.ts
vendored
@@ -1,5 +1,9 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_PORTAL_SITE_CODE?: string
|
||||||
|
}
|
||||||
|
|
||||||
declare module '*.vue' {
|
declare module '*.vue' {
|
||||||
import type { DefineComponent } from 'vue'
|
import type { DefineComponent } from 'vue'
|
||||||
const component: DefineComponent<{}, {}, any>
|
const component: DefineComponent<{}, {}, any>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import request from '@/utils/request'
|
import request from '@/utils/request'
|
||||||
|
import { portalSiteQueryParams } from '@/config/portalSite'
|
||||||
|
|
||||||
export const portalApi = {
|
export const portalApi = {
|
||||||
getCompanyInfo: () => request.get('/portal/company'),
|
getCompanyInfo: () => request.get('/portal/company'),
|
||||||
@@ -17,9 +18,12 @@ export const portalApi = {
|
|||||||
getCaseCategories: () => request.get('/portal/case/category'),
|
getCaseCategories: () => request.get('/portal/case/category'),
|
||||||
getCases: (params?: any) => request.get('/portal/case', { params }),
|
getCases: (params?: any) => request.get('/portal/case', { params }),
|
||||||
getCaseById: (id: number) => request.get(`/portal/case/${id}`),
|
getCaseById: (id: number) => request.get(`/portal/case/${id}`),
|
||||||
getNewsCategories: () => request.get('/portal/news/category'),
|
getNewsCategories: () =>
|
||||||
getNewsList: (params?: any) => request.get('/portal/news', { params }),
|
request.get('/portal/news/category', { params: { ...portalSiteQueryParams() } }),
|
||||||
getNewsById: (id: number) => request.get(`/portal/news/${id}`),
|
getNewsList: (params?: any) =>
|
||||||
|
request.get('/portal/news', { params: { ...portalSiteQueryParams(), ...params } }),
|
||||||
|
getNewsById: (id: number) =>
|
||||||
|
request.get(`/portal/news/${id}`, { params: { ...portalSiteQueryParams() } }),
|
||||||
}
|
}
|
||||||
|
|
||||||
export const adminApi = {
|
export const adminApi = {
|
||||||
@@ -85,11 +89,12 @@ export const adminApi = {
|
|||||||
addCaseCategory: (data: any) => request.post('/admin/case/category', data),
|
addCaseCategory: (data: any) => request.post('/admin/case/category', data),
|
||||||
deleteCaseCategory: (id: number) => request.delete(`/admin/case/category/${id}`),
|
deleteCaseCategory: (id: number) => request.delete(`/admin/case/category/${id}`),
|
||||||
|
|
||||||
getNewsList: (params?: any) => request.get('/admin/news', { params }),
|
getNewsList: (params?: any) => request.get('/admin/news', { params: { ...params } }),
|
||||||
addNews: (data: any) => request.post('/admin/news', data),
|
addNews: (data: any) => request.post('/admin/news', data),
|
||||||
updateNews: (data: any) => request.put('/admin/news', data),
|
updateNews: (data: any) => request.put('/admin/news', data),
|
||||||
deleteNews: (id: number) => request.delete(`/admin/news/${id}`),
|
deleteNews: (id: number) => request.delete(`/admin/news/${id}`),
|
||||||
getNewsCategories: () => request.get('/admin/news/category'),
|
getNewsCategories: (params?: any) =>
|
||||||
|
request.get('/admin/news/category', { params: { ...params } }),
|
||||||
addNewsCategory: (data: any) => request.post('/admin/news/category', data),
|
addNewsCategory: (data: any) => request.post('/admin/news/category', data),
|
||||||
deleteNewsCategory: (id: number) => request.delete(`/admin/news/category/${id}`),
|
deleteNewsCategory: (id: number) => request.delete(`/admin/news/category/${id}`),
|
||||||
|
|
||||||
|
|||||||
8
client/src/config/portalSite.ts
Normal file
8
client/src/config/portalSite.ts
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/** 前台新闻等接口按站点隔离;与后端 app.portal.allowed-site-codes 一致。不设则走后端默认 site-code。 */
|
||||||
|
export function portalSiteQueryParams(): Record<string, string> {
|
||||||
|
const code = import.meta.env.VITE_PORTAL_SITE_CODE as string | undefined
|
||||||
|
if (code && String(code).trim() !== '') {
|
||||||
|
return { siteCode: String(code).trim().toLowerCase() }
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
@@ -2,10 +2,19 @@
|
|||||||
<div class="admin-crud-page">
|
<div class="admin-crud-page">
|
||||||
<div class="page-header">
|
<div class="page-header">
|
||||||
<h2>新闻管理</h2>
|
<h2>新闻管理</h2>
|
||||||
<el-button type="primary" @click="openDialog()">新增新闻</el-button>
|
<div class="page-header-filters">
|
||||||
|
<span style="margin-right:8px">站点</span>
|
||||||
|
<el-select v-model="filterSiteCode" placeholder="全部站点" clearable style="width:180px" @change="loadList">
|
||||||
|
<el-option label="全部站点" value="" />
|
||||||
|
<el-option label="主站 wuhansaga" value="wuhansaga" />
|
||||||
|
<el-option label="第二站点 saga-secondary" value="saga-secondary" />
|
||||||
|
</el-select>
|
||||||
|
<el-button type="primary" style="margin-left:12px" @click="openDialog()">新增新闻</el-button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-table :data="list" border stripe v-loading="loading">
|
<el-table :data="list" border stripe v-loading="loading">
|
||||||
<el-table-column prop="newsId" label="ID" width="80" />
|
<el-table-column prop="newsId" label="ID" width="80" />
|
||||||
|
<el-table-column prop="siteCode" label="站点" width="130" />
|
||||||
<el-table-column label="封面" width="140">
|
<el-table-column label="封面" width="140">
|
||||||
<template #default="{ row }">
|
<template #default="{ row }">
|
||||||
<el-image v-if="row.coverImage" :src="uploadPublicUrl(row.coverImage)" style="width:100px;height:50px;" fit="cover" />
|
<el-image v-if="row.coverImage" :src="uploadPublicUrl(row.coverImage)" style="width:100px;height:50px;" fit="cover" />
|
||||||
@@ -31,7 +40,17 @@
|
|||||||
<el-form :model="form" label-width="120px">
|
<el-form :model="form" label-width="120px">
|
||||||
<el-form-item label="标题(中)"><el-input v-model="form.titleZh" /></el-form-item>
|
<el-form-item label="标题(中)"><el-input v-model="form.titleZh" /></el-form-item>
|
||||||
<el-form-item label="标题(英)"><el-input v-model="form.titleEn" /></el-form-item>
|
<el-form-item label="标题(英)"><el-input v-model="form.titleEn" /></el-form-item>
|
||||||
<el-form-item label="分类ID"><el-input-number v-model="form.categoryId" :min="1" /></el-form-item>
|
<el-form-item label="站点">
|
||||||
|
<el-select v-model="form.siteCode" placeholder="请选择" style="width:100%" @change="onFormSiteChange">
|
||||||
|
<el-option label="主站 wuhansaga" value="wuhansaga" />
|
||||||
|
<el-option label="第二站点 saga-secondary" value="saga-secondary" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="分类">
|
||||||
|
<el-select v-model="form.categoryId" placeholder="请选择分类" style="width:100%">
|
||||||
|
<el-option v-for="cat in categoryOptions" :key="cat.newsCategoryId" :label="cat.nameZh" :value="cat.newsCategoryId" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
<el-form-item label="摘要(中)"><el-input v-model="form.excerptZh" type="textarea" :rows="2" /></el-form-item>
|
<el-form-item label="摘要(中)"><el-input v-model="form.excerptZh" type="textarea" :rows="2" /></el-form-item>
|
||||||
<el-form-item label="摘要(英)"><el-input v-model="form.excerptEn" type="textarea" :rows="2" /></el-form-item>
|
<el-form-item label="摘要(英)"><el-input v-model="form.excerptEn" type="textarea" :rows="2" /></el-form-item>
|
||||||
<el-form-item label="内容(中)"><el-input v-model="form.contentZh" type="textarea" :rows="6" /></el-form-item>
|
<el-form-item label="内容(中)"><el-input v-model="form.contentZh" type="textarea" :rows="6" /></el-form-item>
|
||||||
@@ -59,14 +78,37 @@ import { uploadPublicUrl } from '@/utils/uploadUrl'
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const saving = ref(false)
|
const saving = ref(false)
|
||||||
const list = ref<any[]>([])
|
const list = ref<any[]>([])
|
||||||
|
const categoryOptions = ref<any[]>([])
|
||||||
|
const filterSiteCode = ref('')
|
||||||
const dialogVisible = ref(false)
|
const dialogVisible = ref(false)
|
||||||
const editingId = ref<number | null>(null)
|
const editingId = ref<number | null>(null)
|
||||||
const form = ref<any>({})
|
const form = ref<any>({})
|
||||||
|
|
||||||
|
async function loadCategoriesForForm() {
|
||||||
|
const site = form.value.siteCode
|
||||||
|
if (!site) {
|
||||||
|
categoryOptions.value = []
|
||||||
|
return
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await adminApi.getNewsCategories({ siteCode: site })
|
||||||
|
categoryOptions.value = res.data ?? []
|
||||||
|
} catch {
|
||||||
|
categoryOptions.value = []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFormSiteChange() {
|
||||||
|
form.value.categoryId = undefined
|
||||||
|
loadCategoriesForForm()
|
||||||
|
}
|
||||||
|
|
||||||
async function loadList() {
|
async function loadList() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await adminApi.getNewsList()
|
const params: Record<string, string> = {}
|
||||||
|
if (filterSiteCode.value) params.siteCode = filterSiteCode.value
|
||||||
|
const res = await adminApi.getNewsList(params)
|
||||||
list.value = res.data ?? []
|
list.value = res.data ?? []
|
||||||
} catch {
|
} catch {
|
||||||
list.value = []
|
list.value = []
|
||||||
@@ -76,9 +118,16 @@ async function loadList() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function openDialog(row?: any) {
|
function openDialog(row?: any) {
|
||||||
if (row) { editingId.value = row.newsId; form.value = { ...row } }
|
if (row) {
|
||||||
else { editingId.value = null; form.value = { sortOrder: 0, isPublished: 0, isFeatured: 0, categoryId: 1 } }
|
editingId.value = row.newsId
|
||||||
|
form.value = { ...row }
|
||||||
|
} else {
|
||||||
|
editingId.value = null
|
||||||
|
const defaultSite = filterSiteCode.value || 'wuhansaga'
|
||||||
|
form.value = { sortOrder: 0, isPublished: 0, isFeatured: 0, siteCode: defaultSite, categoryId: undefined }
|
||||||
|
}
|
||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
|
loadCategoriesForForm()
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleSave() {
|
async function handleSave() {
|
||||||
@@ -100,5 +149,5 @@ onMounted(loadList)
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="less">
|
<style scoped lang="less">
|
||||||
.admin-crud-page { .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; h2 { font-size: 20px; color: @gray-800; } } }
|
.admin-crud-page { .page-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; flex-wrap: wrap; gap: 12px; h2 { font-size: 20px; color: @gray-800; } .page-header-filters { display: flex; align-items: center; flex-wrap: wrap; } } }
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
37
database/sql/migration_news_multisite.sql
Normal file
37
database/sql/migration_news_multisite.sql
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
-- =============================================================================
|
||||||
|
-- 新闻中心多站点:为 f_news / f_news_category 增加 site_code
|
||||||
|
-- 执行前请备份数据库。可与 schema 增量部署,适合在 Gitea 发版后由运维一次性执行。
|
||||||
|
-- 固定站点编码示例:wuhansaga(主站)、saga-secondary(第二站点,可按品牌改名)
|
||||||
|
-- =============================================================================
|
||||||
|
|
||||||
|
SET NAMES utf8mb4 COLLATE utf8mb4_unicode_ci;
|
||||||
|
|
||||||
|
-- 新闻分类:站点维度的栏目互相独立(不同站点可有各自一套分类及排序)
|
||||||
|
ALTER TABLE f_news_category
|
||||||
|
ADD COLUMN site_code VARCHAR(32) NOT NULL DEFAULT 'wuhansaga'
|
||||||
|
COMMENT '站点编码:小写英文短码,如 wuhansaga、saga-secondary,扩展新站时仅增编码不改结构'
|
||||||
|
AFTER category_id;
|
||||||
|
|
||||||
|
ALTER TABLE f_news_category
|
||||||
|
ADD KEY idx_f_news_category_site (site_code, del_flag, is_published, sort_order);
|
||||||
|
|
||||||
|
-- 新闻正文:与分类 site_code 逻辑上一致;保存时业务侧校验 category 与 news 同属一站
|
||||||
|
ALTER TABLE f_news
|
||||||
|
ADD COLUMN site_code VARCHAR(32) NOT NULL DEFAULT 'wuhansaga'
|
||||||
|
COMMENT '站点编码,与 f_news_category.site_code 取值域一致'
|
||||||
|
AFTER category_id;
|
||||||
|
|
||||||
|
ALTER TABLE f_news
|
||||||
|
ADD KEY idx_f_news_site_list (site_code, del_flag, is_published, category_id),
|
||||||
|
ADD KEY idx_f_news_site_time (site_code, del_flag, is_published, create_time);
|
||||||
|
|
||||||
|
-- 旧数据:全部归入主站(若第二站需相同栏目结构,可复制分类再批量改 site_code / 或导数据)
|
||||||
|
UPDATE f_news_category SET site_code = 'wuhansaga' WHERE site_code = '' OR site_code IS NULL;
|
||||||
|
UPDATE f_news SET site_code = 'wuhansaga' WHERE site_code = '' OR site_code IS NULL;
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- 【可选】第二站点初始化分类骨架(与主站相同名称时仍需独立 category_id)
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- INSERT INTO f_news_category (site_code, name_zh, name_en, sort_order, is_published)
|
||||||
|
-- SELECT 'saga-secondary', name_zh, name_en, sort_order, is_published
|
||||||
|
-- FROM f_news_category WHERE site_code = 'wuhansaga' AND del_flag = 0;
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
package com.wuhansaga.server;
|
package com.wuhansaga.server;
|
||||||
|
|
||||||
|
import com.wuhansaga.server.config.PortalSiteProperties;
|
||||||
import org.mybatis.spring.annotation.MapperScan;
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
@MapperScan("com.wuhansaga.server.mapper")
|
@MapperScan("com.wuhansaga.server.mapper")
|
||||||
|
@EnableConfigurationProperties(PortalSiteProperties.class)
|
||||||
public class WuhanSagaApplication {
|
public class WuhanSagaApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.wuhansaga.server.config;
|
||||||
|
|
||||||
|
import com.wuhansaga.server.constant.SiteCodes;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@ConfigurationProperties(prefix = "app.portal")
|
||||||
|
public class PortalSiteProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 本实例默认站点(单域名单部署时一般不设查询参数,仅用此值)
|
||||||
|
*/
|
||||||
|
private String siteCode = SiteCodes.WUHAN_SAGA;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 逗号分隔允许列表;请求中的 siteCode 参数或 X-Portal-Site 头必须命中此值之一
|
||||||
|
*/
|
||||||
|
private String allowedSiteCodes = SiteCodes.WUHAN_SAGA + "," + SiteCodes.SAGA_SECONDARY;
|
||||||
|
|
||||||
|
public List<String> allowedCodesList() {
|
||||||
|
return Arrays.stream(allowedSiteCodes.split(","))
|
||||||
|
.map(String::trim)
|
||||||
|
.filter(s -> !s.isEmpty())
|
||||||
|
.map(s -> s.toLowerCase())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
package com.wuhansaga.server.config;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析前台站点:优先级为 查询参数 siteCode > 请求头 X-Portal-Site > 配置文件 app.portal.site-code。
|
||||||
|
* 非法编码回退到默认站点并打 WARN,避免扫库枚举。
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class PortalSiteResolver {
|
||||||
|
|
||||||
|
private static final String HEADER_PORTAL_SITE = "X-Portal-Site";
|
||||||
|
|
||||||
|
private final PortalSiteProperties portalSiteProperties;
|
||||||
|
|
||||||
|
public String resolve(HttpServletRequest request) {
|
||||||
|
List<String> allowed = portalSiteProperties.allowedCodesList();
|
||||||
|
String candidate = firstNonBlank(
|
||||||
|
request.getParameter("siteCode"),
|
||||||
|
request.getHeader(HEADER_PORTAL_SITE)
|
||||||
|
);
|
||||||
|
if (StringUtils.hasText(candidate)) {
|
||||||
|
String normalized = candidate.trim().toLowerCase(Locale.ROOT);
|
||||||
|
if (allowed.contains(normalized)) {
|
||||||
|
return normalized;
|
||||||
|
}
|
||||||
|
log.warn("[portal] 无效站点编码 [{}],将使用默认 [{}]", candidate, portalSiteProperties.getSiteCode());
|
||||||
|
}
|
||||||
|
String fallback = portalSiteProperties.getSiteCode().trim().toLowerCase(Locale.ROOT);
|
||||||
|
if (!allowed.contains(fallback)) {
|
||||||
|
log.warn("[portal] 默认站点 [{}] 不在 app.portal.allowed-site-codes 中,仍使用该值查询", fallback);
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String firstNonBlank(String a, String b) {
|
||||||
|
if (StringUtils.hasText(a)) {
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
if (StringUtils.hasText(b)) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.wuhansaga.server.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 站点编码常量:与库中 f_news.site_code / f_news_category.site_code 一致,扩展新站时在此与配置中同步增加。
|
||||||
|
*/
|
||||||
|
public final class SiteCodes {
|
||||||
|
|
||||||
|
private SiteCodes() {}
|
||||||
|
|
||||||
|
/** 武汉萨格主站 */
|
||||||
|
public static final String WUHAN_SAGA = "wuhansaga";
|
||||||
|
|
||||||
|
/** 第二站点(可按实际品牌改名,并同步改 application.yml 与库内数据) */
|
||||||
|
public static final String SAGA_SECONDARY = "saga-secondary";
|
||||||
|
}
|
||||||
@@ -21,11 +21,12 @@ public class AdminNewsController {
|
|||||||
private final NewsService newsService;
|
private final NewsService newsService;
|
||||||
private final NewsCategoryService newsCategoryService;
|
private final NewsCategoryService newsCategoryService;
|
||||||
|
|
||||||
@Operation(summary = "新闻列表")
|
@Operation(summary = "新闻列表(可选 siteCode 过滤站点,不传则全部站点)")
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public R<List<News>> list(@RequestParam(required = false) Long categoryId,
|
public R<List<News>> list(@RequestParam(required = false) Long categoryId,
|
||||||
@RequestParam(required = false) Integer isFeatured) {
|
@RequestParam(required = false) Integer isFeatured,
|
||||||
return R.ok(newsService.listPublished(categoryId, isFeatured));
|
@RequestParam(required = false) String siteCode) {
|
||||||
|
return R.ok(newsService.listForAdmin(categoryId, isFeatured, null, siteCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "新闻详情")
|
@Operation(summary = "新闻详情")
|
||||||
@@ -55,10 +56,10 @@ public class AdminNewsController {
|
|||||||
return R.ok();
|
return R.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "新闻分类列表")
|
@Operation(summary = "新闻分类列表(可选 siteCode 过滤)")
|
||||||
@GetMapping("/category")
|
@GetMapping("/category")
|
||||||
public R<List<NewsCategory>> listCategory() {
|
public R<List<NewsCategory>> listCategory(@RequestParam(required = false) String siteCode) {
|
||||||
return R.ok(newsCategoryService.listAll());
|
return R.ok(newsCategoryService.listAll(siteCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "新增新闻分类")
|
@Operation(summary = "新增新闻分类")
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
package com.wuhansaga.server.controller.portal;
|
package com.wuhansaga.server.controller.portal;
|
||||||
|
|
||||||
import com.wuhansaga.server.common.R;
|
import com.wuhansaga.server.common.R;
|
||||||
|
import com.wuhansaga.server.config.PortalSiteResolver;
|
||||||
import com.wuhansaga.server.entity.News;
|
import com.wuhansaga.server.entity.News;
|
||||||
import com.wuhansaga.server.entity.NewsCategory;
|
import com.wuhansaga.server.entity.NewsCategory;
|
||||||
import com.wuhansaga.server.service.NewsCategoryService;
|
import com.wuhansaga.server.service.NewsCategoryService;
|
||||||
import com.wuhansaga.server.service.NewsService;
|
import com.wuhansaga.server.service.NewsService;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
@@ -20,23 +22,28 @@ public class PortalNewsController {
|
|||||||
|
|
||||||
private final NewsService newsService;
|
private final NewsService newsService;
|
||||||
private final NewsCategoryService newsCategoryService;
|
private final NewsCategoryService newsCategoryService;
|
||||||
|
private final PortalSiteResolver portalSiteResolver;
|
||||||
|
|
||||||
@Operation(summary = "新闻分类列表")
|
@Operation(summary = "新闻分类列表(按站点隔离)")
|
||||||
@GetMapping("/category")
|
@GetMapping("/category")
|
||||||
public R<List<NewsCategory>> listCategory() {
|
public R<List<NewsCategory>> listCategory(HttpServletRequest request) {
|
||||||
return R.ok(newsCategoryService.listPublished());
|
String siteCode = portalSiteResolver.resolve(request);
|
||||||
|
return R.ok(newsCategoryService.listPublished(siteCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "新闻列表")
|
@Operation(summary = "新闻列表(按站点隔离;可选 ?siteCode=、请求头 X-Portal-Site)")
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public R<List<News>> list(@RequestParam(required = false) Long categoryId,
|
public R<List<News>> list(HttpServletRequest request,
|
||||||
@RequestParam(required = false) Integer isFeatured) {
|
@RequestParam(required = false) Long categoryId,
|
||||||
return R.ok(newsService.listPublished(categoryId, isFeatured));
|
@RequestParam(required = false) Integer isFeatured) {
|
||||||
|
String siteCode = portalSiteResolver.resolve(request);
|
||||||
|
return R.ok(newsService.listPublished(categoryId, isFeatured, siteCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operation(summary = "新闻详情")
|
@Operation(summary = "新闻详情(仅返回当前站点已发布稿件)")
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
public R<News> getById(@PathVariable Long id) {
|
public R<News> getById(HttpServletRequest request, @PathVariable Long id) {
|
||||||
return R.ok(newsService.getPublishedById(id));
|
String siteCode = portalSiteResolver.resolve(request);
|
||||||
|
return R.ok(newsService.getPublishedById(id, siteCode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ public class News {
|
|||||||
|
|
||||||
private Long newsId;
|
private Long newsId;
|
||||||
private Long categoryId;
|
private Long categoryId;
|
||||||
|
/** 站点编码:与新闻分类 siteCode 一致 */
|
||||||
|
private String siteCode;
|
||||||
private String titleZh;
|
private String titleZh;
|
||||||
private String titleEn;
|
private String titleEn;
|
||||||
private String excerptZh;
|
private String excerptZh;
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import java.time.LocalDateTime;
|
|||||||
public class NewsCategory {
|
public class NewsCategory {
|
||||||
|
|
||||||
private Long newsCategoryId;
|
private Long newsCategoryId;
|
||||||
|
/** 站点编码:同站新闻、分类共用一套取值域 */
|
||||||
|
private String siteCode;
|
||||||
private String nameZh;
|
private String nameZh;
|
||||||
private String nameEn;
|
private String nameEn;
|
||||||
private Integer sortOrder;
|
private Integer sortOrder;
|
||||||
|
|||||||
@@ -2,13 +2,14 @@ package com.wuhansaga.server.mapper;
|
|||||||
|
|
||||||
import com.wuhansaga.server.entity.NewsCategory;
|
import com.wuhansaga.server.entity.NewsCategory;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface NewsCategoryMapper {
|
public interface NewsCategoryMapper {
|
||||||
|
|
||||||
List<NewsCategory> selectAll();
|
List<NewsCategory> selectAll(@Param("siteCode") String siteCode);
|
||||||
|
|
||||||
NewsCategory selectById(Long id);
|
NewsCategory selectById(Long id);
|
||||||
|
|
||||||
@@ -18,5 +19,5 @@ public interface NewsCategoryMapper {
|
|||||||
|
|
||||||
int deleteById(Long id);
|
int deleteById(Long id);
|
||||||
|
|
||||||
List<NewsCategory> selectPublished();
|
List<NewsCategory> selectPublished(@Param("siteCode") String siteCode);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,11 +11,15 @@ public interface NewsMapper {
|
|||||||
|
|
||||||
List<News> selectList(@Param("categoryId") Long categoryId,
|
List<News> selectList(@Param("categoryId") Long categoryId,
|
||||||
@Param("isFeatured") Integer isFeatured,
|
@Param("isFeatured") Integer isFeatured,
|
||||||
@Param("keyword") String keyword);
|
@Param("keyword") String keyword,
|
||||||
|
@Param("isPublished") Integer isPublished,
|
||||||
|
@Param("siteCode") String siteCode);
|
||||||
|
|
||||||
long selectCount(@Param("categoryId") Long categoryId,
|
long selectCount(@Param("categoryId") Long categoryId,
|
||||||
@Param("isFeatured") Integer isFeatured,
|
@Param("isFeatured") Integer isFeatured,
|
||||||
@Param("keyword") String keyword);
|
@Param("keyword") String keyword,
|
||||||
|
@Param("isPublished") Integer isPublished,
|
||||||
|
@Param("siteCode") String siteCode);
|
||||||
|
|
||||||
News selectById(Long id);
|
News selectById(Long id);
|
||||||
|
|
||||||
@@ -26,7 +30,10 @@ public interface NewsMapper {
|
|||||||
int deleteById(Long id);
|
int deleteById(Long id);
|
||||||
|
|
||||||
List<News> selectPublished(@Param("categoryId") Long categoryId,
|
List<News> selectPublished(@Param("categoryId") Long categoryId,
|
||||||
@Param("isFeatured") Integer isFeatured);
|
@Param("isFeatured") Integer isFeatured,
|
||||||
|
@Param("siteCode") String siteCode);
|
||||||
|
|
||||||
|
News selectPublishedById(@Param("id") Long id, @Param("siteCode") String siteCode);
|
||||||
|
|
||||||
int incrementViewCount(Long id);
|
int incrementViewCount(Long id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.wuhansaga.server.service;
|
package com.wuhansaga.server.service;
|
||||||
|
|
||||||
|
import com.wuhansaga.server.constant.SiteCodes;
|
||||||
import com.wuhansaga.server.entity.NewsCategory;
|
import com.wuhansaga.server.entity.NewsCategory;
|
||||||
import com.wuhansaga.server.mapper.NewsCategoryMapper;
|
import com.wuhansaga.server.mapper.NewsCategoryMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -13,12 +15,13 @@ public class NewsCategoryService {
|
|||||||
|
|
||||||
private final NewsCategoryMapper newsCategoryMapper;
|
private final NewsCategoryMapper newsCategoryMapper;
|
||||||
|
|
||||||
public List<NewsCategory> listAll() {
|
/** siteCode 为空时不过滤站点(后台全量) */
|
||||||
return newsCategoryMapper.selectAll();
|
public List<NewsCategory> listAll(String siteCode) {
|
||||||
|
return newsCategoryMapper.selectAll(siteCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<NewsCategory> listPublished() {
|
public List<NewsCategory> listPublished(String siteCode) {
|
||||||
return newsCategoryMapper.selectPublished();
|
return newsCategoryMapper.selectPublished(siteCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public NewsCategory getById(Long id) {
|
public NewsCategory getById(Long id) {
|
||||||
@@ -26,11 +29,18 @@ public class NewsCategoryService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void add(NewsCategory entity) {
|
public void add(NewsCategory entity) {
|
||||||
|
if (!StringUtils.hasText(entity.getSiteCode())) {
|
||||||
|
entity.setSiteCode(SiteCodes.WUHAN_SAGA);
|
||||||
|
}
|
||||||
|
entity.setSiteCode(entity.getSiteCode().trim().toLowerCase());
|
||||||
entity.setIsPublished(1);
|
entity.setIsPublished(1);
|
||||||
newsCategoryMapper.insert(entity);
|
newsCategoryMapper.insert(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(NewsCategory entity) {
|
public void update(NewsCategory entity) {
|
||||||
|
if (StringUtils.hasText(entity.getSiteCode())) {
|
||||||
|
entity.setSiteCode(entity.getSiteCode().trim().toLowerCase());
|
||||||
|
}
|
||||||
newsCategoryMapper.update(entity);
|
newsCategoryMapper.update(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,14 @@ package com.wuhansaga.server.service;
|
|||||||
|
|
||||||
import com.wuhansaga.server.common.PageQuery;
|
import com.wuhansaga.server.common.PageQuery;
|
||||||
import com.wuhansaga.server.common.PageResult;
|
import com.wuhansaga.server.common.PageResult;
|
||||||
|
import com.wuhansaga.server.constant.SiteCodes;
|
||||||
import com.wuhansaga.server.entity.News;
|
import com.wuhansaga.server.entity.News;
|
||||||
|
import com.wuhansaga.server.entity.NewsCategory;
|
||||||
|
import com.wuhansaga.server.mapper.NewsCategoryMapper;
|
||||||
import com.wuhansaga.server.mapper.NewsMapper;
|
import com.wuhansaga.server.mapper.NewsMapper;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -14,40 +18,75 @@ import java.util.List;
|
|||||||
public class NewsService {
|
public class NewsService {
|
||||||
|
|
||||||
private final NewsMapper newsMapper;
|
private final NewsMapper newsMapper;
|
||||||
|
private final NewsCategoryMapper newsCategoryMapper;
|
||||||
|
|
||||||
public PageResult<News> page(Long categoryId, Integer isFeatured, String keyword, PageQuery query) {
|
public PageResult<News> page(Long categoryId, Integer isFeatured, String keyword, PageQuery query) {
|
||||||
List<News> records = newsMapper.selectList(categoryId, isFeatured, keyword);
|
List<News> records = newsMapper.selectList(categoryId, isFeatured, keyword, null, null);
|
||||||
return new PageResult<>(records, records.size(), query.getPage(), query.getSize());
|
return new PageResult<>(records, records.size(), query.getPage(), query.getSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<News> listPublished(Long categoryId, Integer isFeatured) {
|
public List<News> listPublished(Long categoryId, Integer isFeatured, String siteCode) {
|
||||||
return newsMapper.selectPublished(categoryId, isFeatured);
|
return newsMapper.selectPublished(categoryId, isFeatured, siteCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 后台列表:siteCode 为空则跨站点查询 */
|
||||||
|
public List<News> listForAdmin(Long categoryId, Integer isFeatured, String keyword, String siteCode) {
|
||||||
|
return newsMapper.selectList(categoryId, isFeatured, keyword, null, siteCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public News getById(Long id) {
|
public News getById(Long id) {
|
||||||
return newsMapper.selectById(id);
|
return newsMapper.selectById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public News getPublishedById(Long id) {
|
public News getPublishedById(Long id, String siteCode) {
|
||||||
News news = newsMapper.selectById(id);
|
News news = newsMapper.selectPublishedById(id, siteCode);
|
||||||
if (news != null && news.getIsPublished() == 1) {
|
if (news != null) {
|
||||||
newsMapper.incrementViewCount(id);
|
newsMapper.incrementViewCount(id);
|
||||||
return news;
|
|
||||||
}
|
}
|
||||||
return null;
|
return news;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(News entity) {
|
public void add(News entity) {
|
||||||
|
if (!StringUtils.hasText(entity.getSiteCode())) {
|
||||||
|
entity.setSiteCode(SiteCodes.WUHAN_SAGA);
|
||||||
|
}
|
||||||
|
entity.setSiteCode(entity.getSiteCode().trim().toLowerCase());
|
||||||
|
ensureNewsCategorySite(entity);
|
||||||
entity.setIsPublished(1);
|
entity.setIsPublished(1);
|
||||||
entity.setViewCount(0);
|
entity.setViewCount(0);
|
||||||
newsMapper.insert(entity);
|
newsMapper.insert(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void update(News entity) {
|
public void update(News entity) {
|
||||||
|
if (StringUtils.hasText(entity.getSiteCode())) {
|
||||||
|
entity.setSiteCode(entity.getSiteCode().trim().toLowerCase());
|
||||||
|
}
|
||||||
|
News existing = entity.getNewsId() != null ? newsMapper.selectById(entity.getNewsId()) : null;
|
||||||
|
Long categoryId = entity.getCategoryId() != null ? entity.getCategoryId() : (existing != null ? existing.getCategoryId() : null);
|
||||||
|
String siteCode = StringUtils.hasText(entity.getSiteCode())
|
||||||
|
? entity.getSiteCode()
|
||||||
|
: (existing != null ? existing.getSiteCode() : null);
|
||||||
|
News probe = new News();
|
||||||
|
probe.setCategoryId(categoryId);
|
||||||
|
probe.setSiteCode(siteCode);
|
||||||
|
ensureNewsCategorySite(probe);
|
||||||
newsMapper.update(entity);
|
newsMapper.update(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void delete(Long id) {
|
public void delete(Long id) {
|
||||||
newsMapper.deleteById(id);
|
newsMapper.deleteById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void ensureNewsCategorySite(News entity) {
|
||||||
|
if (!StringUtils.hasText(entity.getSiteCode()) || entity.getCategoryId() == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
NewsCategory cat = newsCategoryMapper.selectById(entity.getCategoryId());
|
||||||
|
if (cat == null) {
|
||||||
|
throw new IllegalArgumentException("新闻分类不存在");
|
||||||
|
}
|
||||||
|
if (!entity.getSiteCode().equals(cat.getSiteCode())) {
|
||||||
|
throw new IllegalArgumentException("新闻站点与分类站点不一致");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,3 +60,9 @@ upload:
|
|||||||
path: uploads/
|
path: uploads/
|
||||||
allowed-types: image/jpeg,image/png,image/gif,image/webp,image/svg+xml,video/mp4,video/webm
|
allowed-types: image/jpeg,image/png,image/gif,image/webp,image/svg+xml,video/mp4,video/webm
|
||||||
max-size: 52428800
|
max-size: 52428800
|
||||||
|
|
||||||
|
# 新闻中心多站点:单部署实例默认站点;扩展编码时改 allowed-site-codes 与库内数据
|
||||||
|
app:
|
||||||
|
portal:
|
||||||
|
site-code: wuhansaga
|
||||||
|
allowed-site-codes: wuhansaga,saga-secondary
|
||||||
|
|||||||
@@ -106,30 +106,31 @@ ON DUPLICATE KEY UPDATE
|
|||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 新闻分类
|
-- 新闻分类
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
INSERT INTO f_news_category (name_zh, name_en, sort_order) VALUES
|
INSERT INTO f_news_category (site_code, name_zh, name_en, sort_order) VALUES
|
||||||
('公司新闻', 'Company News', 10),
|
('wuhansaga', '公司新闻', 'Company News', 10),
|
||||||
('行业动态', 'Industry News', 20),
|
('wuhansaga', '行业动态', 'Industry News', 20),
|
||||||
('技术文章', 'Technical Articles', 30)
|
('wuhansaga', '技术文章', 'Technical Articles', 30)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
|
site_code = VALUES(site_code),
|
||||||
name_zh = VALUES(name_zh), name_en = VALUES(name_en), sort_order = VALUES(sort_order);
|
name_zh = VALUES(name_zh), name_en = VALUES(name_en), sort_order = VALUES(sort_order);
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 新闻文章(示例;生产环境可替换为正式稿件)
|
-- 新闻文章(示例;生产环境可替换为正式稿件)
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
INSERT INTO f_news (category_id, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en, is_featured, is_published, sort_order) VALUES
|
INSERT INTO f_news (category_id, site_code, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en, is_featured, is_published, sort_order) VALUES
|
||||||
(1, '武汉萨格官网更新上线', 'Wuhan Saga Website Refresh',
|
(1, 'wuhansaga', '武汉萨格官网更新上线', 'Wuhan Saga Website Refresh',
|
||||||
'集中展示连续板带处理产线、单体设备及工程案例。',
|
'集中展示连续板带处理产线、单体设备及工程案例。',
|
||||||
'Highlighting strip processing lines, equipment and engineering cases.',
|
'Highlighting strip processing lines, equipment and engineering cases.',
|
||||||
'<p>武汉萨格工程技术有限公司官网已升级,客户可通过产品中心了解热镀锌、退火、酸洗及感应加热等成套装备与单体设备,并查阅成功案例与新闻资讯。</p>',
|
'<p>武汉萨格工程技术有限公司官网已升级,客户可通过产品中心了解热镀锌、退火、酸洗及感应加热等成套装备与单体设备,并查阅成功案例与新闻资讯。</p>',
|
||||||
'<p>Wuhan Saga Engineering has refreshed its website for strip galvanizing, annealing, pickling, induction heating solutions, case studies and news.</p>',
|
'<p>Wuhan Saga Engineering has refreshed its website for strip galvanizing, annealing, pickling, induction heating solutions, case studies and news.</p>',
|
||||||
1, 1, 10),
|
1, 1, 10),
|
||||||
(2, '板带处理装备市场观察', 'Strip Processing Equipment Market Notes',
|
(2, 'wuhansaga', '板带处理装备市场观察', 'Strip Processing Equipment Market Notes',
|
||||||
'节能与智能化连续处理机组需求持续增长。',
|
'节能与智能化连续处理机组需求持续增长。',
|
||||||
'Growing demand for energy-efficient intelligent continuous lines.',
|
'Growing demand for energy-efficient intelligent continuous lines.',
|
||||||
'<p>国内外钢铁及加工企业持续投资连续镀锌、退火与酸洗机组。武汉萨格团队在设计与改造项目中注重节能环保与自动化控制。</p>',
|
'<p>国内外钢铁及加工企业持续投资连续镀锌、退火与酸洗机组。武汉萨格团队在设计与改造项目中注重节能环保与自动化控制。</p>',
|
||||||
'<p>Steel and processing firms continue to invest in continuous galvanizing, annealing and pickling lines with emphasis on energy saving and automation.</p>',
|
'<p>Steel and processing firms continue to invest in continuous galvanizing, annealing and pickling lines with emphasis on energy saving and automation.</p>',
|
||||||
0, 1, 20),
|
0, 1, 20),
|
||||||
(3, '感应加热在涂层干燥中的应用', 'Induction Heating in Coating Drying',
|
(3, 'wuhansaga', '感应加热在涂层干燥中的应用', 'Induction Heating in Coating Drying',
|
||||||
'非接触加热可提高涂层烘干效率并降低能耗。',
|
'非接触加热可提高涂层烘干效率并降低能耗。',
|
||||||
'Non-contact heating can improve drying efficiency and save energy.',
|
'Non-contact heating can improve drying efficiency and save energy.',
|
||||||
'<p>感应加热适用于涂层干燥等工艺环节,可与产线控制深度集成,实现分区温控与节能运行。</p>',
|
'<p>感应加热适用于涂层干燥等工艺环节,可与产线控制深度集成,实现分区温控与节能运行。</p>',
|
||||||
|
|||||||
@@ -7,11 +7,15 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<select id="selectAll" resultMap="newsCategoryResult">
|
<select id="selectAll" resultMap="newsCategoryResult">
|
||||||
SELECT * FROM f_news_category WHERE del_flag = 0 ORDER BY sort_order ASC
|
SELECT * FROM f_news_category WHERE del_flag = 0
|
||||||
|
<if test="siteCode != null and siteCode != ''">AND site_code = #{siteCode}</if>
|
||||||
|
ORDER BY sort_order ASC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectPublished" resultMap="newsCategoryResult">
|
<select id="selectPublished" resultMap="newsCategoryResult">
|
||||||
SELECT * FROM f_news_category WHERE del_flag = 0 AND is_published = 1 ORDER BY sort_order ASC
|
SELECT * FROM f_news_category WHERE del_flag = 0 AND is_published = 1
|
||||||
|
<if test="siteCode != null and siteCode != ''">AND site_code = #{siteCode}</if>
|
||||||
|
ORDER BY sort_order ASC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectById" resultMap="newsCategoryResult">
|
<select id="selectById" resultMap="newsCategoryResult">
|
||||||
@@ -19,13 +23,14 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insert" useGeneratedKeys="true" keyProperty="newsCategoryId" keyColumn="category_id">
|
<insert id="insert" useGeneratedKeys="true" keyProperty="newsCategoryId" keyColumn="category_id">
|
||||||
INSERT INTO f_news_category (name_zh, name_en, sort_order, is_published, create_by, remark)
|
INSERT INTO f_news_category (site_code, name_zh, name_en, sort_order, is_published, create_by, remark)
|
||||||
VALUES (#{nameZh}, #{nameEn}, #{sortOrder}, #{isPublished}, #{createBy}, #{remark})
|
VALUES (#{siteCode}, #{nameZh}, #{nameEn}, #{sortOrder}, #{isPublished}, #{createBy}, #{remark})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="update" parameterType="com.wuhansaga.server.entity.NewsCategory">
|
<update id="update" parameterType="com.wuhansaga.server.entity.NewsCategory">
|
||||||
UPDATE f_news_category
|
UPDATE f_news_category
|
||||||
<set>
|
<set>
|
||||||
|
<if test="siteCode != null">site_code = #{siteCode},</if>
|
||||||
<if test="nameZh != null">name_zh = #{nameZh},</if>
|
<if test="nameZh != null">name_zh = #{nameZh},</if>
|
||||||
<if test="nameEn != null">name_en = #{nameEn},</if>
|
<if test="nameEn != null">name_en = #{nameEn},</if>
|
||||||
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<resultMap id="newsResult" type="com.wuhansaga.server.entity.News">
|
<resultMap id="newsResult" type="com.wuhansaga.server.entity.News">
|
||||||
<id property="newsId" column="news_id"/>
|
<id property="newsId" column="news_id"/>
|
||||||
<result property="categoryId" column="category_id"/>
|
<result property="categoryId" column="category_id"/>
|
||||||
|
<result property="siteCode" column="site_code"/>
|
||||||
<result property="titleZh" column="title_zh"/>
|
<result property="titleZh" column="title_zh"/>
|
||||||
<result property="titleEn" column="title_en"/>
|
<result property="titleEn" column="title_en"/>
|
||||||
<result property="excerptZh" column="excerpt_zh"/>
|
<result property="excerptZh" column="excerpt_zh"/>
|
||||||
@@ -12,11 +13,21 @@
|
|||||||
<result property="contentZh" column="content_zh"/>
|
<result property="contentZh" column="content_zh"/>
|
||||||
<result property="contentEn" column="content_en"/>
|
<result property="contentEn" column="content_en"/>
|
||||||
<result property="coverImage" column="cover_image"/>
|
<result property="coverImage" column="cover_image"/>
|
||||||
|
<result property="metaTitleZh" column="meta_title_zh"/>
|
||||||
|
<result property="metaTitleEn" column="meta_title_en"/>
|
||||||
|
<result property="metaDescriptionZh" column="meta_description_zh"/>
|
||||||
|
<result property="metaDescriptionEn" column="meta_description_en"/>
|
||||||
|
<result property="metaKeywords" column="meta_keywords"/>
|
||||||
<result property="isFeatured" column="is_featured"/>
|
<result property="isFeatured" column="is_featured"/>
|
||||||
<result property="isPublished" column="is_published"/>
|
<result property="isPublished" column="is_published"/>
|
||||||
<result property="viewCount" column="view_count"/>
|
<result property="viewCount" column="view_count"/>
|
||||||
<result property="sortOrder" column="sort_order"/>
|
<result property="sortOrder" column="sort_order"/>
|
||||||
|
<result property="createBy" column="create_by"/>
|
||||||
|
<result property="updateBy" column="update_by"/>
|
||||||
<result property="createTime" column="create_time"/>
|
<result property="createTime" column="create_time"/>
|
||||||
|
<result property="updateTime" column="update_time"/>
|
||||||
|
<result property="remark" column="remark"/>
|
||||||
|
<result property="delFlag" column="del_flag"/>
|
||||||
<result property="categoryNameZh" column="category_name_zh"/>
|
<result property="categoryNameZh" column="category_name_zh"/>
|
||||||
<result property="categoryNameEn" column="category_name_en"/>
|
<result property="categoryNameEn" column="category_name_en"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
@@ -26,8 +37,10 @@
|
|||||||
FROM f_news n
|
FROM f_news n
|
||||||
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
||||||
WHERE n.del_flag = 0
|
WHERE n.del_flag = 0
|
||||||
|
<if test="siteCode != null and siteCode != ''">AND n.site_code = #{siteCode}</if>
|
||||||
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
||||||
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
||||||
|
<if test="isPublished != null">AND n.is_published = #{isPublished}</if>
|
||||||
<if test="keyword != null and keyword != ''">
|
<if test="keyword != null and keyword != ''">
|
||||||
AND (n.title_zh LIKE CONCAT('%',#{keyword},'%') OR n.title_en LIKE CONCAT('%',#{keyword},'%'))
|
AND (n.title_zh LIKE CONCAT('%',#{keyword},'%') OR n.title_en LIKE CONCAT('%',#{keyword},'%'))
|
||||||
</if>
|
</if>
|
||||||
@@ -35,11 +48,14 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectCount" resultType="long">
|
<select id="selectCount" resultType="long">
|
||||||
SELECT COUNT(*) FROM f_news WHERE del_flag = 0
|
SELECT COUNT(*) FROM f_news n
|
||||||
<if test="categoryId != null">AND category_id = #{categoryId}</if>
|
WHERE n.del_flag = 0
|
||||||
<if test="isFeatured != null">AND is_featured = #{isFeatured}</if>
|
<if test="siteCode != null and siteCode != ''">AND n.site_code = #{siteCode}</if>
|
||||||
|
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
||||||
|
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
||||||
|
<if test="isPublished != null">AND n.is_published = #{isPublished}</if>
|
||||||
<if test="keyword != null and keyword != ''">
|
<if test="keyword != null and keyword != ''">
|
||||||
AND (title_zh LIKE CONCAT('%',#{keyword},'%') OR title_en LIKE CONCAT('%',#{keyword},'%'))
|
AND (n.title_zh LIKE CONCAT('%',#{keyword},'%') OR n.title_en LIKE CONCAT('%',#{keyword},'%'))
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@@ -48,6 +64,7 @@
|
|||||||
FROM f_news n
|
FROM f_news n
|
||||||
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
||||||
WHERE n.del_flag = 0 AND n.is_published = 1
|
WHERE n.del_flag = 0 AND n.is_published = 1
|
||||||
|
AND n.site_code = #{siteCode}
|
||||||
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
||||||
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
||||||
ORDER BY n.sort_order ASC, n.create_time DESC
|
ORDER BY n.sort_order ASC, n.create_time DESC
|
||||||
@@ -60,11 +77,19 @@
|
|||||||
WHERE n.news_id = #{id} AND n.del_flag = 0
|
WHERE n.news_id = #{id} AND n.del_flag = 0
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectPublishedById" resultMap="newsResult">
|
||||||
|
SELECT n.*, nc.name_zh AS category_name_zh, nc.name_en AS category_name_en
|
||||||
|
FROM f_news n
|
||||||
|
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
||||||
|
WHERE n.news_id = #{id} AND n.del_flag = 0 AND n.is_published = 1
|
||||||
|
AND n.site_code = #{siteCode}
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insert" useGeneratedKeys="true" keyProperty="newsId">
|
<insert id="insert" useGeneratedKeys="true" keyProperty="newsId">
|
||||||
INSERT INTO f_news (category_id, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en,
|
INSERT INTO f_news (category_id, site_code, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en,
|
||||||
cover_image, meta_title_zh, meta_title_en, meta_description_zh, meta_description_en,
|
cover_image, meta_title_zh, meta_title_en, meta_description_zh, meta_description_en,
|
||||||
meta_keywords, is_featured, is_published, sort_order, create_by, remark)
|
meta_keywords, is_featured, is_published, sort_order, create_by, remark)
|
||||||
VALUES (#{categoryId}, #{titleZh}, #{titleEn}, #{excerptZh}, #{excerptEn}, #{contentZh}, #{contentEn},
|
VALUES (#{categoryId}, #{siteCode}, #{titleZh}, #{titleEn}, #{excerptZh}, #{excerptEn}, #{contentZh}, #{contentEn},
|
||||||
#{coverImage}, #{metaTitleZh}, #{metaTitleEn}, #{metaDescriptionZh}, #{metaDescriptionEn},
|
#{coverImage}, #{metaTitleZh}, #{metaTitleEn}, #{metaDescriptionZh}, #{metaDescriptionEn},
|
||||||
#{metaKeywords}, #{isFeatured}, #{isPublished}, #{sortOrder}, #{createBy}, #{remark})
|
#{metaKeywords}, #{isFeatured}, #{isPublished}, #{sortOrder}, #{createBy}, #{remark})
|
||||||
</insert>
|
</insert>
|
||||||
@@ -73,6 +98,7 @@
|
|||||||
UPDATE f_news
|
UPDATE f_news
|
||||||
<set>
|
<set>
|
||||||
<if test="categoryId != null">category_id = #{categoryId},</if>
|
<if test="categoryId != null">category_id = #{categoryId},</if>
|
||||||
|
<if test="siteCode != null">site_code = #{siteCode},</if>
|
||||||
<if test="titleZh != null">title_zh = #{titleZh},</if>
|
<if test="titleZh != null">title_zh = #{titleZh},</if>
|
||||||
<if test="titleEn != null">title_en = #{titleEn},</if>
|
<if test="titleEn != null">title_en = #{titleEn},</if>
|
||||||
<if test="excerptZh != null">excerpt_zh = #{excerptZh},</if>
|
<if test="excerptZh != null">excerpt_zh = #{excerptZh},</if>
|
||||||
@@ -80,6 +106,11 @@
|
|||||||
<if test="contentZh != null">content_zh = #{contentZh},</if>
|
<if test="contentZh != null">content_zh = #{contentZh},</if>
|
||||||
<if test="contentEn != null">content_en = #{contentEn},</if>
|
<if test="contentEn != null">content_en = #{contentEn},</if>
|
||||||
<if test="coverImage != null">cover_image = #{coverImage},</if>
|
<if test="coverImage != null">cover_image = #{coverImage},</if>
|
||||||
|
<if test="metaTitleZh != null">meta_title_zh = #{metaTitleZh},</if>
|
||||||
|
<if test="metaTitleEn != null">meta_title_en = #{metaTitleEn},</if>
|
||||||
|
<if test="metaDescriptionZh != null">meta_description_zh = #{metaDescriptionZh},</if>
|
||||||
|
<if test="metaDescriptionEn != null">meta_description_en = #{metaDescriptionEn},</if>
|
||||||
|
<if test="metaKeywords != null">meta_keywords = #{metaKeywords},</if>
|
||||||
<if test="isFeatured != null">is_featured = #{isFeatured},</if>
|
<if test="isFeatured != null">is_featured = #{isFeatured},</if>
|
||||||
<if test="isPublished != null">is_published = #{isPublished},</if>
|
<if test="isPublished != null">is_published = #{isPublished},</if>
|
||||||
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
||||||
|
|||||||
@@ -380,6 +380,7 @@ CREATE TABLE IF NOT EXISTS f_case_study (
|
|||||||
-- ================================================================
|
-- ================================================================
|
||||||
CREATE TABLE IF NOT EXISTS f_news_category (
|
CREATE TABLE IF NOT EXISTS f_news_category (
|
||||||
category_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
category_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
|
site_code VARCHAR(32) NOT NULL DEFAULT 'wuhansaga' COMMENT '站点编码:小写英文短码,与 f_news.site_code 取值域一致',
|
||||||
name_zh VARCHAR(100) NOT NULL COMMENT '分类名称(中文)',
|
name_zh VARCHAR(100) NOT NULL COMMENT '分类名称(中文)',
|
||||||
name_en VARCHAR(100) NOT NULL COMMENT '分类名称(英文)',
|
name_en VARCHAR(100) NOT NULL COMMENT '分类名称(英文)',
|
||||||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
||||||
@@ -390,7 +391,8 @@ CREATE TABLE IF NOT EXISTS f_news_category (
|
|||||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||||
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
||||||
PRIMARY KEY (category_id)
|
PRIMARY KEY (category_id),
|
||||||
|
KEY idx_f_news_category_site (site_code, del_flag, is_published, sort_order)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻分类';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻分类';
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
@@ -399,6 +401,7 @@ CREATE TABLE IF NOT EXISTS f_news_category (
|
|||||||
CREATE TABLE IF NOT EXISTS f_news (
|
CREATE TABLE IF NOT EXISTS f_news (
|
||||||
news_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
news_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
category_id BIGINT NOT NULL COMMENT '所属分类',
|
category_id BIGINT NOT NULL COMMENT '所属分类',
|
||||||
|
site_code VARCHAR(32) NOT NULL DEFAULT 'wuhansaga' COMMENT '站点编码:与分类 site_code 一致,用于多站点数据隔离',
|
||||||
title_zh VARCHAR(200) NOT NULL COMMENT '标题(中文)',
|
title_zh VARCHAR(200) NOT NULL COMMENT '标题(中文)',
|
||||||
title_en VARCHAR(200) NOT NULL COMMENT '标题(英文)',
|
title_en VARCHAR(200) NOT NULL COMMENT '标题(英文)',
|
||||||
excerpt_zh TEXT COMMENT '摘要(中文)',
|
excerpt_zh TEXT COMMENT '摘要(中文)',
|
||||||
@@ -422,6 +425,8 @@ CREATE TABLE IF NOT EXISTS f_news (
|
|||||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||||
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
||||||
PRIMARY KEY (news_id),
|
PRIMARY KEY (news_id),
|
||||||
|
KEY idx_f_news_site_list (site_code, del_flag, is_published, category_id),
|
||||||
|
KEY idx_f_news_site_time (site_code, del_flag, is_published, create_time),
|
||||||
KEY idx_f_news_category (category_id),
|
KEY idx_f_news_category (category_id),
|
||||||
KEY idx_f_news_create_time (create_time)
|
KEY idx_f_news_create_time (create_time)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻文章';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻文章';
|
||||||
|
|||||||
@@ -60,3 +60,9 @@ upload:
|
|||||||
path: uploads/
|
path: uploads/
|
||||||
allowed-types: image/jpeg,image/png,image/gif,image/webp,image/svg+xml,video/mp4,video/webm
|
allowed-types: image/jpeg,image/png,image/gif,image/webp,image/svg+xml,video/mp4,video/webm
|
||||||
max-size: 52428800
|
max-size: 52428800
|
||||||
|
|
||||||
|
# 新闻中心多站点:单部署实例默认站点;扩展编码时改 allowed-site-codes 与库内数据
|
||||||
|
app:
|
||||||
|
portal:
|
||||||
|
site-code: wuhansaga
|
||||||
|
allowed-site-codes: wuhansaga,saga-secondary
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -60,26 +60,33 @@ INSERT INTO f_company_info (
|
|||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 产品分类
|
-- 产品分类
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
INSERT INTO f_product_category (product_category_id, name_zh, name_en, parent_id, sort_order) VALUES
|
INSERT INTO f_product_category (product_category_id, name_zh, name_en, module_type, parent_id, sort_order) VALUES
|
||||||
(1, '连续涂镀机组', 'Continuous Coating Lines', NULL, 10),
|
(1, '连续涂镀机组', 'Continuous Coating Lines', 'product_line', NULL, 10),
|
||||||
(2, '连续热处理机组', 'Continuous Heat Treatment Lines', NULL, 20),
|
(2, '连续热处理机组', 'Continuous Heat Treatment Lines', 'product_line', NULL, 20),
|
||||||
(3, '表面处理机组', 'Surface Treatment Lines', NULL, 30),
|
(3, '表面处理机组', 'Surface Treatment Lines', 'product_line', NULL, 30),
|
||||||
(4, '后处理及辅机', 'Post-processing & Auxiliary', NULL, 40),
|
(4, '后处理及辅机', 'Post-processing & Auxiliary', 'product_line', NULL, 40),
|
||||||
(5, '单体设备', 'Single Equipment', NULL, 50),
|
(5, '单体设备', 'Single Equipment', 'equipment', NULL, 50),
|
||||||
(6, '备品备件', 'Spare Parts', NULL, 60),
|
(6, '备品备件', 'Spare Parts', 'spare_part', NULL, 60),
|
||||||
(11, '热镀锌/镀铝锌机组', 'Hot Dipped Galvanizing / Galvalume Line', 1, 11),
|
(11, '热镀锌/镀铝锌机组', 'Hot Dipped Galvanizing / Galvalume Line', 'product_line', 1, 11),
|
||||||
(12, '锌铝镁机组', 'Zinc Aluminum Magnesium (ZAM) Line', 1, 12),
|
(12, '锌铝镁机组', 'Zinc Aluminum Magnesium (ZAM) Line', 'product_line', 1, 12),
|
||||||
(13, '彩涂机组', 'Color Coating Line (CCL)', 1, 13),
|
(13, '彩涂机组', 'Color Coating Line (CCL)', 'product_line', 1, 13),
|
||||||
(21, '普碳钢连续退火线', 'Plain Carbon Steel Continuous Annealing Line', 2, 21),
|
(21, '普碳钢连续退火线', 'Plain Carbon Steel Continuous Annealing Line', 'product_line', 2, 21),
|
||||||
(22, '冷轧退火镀锌两用机组', 'Annealing & Galvanizing Combo Line', 2, 22),
|
(22, '冷轧退火镀锌两用机组', 'Annealing & Galvanizing Combo Line', 'product_line', 2, 22),
|
||||||
(23, '硅钢连续处理机组', 'Silicon Steel Processing Line', 2, 23),
|
(23, '硅钢连续处理机组', 'Silicon Steel Processing Line', 'product_line', 2, 23),
|
||||||
(31, '碳钢酸洗机组', 'Carbon Steel Pickling Line', 3, 31),
|
(31, '碳钢酸洗机组', 'Carbon Steel Pickling Line', 'product_line', 3, 31),
|
||||||
(32, '不锈钢退火酸洗机组', 'Stainless Steel Annealing & Pickling Line', 3, 32),
|
(32, '不锈钢退火酸洗机组', 'Stainless Steel Annealing & Pickling Line', 'product_line', 3, 32),
|
||||||
(41, '拉矫/脱脂/重卷线', 'Tension Leveling, Degreasing, Re-coiling', 4, 41)
|
(41, '拉矫/脱脂/重卷线', 'Tension Leveling, Degreasing, Re-coiling', 'product_line', 4, 41),
|
||||||
|
(200, '卷取设备', 'Reeling & Coiling Equipment', 'equipment', 5, 200),
|
||||||
|
(201, '炉类设备', 'Furnace Equipment', 'equipment', 5, 201),
|
||||||
|
(202, '涂布与焊接设备', 'Coating & Welding Equipment', 'equipment', 5, 202),
|
||||||
|
(203, '破鳞设备', 'Scale Breaking Equipment', 'equipment', 5, 203),
|
||||||
|
(204, '拉矫矫直设备', 'Leveling & Straightening Equipment', 'equipment', 5, 204),
|
||||||
|
(205, '剪切修边设备', 'Shearing & Trimming Equipment', 'equipment', 5, 205)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
name_zh = VALUES(name_zh), name_en = VALUES(name_en), parent_id = VALUES(parent_id), sort_order = VALUES(sort_order);
|
name_zh = VALUES(name_zh), name_en = VALUES(name_en), module_type = VALUES(module_type),
|
||||||
|
parent_id = VALUES(parent_id), sort_order = VALUES(sort_order);
|
||||||
|
|
||||||
ALTER TABLE f_product_category AUTO_INCREMENT = 100;
|
ALTER TABLE f_product_category AUTO_INCREMENT = 210;
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 案例分类
|
-- 案例分类
|
||||||
@@ -99,13 +106,37 @@ ON DUPLICATE KEY UPDATE
|
|||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 新闻分类
|
-- 新闻分类
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
INSERT INTO f_news_category (name_zh, name_en, sort_order) VALUES
|
INSERT INTO f_news_category (site_code, name_zh, name_en, sort_order) VALUES
|
||||||
('公司新闻', 'Company News', 10),
|
('wuhansaga', '公司新闻', 'Company News', 10),
|
||||||
('行业动态', 'Industry News', 20),
|
('wuhansaga', '行业动态', 'Industry News', 20),
|
||||||
('技术文章', 'Technical Articles', 30)
|
('wuhansaga', '技术文章', 'Technical Articles', 30)
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
|
site_code = VALUES(site_code),
|
||||||
name_zh = VALUES(name_zh), name_en = VALUES(name_en), sort_order = VALUES(sort_order);
|
name_zh = VALUES(name_zh), name_en = VALUES(name_en), sort_order = VALUES(sort_order);
|
||||||
|
|
||||||
|
-- ================================================================
|
||||||
|
-- 新闻文章(示例;生产环境可替换为正式稿件)
|
||||||
|
-- ================================================================
|
||||||
|
INSERT INTO f_news (category_id, site_code, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en, is_featured, is_published, sort_order) VALUES
|
||||||
|
(1, 'wuhansaga', '武汉萨格官网更新上线', 'Wuhan Saga Website Refresh',
|
||||||
|
'集中展示连续板带处理产线、单体设备及工程案例。',
|
||||||
|
'Highlighting strip processing lines, equipment and engineering cases.',
|
||||||
|
'<p>武汉萨格工程技术有限公司官网已升级,客户可通过产品中心了解热镀锌、退火、酸洗及感应加热等成套装备与单体设备,并查阅成功案例与新闻资讯。</p>',
|
||||||
|
'<p>Wuhan Saga Engineering has refreshed its website for strip galvanizing, annealing, pickling, induction heating solutions, case studies and news.</p>',
|
||||||
|
1, 1, 10),
|
||||||
|
(2, 'wuhansaga', '板带处理装备市场观察', 'Strip Processing Equipment Market Notes',
|
||||||
|
'节能与智能化连续处理机组需求持续增长。',
|
||||||
|
'Growing demand for energy-efficient intelligent continuous lines.',
|
||||||
|
'<p>国内外钢铁及加工企业持续投资连续镀锌、退火与酸洗机组。武汉萨格团队在设计与改造项目中注重节能环保与自动化控制。</p>',
|
||||||
|
'<p>Steel and processing firms continue to invest in continuous galvanizing, annealing and pickling lines with emphasis on energy saving and automation.</p>',
|
||||||
|
0, 1, 20),
|
||||||
|
(3, 'wuhansaga', '感应加热在涂层干燥中的应用', 'Induction Heating in Coating Drying',
|
||||||
|
'非接触加热可提高涂层烘干效率并降低能耗。',
|
||||||
|
'Non-contact heating can improve drying efficiency and save energy.',
|
||||||
|
'<p>感应加热适用于涂层干燥等工艺环节,可与产线控制深度集成,实现分区温控与节能运行。</p>',
|
||||||
|
'<p>Induction heating suits coating drying processes and integrates with line control for zoned temperature and energy saving.</p>',
|
||||||
|
0, 1, 30);
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 关于我们
|
-- 关于我们
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
@@ -278,28 +309,69 @@ ON DUPLICATE KEY UPDATE
|
|||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 单体设备
|
-- 单体设备
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
INSERT INTO f_single_equipment (category_id, name_zh, name_en, technical_highlights_zh, technical_highlights_en, sort_order) VALUES
|
INSERT INTO f_single_equipment (category_id, name_zh, name_en, technical_highlights_zh, technical_highlights_en, sort_order, is_published) VALUES
|
||||||
(5, '感应加热系统', 'Induction Heating System', '焊缝退火、硅钢轧前加热、涂层干燥', 'Weld annealing, Si-steel preheat, coating drying', 10),
|
(5, '感应加热系统', 'Induction Heating System', '焊缝退火、硅钢轧前加热、涂层干燥', 'Weld annealing, Si-steel preheat, coating drying', 10, 1),
|
||||||
(5, '镀后冷却系统', 'Post-plating Cooling System', '喷气冷却、气雾冷却(BLADE喷嘴)', 'Jet and air-mist cooling (BLADE nozzles)', 20),
|
(5, '镀后冷却系统', 'Post-plating Cooling System', '喷气冷却、气雾冷却(BLADE喷嘴)', 'Jet and air-mist cooling (BLADE nozzles)', 20, 1),
|
||||||
(5, '电磁驱渣器', 'Electromagnetic Slag Drive', '替代人工除渣,自动化锌锅', 'Automated zinc pot skimming', 30),
|
(5, '电磁驱渣器', 'Electromagnetic Slag Drive', '替代人工除渣,自动化锌锅', 'Automated zinc pot skimming', 30, 1),
|
||||||
(5, '红外辐射炉', 'Infrared Radiation Furnace', '涂层干燥,非接触加热', 'Non-contact coating drying', 40),
|
(5, '红外辐射炉', 'Infrared Radiation Furnace', '涂层干燥,非接触加热', 'Non-contact coating drying', 40, 1),
|
||||||
(5, '氢气回收装置', 'Hydrogen Recovery Unit', '回收率>75%,2-3年回本', 'Recovery rate >75%, typical payback 2–3 years', 50),
|
(5, '氢气回收装置', 'Hydrogen Recovery Unit', '回收率>75%,2-3年回本', 'Recovery rate >75%, typical payback 2–3 years', 50, 1),
|
||||||
(5, '合金化炉', 'Alloy Coating Furnace', '直接火焰加热(FLOX/MILD),NOx降50-70%', 'FLOX/MILD firing, NOx reduction 50-70%', 60),
|
(5, '合金化炉', 'Alloy Coating Furnace', '直接火焰加热(FLOX/MILD),NOx降50-70%', 'FLOX/MILD firing, NOx reduction 50-70%', 60, 1),
|
||||||
(5, '燃烧系统改造', 'Combustion System Revamp', '双燃料切换(LPG/NG/COG)', 'Dual-fuel switching (LPG/NG/COG)', 70)
|
(5, '燃烧系统改造', 'Combustion System Revamp', '双燃料切换(LPG/NG/COG)', 'Dual-fuel switching (LPG/NG/COG)', 70, 1),
|
||||||
ON DUPLICATE KEY UPDATE
|
(200, '开收卷机(机型一)', 'Payoff / Tension Reel (Type A)', '板材开卷、张力卷取与收卷', 'Strip payoff, tension reel and recoiling', 200, 1),
|
||||||
name_zh = VALUES(name_zh), name_en = VALUES(name_en), technical_highlights_zh = VALUES(technical_highlights_zh),
|
(200, '开收卷机(机型二)', 'Payoff / Tension Reel (Type B)', '重载卷取与张力控制', 'Heavy-duty recoiling with tension control', 210, 1),
|
||||||
|
(201, '立式炉', 'Vertical Furnace', '立式布置热处理炉', 'Vertically arranged heat-treatment furnace', 220, 1),
|
||||||
|
(201, '卧式炉', 'Horizontal Furnace', '卧式连续热处理炉', 'Horizontal continuous heat-treatment furnace', 230, 1),
|
||||||
|
(202, '焊机', 'Welder', '带钢闪光焊、搭接焊等', 'Flash welding, lap welding for strip joining', 240, 1),
|
||||||
|
(202, '立式涂机', 'Vertical Coating Machine', '立式辊涂、涂层施加', 'Vertical roll coater / film application', 250, 1),
|
||||||
|
(202, '卧式涂机', 'Horizontal Coating Machine', '水平涂覆与烘干前道工序', 'Horizontal coating application', 260, 1),
|
||||||
|
(203, '破鳞机(机型一)', 'Scale Breaker (Type I)', '热轧氧化铁皮破碎与疏松', 'Breaking and loosening hot-rolled scale', 270, 1),
|
||||||
|
(203, '破鳞机(机型二)', 'Scale Breaker (Type II)', '另一型式破鳞与延伸', 'Alternative scale breaking configuration', 280, 1),
|
||||||
|
(204, '拉矫机', 'Tension Leveler', '带钢拉伸弯曲矫直', 'Tension leveling / stretch leveling', 290, 1),
|
||||||
|
(204, '两弯两矫拉弯矫直机', 'Two-bend Two-straight Stretch-bend Leveler', '多辊拉弯矫直改善板形', 'Multi-roll stretch-bend leveling for strip shape', 300, 1),
|
||||||
|
(205, '圆盘剪', 'Side Trimmer', '两侧碎边裁剪宽度', 'Side trimming for strip width', 310, 1),
|
||||||
|
(205, '碎边剪', 'Edge Chop Shear', '碎边切断与收集', 'Chopping and handling of edge trim', 320, 1),
|
||||||
|
(205, '圆盘剪(双刀头)', 'Side Trimmer (Twin Knife Head)', '双刀头提高修边效率', 'Twin knife heads for trimming efficiency', 330, 1),
|
||||||
|
(205, '双刀头碎边圆盘剪', 'Twin-head Edge-chop Disc Shear', '碎边与圆盘剪组合结构', 'Combined edge chop and disc shear', 340, 1)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
name_zh = VALUES(name_zh), name_en = VALUES(name_en), technical_highlights_zh = VALUES(technical_highlights_zh),
|
||||||
technical_highlights_en = VALUES(technical_highlights_en), sort_order = VALUES(sort_order);
|
technical_highlights_en = VALUES(technical_highlights_en), sort_order = VALUES(sort_order);
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 备品备件
|
-- 成套机组与单体设备关联(与 f_single_equipment 自增 ID 顺序一致,可后台调整)
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
INSERT INTO f_spare_part (category_id, name_zh, name_en, description_zh, description_en, sort_order) VALUES
|
INSERT INTO f_product_line_equipment (product_line_id, equipment_id, sort_order) VALUES
|
||||||
(6, '辐射管(W/I/U型)', 'Radiant Tubes (W/I/U)', '工业炉用辐射管', 'Radiant tubes for industrial furnaces', 10),
|
(1, 3, 10), (1, 6, 20), (1, 2, 30), (1, 5, 40), (1, 1, 50), (1, 7, 60),
|
||||||
(6, '换热器', 'Heat Exchangers', '翅片管换热器、RJC换热器等', 'Finned tube and RJC-type exchangers', 20),
|
(2, 2, 10), (2, 5, 20), (2, 6, 30), (2, 7, 40),
|
||||||
(6, '炉辊与张力辊', 'Hearth & Tension Rolls', '炉辊、大炉辊、张力辊、转向辊等', 'Hearth rolls, tension rolls, deflector rolls', 30)
|
(3, 10, 10), (3, 11, 20), (3, 4, 30), (3, 17, 40),
|
||||||
ON DUPLICATE KEY UPDATE
|
(4, 10, 10), (4, 11, 20), (4, 8, 30), (4, 9, 40), (4, 2, 50), (4, 6, 60),
|
||||||
name_zh = VALUES(name_zh), name_en = VALUES(name_en), description_zh = VALUES(description_zh),
|
(5, 4, 10), (5, 1, 20), (5, 13, 30), (5, 14, 40),
|
||||||
description_en = VALUES(description_en), sort_order = VALUES(sort_order);
|
(6, 1, 10), (6, 10, 20), (6, 11, 30), (6, 5, 40),
|
||||||
|
(7, 15, 10), (7, 16, 20), (7, 17, 30), (7, 19, 40),
|
||||||
|
(8, 10, 10), (8, 11, 20), (8, 12, 30),
|
||||||
|
(9, 17, 10), (9, 18, 20), (9, 19, 30), (9, 20, 40), (9, 8, 50)
|
||||||
|
ON DUPLICATE KEY UPDATE sort_order = VALUES(sort_order);
|
||||||
|
|
||||||
|
-- ================================================================
|
||||||
|
-- 备品备件(产品目录单品,与官网图册一致;封面请在后台上传 cover_image)
|
||||||
|
-- ================================================================
|
||||||
|
INSERT INTO f_spare_part (category_id, name_zh, name_en, description_zh, description_en, sort_order, is_published) VALUES
|
||||||
|
(6, '翅片管换热器', 'Finned Tube Heat Exchanger', '备品备件', 'Spare parts', 10, 1),
|
||||||
|
(6, 'RJC 换热器', 'RJC Heat exchanger', '备品备件', 'Spare parts', 20, 1),
|
||||||
|
(6, 'W 型辐射管', 'W-radiant tube', '备品备件', 'Spare parts', 30, 1),
|
||||||
|
(6, 'I 型辐射管', 'I-type Radiant Tube', '备品备件', 'Spare parts', 40, 1),
|
||||||
|
(6, 'U 型辐射管', 'U-Radiant Tube', '备品备件', 'Spare parts', 50, 1),
|
||||||
|
(6, '滑块', 'Slide Block', '备品备件', 'Spare parts', 60, 1),
|
||||||
|
(6, '轴套衬套', 'Bush and Sleeve', '备品备件', 'Spare parts', 70, 1),
|
||||||
|
(6, '支臂', 'Support Arm', '备品备件', 'Spare parts', 80, 1),
|
||||||
|
(6, '炉辊', 'Hearth Roll', '备品备件', 'Spare parts', 90, 1),
|
||||||
|
(6, '大炉辊', 'Big Hearth Roll', '备品备件', 'Spare parts', 100, 1),
|
||||||
|
(6, '镀铬辊', 'Chromed Roll', '备品备件', 'Spare parts', 110, 1),
|
||||||
|
(6, '氯丁胶转向辊', 'Rubber Turning Roll', '备品备件', 'Spare parts', 120, 1),
|
||||||
|
(6, '聚氨酯辊', 'PU Roll', '备品备件', 'Spare parts', 130, 1),
|
||||||
|
(6, '汲料辊', 'Pick Up Roll', '备品备件', 'Spare parts', 140, 1),
|
||||||
|
(6, '托辊', 'Support Roll', '备品备件', 'Spare parts', 150, 1),
|
||||||
|
(6, '水淬辊', 'Water Quenching Roll', '备品备件', 'Spare parts', 160, 1),
|
||||||
|
(6, '张力辊', 'Bridle Roll', '备品备件', 'Spare parts', 170, 1);
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 成功案例
|
-- 成功案例
|
||||||
@@ -321,4 +393,5 @@ ON DUPLICATE KEY UPDATE
|
|||||||
ALTER TABLE f_company_info AUTO_INCREMENT = 2;
|
ALTER TABLE f_company_info AUTO_INCREMENT = 2;
|
||||||
ALTER TABLE f_case_category AUTO_INCREMENT = 9;
|
ALTER TABLE f_case_category AUTO_INCREMENT = 9;
|
||||||
ALTER TABLE f_news_category AUTO_INCREMENT = 4;
|
ALTER TABLE f_news_category AUTO_INCREMENT = 4;
|
||||||
|
ALTER TABLE f_news AUTO_INCREMENT = 4;
|
||||||
ALTER TABLE f_media_library AUTO_INCREMENT = 500;
|
ALTER TABLE f_media_library AUTO_INCREMENT = 500;
|
||||||
@@ -7,11 +7,15 @@
|
|||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<select id="selectAll" resultMap="newsCategoryResult">
|
<select id="selectAll" resultMap="newsCategoryResult">
|
||||||
SELECT * FROM f_news_category WHERE del_flag = 0 ORDER BY sort_order ASC
|
SELECT * FROM f_news_category WHERE del_flag = 0
|
||||||
|
<if test="siteCode != null and siteCode != ''">AND site_code = #{siteCode}</if>
|
||||||
|
ORDER BY sort_order ASC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectPublished" resultMap="newsCategoryResult">
|
<select id="selectPublished" resultMap="newsCategoryResult">
|
||||||
SELECT * FROM f_news_category WHERE del_flag = 0 AND is_published = 1 ORDER BY sort_order ASC
|
SELECT * FROM f_news_category WHERE del_flag = 0 AND is_published = 1
|
||||||
|
<if test="siteCode != null and siteCode != ''">AND site_code = #{siteCode}</if>
|
||||||
|
ORDER BY sort_order ASC
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectById" resultMap="newsCategoryResult">
|
<select id="selectById" resultMap="newsCategoryResult">
|
||||||
@@ -19,13 +23,14 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<insert id="insert" useGeneratedKeys="true" keyProperty="newsCategoryId" keyColumn="category_id">
|
<insert id="insert" useGeneratedKeys="true" keyProperty="newsCategoryId" keyColumn="category_id">
|
||||||
INSERT INTO f_news_category (name_zh, name_en, sort_order, is_published, create_by, remark)
|
INSERT INTO f_news_category (site_code, name_zh, name_en, sort_order, is_published, create_by, remark)
|
||||||
VALUES (#{nameZh}, #{nameEn}, #{sortOrder}, #{isPublished}, #{createBy}, #{remark})
|
VALUES (#{siteCode}, #{nameZh}, #{nameEn}, #{sortOrder}, #{isPublished}, #{createBy}, #{remark})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="update" parameterType="com.wuhansaga.server.entity.NewsCategory">
|
<update id="update" parameterType="com.wuhansaga.server.entity.NewsCategory">
|
||||||
UPDATE f_news_category
|
UPDATE f_news_category
|
||||||
<set>
|
<set>
|
||||||
|
<if test="siteCode != null">site_code = #{siteCode},</if>
|
||||||
<if test="nameZh != null">name_zh = #{nameZh},</if>
|
<if test="nameZh != null">name_zh = #{nameZh},</if>
|
||||||
<if test="nameEn != null">name_en = #{nameEn},</if>
|
<if test="nameEn != null">name_en = #{nameEn},</if>
|
||||||
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
<resultMap id="newsResult" type="com.wuhansaga.server.entity.News">
|
<resultMap id="newsResult" type="com.wuhansaga.server.entity.News">
|
||||||
<id property="newsId" column="news_id"/>
|
<id property="newsId" column="news_id"/>
|
||||||
<result property="categoryId" column="category_id"/>
|
<result property="categoryId" column="category_id"/>
|
||||||
|
<result property="siteCode" column="site_code"/>
|
||||||
<result property="titleZh" column="title_zh"/>
|
<result property="titleZh" column="title_zh"/>
|
||||||
<result property="titleEn" column="title_en"/>
|
<result property="titleEn" column="title_en"/>
|
||||||
<result property="excerptZh" column="excerpt_zh"/>
|
<result property="excerptZh" column="excerpt_zh"/>
|
||||||
@@ -12,11 +13,21 @@
|
|||||||
<result property="contentZh" column="content_zh"/>
|
<result property="contentZh" column="content_zh"/>
|
||||||
<result property="contentEn" column="content_en"/>
|
<result property="contentEn" column="content_en"/>
|
||||||
<result property="coverImage" column="cover_image"/>
|
<result property="coverImage" column="cover_image"/>
|
||||||
|
<result property="metaTitleZh" column="meta_title_zh"/>
|
||||||
|
<result property="metaTitleEn" column="meta_title_en"/>
|
||||||
|
<result property="metaDescriptionZh" column="meta_description_zh"/>
|
||||||
|
<result property="metaDescriptionEn" column="meta_description_en"/>
|
||||||
|
<result property="metaKeywords" column="meta_keywords"/>
|
||||||
<result property="isFeatured" column="is_featured"/>
|
<result property="isFeatured" column="is_featured"/>
|
||||||
<result property="isPublished" column="is_published"/>
|
<result property="isPublished" column="is_published"/>
|
||||||
<result property="viewCount" column="view_count"/>
|
<result property="viewCount" column="view_count"/>
|
||||||
<result property="sortOrder" column="sort_order"/>
|
<result property="sortOrder" column="sort_order"/>
|
||||||
|
<result property="createBy" column="create_by"/>
|
||||||
|
<result property="updateBy" column="update_by"/>
|
||||||
<result property="createTime" column="create_time"/>
|
<result property="createTime" column="create_time"/>
|
||||||
|
<result property="updateTime" column="update_time"/>
|
||||||
|
<result property="remark" column="remark"/>
|
||||||
|
<result property="delFlag" column="del_flag"/>
|
||||||
<result property="categoryNameZh" column="category_name_zh"/>
|
<result property="categoryNameZh" column="category_name_zh"/>
|
||||||
<result property="categoryNameEn" column="category_name_en"/>
|
<result property="categoryNameEn" column="category_name_en"/>
|
||||||
</resultMap>
|
</resultMap>
|
||||||
@@ -26,8 +37,10 @@
|
|||||||
FROM f_news n
|
FROM f_news n
|
||||||
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
||||||
WHERE n.del_flag = 0
|
WHERE n.del_flag = 0
|
||||||
|
<if test="siteCode != null and siteCode != ''">AND n.site_code = #{siteCode}</if>
|
||||||
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
||||||
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
||||||
|
<if test="isPublished != null">AND n.is_published = #{isPublished}</if>
|
||||||
<if test="keyword != null and keyword != ''">
|
<if test="keyword != null and keyword != ''">
|
||||||
AND (n.title_zh LIKE CONCAT('%',#{keyword},'%') OR n.title_en LIKE CONCAT('%',#{keyword},'%'))
|
AND (n.title_zh LIKE CONCAT('%',#{keyword},'%') OR n.title_en LIKE CONCAT('%',#{keyword},'%'))
|
||||||
</if>
|
</if>
|
||||||
@@ -35,11 +48,14 @@
|
|||||||
</select>
|
</select>
|
||||||
|
|
||||||
<select id="selectCount" resultType="long">
|
<select id="selectCount" resultType="long">
|
||||||
SELECT COUNT(*) FROM f_news WHERE del_flag = 0
|
SELECT COUNT(*) FROM f_news n
|
||||||
<if test="categoryId != null">AND category_id = #{categoryId}</if>
|
WHERE n.del_flag = 0
|
||||||
<if test="isFeatured != null">AND is_featured = #{isFeatured}</if>
|
<if test="siteCode != null and siteCode != ''">AND n.site_code = #{siteCode}</if>
|
||||||
|
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
||||||
|
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
||||||
|
<if test="isPublished != null">AND n.is_published = #{isPublished}</if>
|
||||||
<if test="keyword != null and keyword != ''">
|
<if test="keyword != null and keyword != ''">
|
||||||
AND (title_zh LIKE CONCAT('%',#{keyword},'%') OR title_en LIKE CONCAT('%',#{keyword},'%'))
|
AND (n.title_zh LIKE CONCAT('%',#{keyword},'%') OR n.title_en LIKE CONCAT('%',#{keyword},'%'))
|
||||||
</if>
|
</if>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@@ -48,6 +64,7 @@
|
|||||||
FROM f_news n
|
FROM f_news n
|
||||||
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
||||||
WHERE n.del_flag = 0 AND n.is_published = 1
|
WHERE n.del_flag = 0 AND n.is_published = 1
|
||||||
|
AND n.site_code = #{siteCode}
|
||||||
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
<if test="categoryId != null">AND n.category_id = #{categoryId}</if>
|
||||||
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
<if test="isFeatured != null">AND n.is_featured = #{isFeatured}</if>
|
||||||
ORDER BY n.sort_order ASC, n.create_time DESC
|
ORDER BY n.sort_order ASC, n.create_time DESC
|
||||||
@@ -60,11 +77,19 @@
|
|||||||
WHERE n.news_id = #{id} AND n.del_flag = 0
|
WHERE n.news_id = #{id} AND n.del_flag = 0
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectPublishedById" resultMap="newsResult">
|
||||||
|
SELECT n.*, nc.name_zh AS category_name_zh, nc.name_en AS category_name_en
|
||||||
|
FROM f_news n
|
||||||
|
LEFT JOIN f_news_category nc ON n.category_id = nc.category_id
|
||||||
|
WHERE n.news_id = #{id} AND n.del_flag = 0 AND n.is_published = 1
|
||||||
|
AND n.site_code = #{siteCode}
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insert" useGeneratedKeys="true" keyProperty="newsId">
|
<insert id="insert" useGeneratedKeys="true" keyProperty="newsId">
|
||||||
INSERT INTO f_news (category_id, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en,
|
INSERT INTO f_news (category_id, site_code, title_zh, title_en, excerpt_zh, excerpt_en, content_zh, content_en,
|
||||||
cover_image, meta_title_zh, meta_title_en, meta_description_zh, meta_description_en,
|
cover_image, meta_title_zh, meta_title_en, meta_description_zh, meta_description_en,
|
||||||
meta_keywords, is_featured, is_published, sort_order, create_by, remark)
|
meta_keywords, is_featured, is_published, sort_order, create_by, remark)
|
||||||
VALUES (#{categoryId}, #{titleZh}, #{titleEn}, #{excerptZh}, #{excerptEn}, #{contentZh}, #{contentEn},
|
VALUES (#{categoryId}, #{siteCode}, #{titleZh}, #{titleEn}, #{excerptZh}, #{excerptEn}, #{contentZh}, #{contentEn},
|
||||||
#{coverImage}, #{metaTitleZh}, #{metaTitleEn}, #{metaDescriptionZh}, #{metaDescriptionEn},
|
#{coverImage}, #{metaTitleZh}, #{metaTitleEn}, #{metaDescriptionZh}, #{metaDescriptionEn},
|
||||||
#{metaKeywords}, #{isFeatured}, #{isPublished}, #{sortOrder}, #{createBy}, #{remark})
|
#{metaKeywords}, #{isFeatured}, #{isPublished}, #{sortOrder}, #{createBy}, #{remark})
|
||||||
</insert>
|
</insert>
|
||||||
@@ -73,6 +98,7 @@
|
|||||||
UPDATE f_news
|
UPDATE f_news
|
||||||
<set>
|
<set>
|
||||||
<if test="categoryId != null">category_id = #{categoryId},</if>
|
<if test="categoryId != null">category_id = #{categoryId},</if>
|
||||||
|
<if test="siteCode != null">site_code = #{siteCode},</if>
|
||||||
<if test="titleZh != null">title_zh = #{titleZh},</if>
|
<if test="titleZh != null">title_zh = #{titleZh},</if>
|
||||||
<if test="titleEn != null">title_en = #{titleEn},</if>
|
<if test="titleEn != null">title_en = #{titleEn},</if>
|
||||||
<if test="excerptZh != null">excerpt_zh = #{excerptZh},</if>
|
<if test="excerptZh != null">excerpt_zh = #{excerptZh},</if>
|
||||||
@@ -80,6 +106,11 @@
|
|||||||
<if test="contentZh != null">content_zh = #{contentZh},</if>
|
<if test="contentZh != null">content_zh = #{contentZh},</if>
|
||||||
<if test="contentEn != null">content_en = #{contentEn},</if>
|
<if test="contentEn != null">content_en = #{contentEn},</if>
|
||||||
<if test="coverImage != null">cover_image = #{coverImage},</if>
|
<if test="coverImage != null">cover_image = #{coverImage},</if>
|
||||||
|
<if test="metaTitleZh != null">meta_title_zh = #{metaTitleZh},</if>
|
||||||
|
<if test="metaTitleEn != null">meta_title_en = #{metaTitleEn},</if>
|
||||||
|
<if test="metaDescriptionZh != null">meta_description_zh = #{metaDescriptionZh},</if>
|
||||||
|
<if test="metaDescriptionEn != null">meta_description_en = #{metaDescriptionEn},</if>
|
||||||
|
<if test="metaKeywords != null">meta_keywords = #{metaKeywords},</if>
|
||||||
<if test="isFeatured != null">is_featured = #{isFeatured},</if>
|
<if test="isFeatured != null">is_featured = #{isFeatured},</if>
|
||||||
<if test="isPublished != null">is_published = #{isPublished},</if>
|
<if test="isPublished != null">is_published = #{isPublished},</if>
|
||||||
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
<if test="sortOrder != null">sort_order = #{sortOrder},</if>
|
||||||
|
|||||||
@@ -195,6 +195,7 @@ CREATE TABLE IF NOT EXISTS f_product_category (
|
|||||||
product_category_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
product_category_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
name_zh VARCHAR(100) NOT NULL COMMENT '分类名称(中文)',
|
name_zh VARCHAR(100) NOT NULL COMMENT '分类名称(中文)',
|
||||||
name_en VARCHAR(100) NOT NULL COMMENT '分类名称(英文)',
|
name_en VARCHAR(100) NOT NULL COMMENT '分类名称(英文)',
|
||||||
|
module_type VARCHAR(20) NOT NULL DEFAULT 'product_line' COMMENT '模块类型 product_line/equipment/spare_part',
|
||||||
parent_id BIGINT NULL COMMENT '父分类ID',
|
parent_id BIGINT NULL COMMENT '父分类ID',
|
||||||
icon_class VARCHAR(100) COMMENT '图标类名',
|
icon_class VARCHAR(100) COMMENT '图标类名',
|
||||||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
||||||
@@ -280,6 +281,19 @@ CREATE TABLE IF NOT EXISTS f_single_equipment (
|
|||||||
KEY idx_f_single_equipment_category (category_id)
|
KEY idx_f_single_equipment_category (category_id)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='单体设备';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='单体设备';
|
||||||
|
|
||||||
|
-- ================================================================
|
||||||
|
-- 成套机组与单体设备关联表(多对多)
|
||||||
|
-- ================================================================
|
||||||
|
CREATE TABLE IF NOT EXISTS f_product_line_equipment (
|
||||||
|
product_line_equipment_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
|
product_line_id BIGINT NOT NULL COMMENT '成套机组ID',
|
||||||
|
equipment_id BIGINT NOT NULL COMMENT '单体设备ID(f_single_equipment)',
|
||||||
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
||||||
|
PRIMARY KEY (product_line_equipment_id),
|
||||||
|
UNIQUE KEY uk_f_ple_line_equipment (product_line_id, equipment_id),
|
||||||
|
KEY idx_f_ple_equipment (equipment_id)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='成套机组关联单体设备';
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
-- 备品备件表
|
-- 备品备件表
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
@@ -366,6 +380,7 @@ CREATE TABLE IF NOT EXISTS f_case_study (
|
|||||||
-- ================================================================
|
-- ================================================================
|
||||||
CREATE TABLE IF NOT EXISTS f_news_category (
|
CREATE TABLE IF NOT EXISTS f_news_category (
|
||||||
category_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
category_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
|
site_code VARCHAR(32) NOT NULL DEFAULT 'wuhansaga' COMMENT '站点编码:小写英文短码,与 f_news.site_code 取值域一致',
|
||||||
name_zh VARCHAR(100) NOT NULL COMMENT '分类名称(中文)',
|
name_zh VARCHAR(100) NOT NULL COMMENT '分类名称(中文)',
|
||||||
name_en VARCHAR(100) NOT NULL COMMENT '分类名称(英文)',
|
name_en VARCHAR(100) NOT NULL COMMENT '分类名称(英文)',
|
||||||
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
sort_order INT NOT NULL DEFAULT 0 COMMENT '排序',
|
||||||
@@ -376,7 +391,8 @@ CREATE TABLE IF NOT EXISTS f_news_category (
|
|||||||
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
|
||||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||||
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
||||||
PRIMARY KEY (category_id)
|
PRIMARY KEY (category_id),
|
||||||
|
KEY idx_f_news_category_site (site_code, del_flag, is_published, sort_order)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻分类';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻分类';
|
||||||
|
|
||||||
-- ================================================================
|
-- ================================================================
|
||||||
@@ -385,6 +401,7 @@ CREATE TABLE IF NOT EXISTS f_news_category (
|
|||||||
CREATE TABLE IF NOT EXISTS f_news (
|
CREATE TABLE IF NOT EXISTS f_news (
|
||||||
news_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
news_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '主键',
|
||||||
category_id BIGINT NOT NULL COMMENT '所属分类',
|
category_id BIGINT NOT NULL COMMENT '所属分类',
|
||||||
|
site_code VARCHAR(32) NOT NULL DEFAULT 'wuhansaga' COMMENT '站点编码:与分类 site_code 一致,用于多站点数据隔离',
|
||||||
title_zh VARCHAR(200) NOT NULL COMMENT '标题(中文)',
|
title_zh VARCHAR(200) NOT NULL COMMENT '标题(中文)',
|
||||||
title_en VARCHAR(200) NOT NULL COMMENT '标题(英文)',
|
title_en VARCHAR(200) NOT NULL COMMENT '标题(英文)',
|
||||||
excerpt_zh TEXT COMMENT '摘要(中文)',
|
excerpt_zh TEXT COMMENT '摘要(中文)',
|
||||||
@@ -408,6 +425,8 @@ CREATE TABLE IF NOT EXISTS f_news (
|
|||||||
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
remark VARCHAR(500) DEFAULT NULL COMMENT '备注',
|
||||||
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
del_flag TINYINT(1) NOT NULL DEFAULT 0 COMMENT '删除标志:0正常 1删除',
|
||||||
PRIMARY KEY (news_id),
|
PRIMARY KEY (news_id),
|
||||||
|
KEY idx_f_news_site_list (site_code, del_flag, is_published, category_id),
|
||||||
|
KEY idx_f_news_site_time (site_code, del_flag, is_published, create_time),
|
||||||
KEY idx_f_news_category (category_id),
|
KEY idx_f_news_category (category_id),
|
||||||
KEY idx_f_news_create_time (create_time)
|
KEY idx_f_news_create_time (create_time)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻文章';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='新闻文章';
|
||||||
@@ -534,6 +553,14 @@ ALTER TABLE f_single_equipment
|
|||||||
FOREIGN KEY (category_id) REFERENCES f_product_category (product_category_id)
|
FOREIGN KEY (category_id) REFERENCES f_product_category (product_category_id)
|
||||||
ON DELETE CASCADE ON UPDATE CASCADE;
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
|
ALTER TABLE f_product_line_equipment
|
||||||
|
ADD CONSTRAINT fk_f_ple_product_line
|
||||||
|
FOREIGN KEY (product_line_id) REFERENCES f_product_line (product_line_id)
|
||||||
|
ON DELETE CASCADE ON UPDATE CASCADE,
|
||||||
|
ADD CONSTRAINT fk_f_ple_single_equipment
|
||||||
|
FOREIGN KEY (equipment_id) REFERENCES f_single_equipment (single_equipment_id)
|
||||||
|
ON DELETE CASCADE ON UPDATE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE f_spare_part
|
ALTER TABLE f_spare_part
|
||||||
ADD CONSTRAINT fk_f_spare_part_category
|
ADD CONSTRAINT fk_f_spare_part_category
|
||||||
FOREIGN KEY (category_id) REFERENCES f_product_category (product_category_id)
|
FOREIGN KEY (category_id) REFERENCES f_product_category (product_category_id)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ com\wuhansaga\server\entity\CaseStudy.class
|
|||||||
com\wuhansaga\server\WuhanSagaApplication.class
|
com\wuhansaga\server\WuhanSagaApplication.class
|
||||||
com\wuhansaga\server\entity\CompanyInfo.class
|
com\wuhansaga\server\entity\CompanyInfo.class
|
||||||
com\wuhansaga\server\controller\portal\PortalAboutController.class
|
com\wuhansaga\server\controller\portal\PortalAboutController.class
|
||||||
|
com\wuhansaga\server\constant\SiteCodes.class
|
||||||
com\wuhansaga\server\mapper\SingleEquipmentMapper.class
|
com\wuhansaga\server\mapper\SingleEquipmentMapper.class
|
||||||
com\wuhansaga\server\mapper\ProductCategoryMapper.class
|
com\wuhansaga\server\mapper\ProductCategoryMapper.class
|
||||||
com\wuhansaga\server\service\WorkshopService.class
|
com\wuhansaga\server\service\WorkshopService.class
|
||||||
@@ -33,6 +34,7 @@ com\wuhansaga\server\common\GlobalExceptionHandler.class
|
|||||||
com\wuhansaga\server\mapper\NewsCategoryMapper.class
|
com\wuhansaga\server\mapper\NewsCategoryMapper.class
|
||||||
com\wuhansaga\server\controller\admin\AdminMediaController.class
|
com\wuhansaga\server\controller\admin\AdminMediaController.class
|
||||||
com\wuhansaga\server\mapper\ProductMediaMapper.class
|
com\wuhansaga\server\mapper\ProductMediaMapper.class
|
||||||
|
com\wuhansaga\server\config\PortalSiteResolver.class
|
||||||
com\wuhansaga\server\service\CaseCategoryService.class
|
com\wuhansaga\server\service\CaseCategoryService.class
|
||||||
com\wuhansaga\server\service\ProductLineService.class
|
com\wuhansaga\server\service\ProductLineService.class
|
||||||
com\wuhansaga\server\service\SingleEquipmentService.class
|
com\wuhansaga\server\service\SingleEquipmentService.class
|
||||||
@@ -65,6 +67,7 @@ com\wuhansaga\server\service\SparePartService.class
|
|||||||
com\wuhansaga\server\mapper\CoreTechnologyMapper.class
|
com\wuhansaga\server\mapper\CoreTechnologyMapper.class
|
||||||
com\wuhansaga\server\mapper\ProductLineMapper.class
|
com\wuhansaga\server\mapper\ProductLineMapper.class
|
||||||
com\wuhansaga\server\controller\admin\AdminNewsController.class
|
com\wuhansaga\server\controller\admin\AdminNewsController.class
|
||||||
|
com\wuhansaga\server\config\PortalSiteProperties.class
|
||||||
com\wuhansaga\server\controller\admin\AdminSparePartController.class
|
com\wuhansaga\server\controller\admin\AdminSparePartController.class
|
||||||
com\wuhansaga\server\service\NewsService.class
|
com\wuhansaga\server\service\NewsService.class
|
||||||
com\wuhansaga\server\controller\admin\AdminCoreTechnologyController.class
|
com\wuhansaga\server\controller\admin\AdminCoreTechnologyController.class
|
||||||
|
|||||||
@@ -4,9 +4,12 @@ D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com
|
|||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\common\PageResult.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\common\PageResult.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\common\R.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\common\R.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\OpenApiConfig.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\OpenApiConfig.java
|
||||||
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\PortalSiteProperties.java
|
||||||
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\PortalSiteResolver.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\RedisConfig.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\RedisConfig.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\SaTokenConfig.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\SaTokenConfig.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\WebMvcConfig.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\config\WebMvcConfig.java
|
||||||
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\constant\SiteCodes.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\controller\admin\AdminAboutController.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\controller\admin\AdminAboutController.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\controller\admin\AdminAuthController.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\controller\admin\AdminAuthController.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\controller\admin\AdminBannerController.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\controller\admin\AdminBannerController.java
|
||||||
@@ -58,6 +61,7 @@ D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com
|
|||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\NewsCategoryMapper.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\NewsCategoryMapper.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\NewsMapper.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\NewsMapper.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductCategoryMapper.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductCategoryMapper.java
|
||||||
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductLineEquipmentMapper.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductLineMapper.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductLineMapper.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductMediaMapper.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\ProductMediaMapper.java
|
||||||
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\SingleEquipmentMapper.java
|
D:\DeXun_workspace\projects\wuhan-saga-official-website\server\src\main\java\com\wuhansaga\server\mapper\SingleEquipmentMapper.java
|
||||||
|
|||||||
Reference in New Issue
Block a user