Ver Fonte

Dev article category

tsurumure há 8 meses atrás
pai
commit
2e1caf61cb

+ 2 - 2
db/Import/import_win.bat

@@ -7,10 +7,10 @@
 :: Continue? (Press y|Y for Yes, any other key for No) : (y) ::
 
 :: Win10 (Company) ::
-:: set mysql="C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe" ::
+set mysql="C:\Program Files\MySQL\MySQL Server 8.0\bin\mysql.exe"
 
 :: Win11 (Home) ::
-set mysql="D:\Program\MySQL\MySQL Server 8.1\bin\mysql.exe"
+:: set mysql="D:\Program\MySQL\MySQL Server 8.1\bin\mysql.exe" ::
 
 set sql_directory="D:\CodeJava\QuickLaunchSpring\BackendSys\db"
 

+ 6 - 20
db/cms_article_category.sql

@@ -10,29 +10,15 @@ CREATE TABLE `cms_article_category` (
     PRIMARY KEY (`id`),
     `id` BIGINT(10) AUTO_INCREMENT COMMENT 'ID',
     `parent_id` BIGINT(10) DEFAULT '-1' COMMENT '父ID',
-    `category_name` VARCHAR(100) NOT NULL COMMENT '资讯分类名称',
-    `category_description` VARCHAR(500) COMMENT '资讯分类描述',
     `sort` BIGINT(10) DEFAULT '1' COMMENT '排序',
     `status` TINYINT(1) DEFAULT '1' COMMENT '资讯状态 (-1禁用, 1启用)'
 ) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='资讯分类表';
 
-INSERT INTO cms_article_category(parent_id, category_name, category_description, sort) VALUES
-    (-1, '科技创新', '前沿科技与创新动态', 5),
-        (1, 'K1', 'kkkkkkkkk', 1),
-            (2, 'K1-1', 'kkkkkkkkk', 1),
-        (1, 'K2', 'kkkkkkkkk', 7),
-        (1, 'K3', 'kkkkkkkkk', 8),
-        (1, 'K4', 'kkkkkkkkk', 9),
-        (1, 'K5', 'kkkkkkkkk', 10),
-        (1, 'K6', 'kkkkkkkkk', 11),
-        (1, 'K7', 'kkkkkkkkk', 12),
-        (1, 'K8', 'kkkkkkkkk', 13),
-        (1, 'K9', 'kkkkkkkkk', 14),
-        (1, 'K10', 'kkkkkkkkk', 15),
-    (-1, '健康生活', '提升生活质量的健康指南', 4),
-        (13, 'J1', 'jjjjjj', 3),
-    (-1, '情感关系', '为你解析情感与人际关系', 3),
-    (-1, '旅行探索', '探索世界各地的旅行分享', 2),
-    (-1, '美食烹饪', '养眼美食与烹饪技巧', 1)
+INSERT INTO cms_article_category(parent_id, sort) VALUES
+    (-1, 5),
+        (1, 4),
+    (-1, 3),
+    (-1, 2),
+    (-1, 1)
 ;
 

+ 30 - 0
db/cms_article_category_i18n.sql

@@ -0,0 +1,30 @@
+/**
+Source Server Version: 8.0.31
+Source Database: backendsys
+Date: 2023/05/23 17:09:22
+*/
+
+DROP TABLE IF EXISTS `cms_article_category_i18n`;
+
+CREATE TABLE `cms_article_category_i18n` (
+    PRIMARY KEY (`id`),
+    `id` BIGINT(10) AUTO_INCREMENT COMMENT 'ID',
+    `article_category_id` BIGINT(10) NOT NULL COMMENT '分类ID',
+    `language` VARCHAR(10) NOT NULL COMMENT '语种',
+    `category_name` VARCHAR(100) NOT NULL COMMENT '资讯分类名称',
+    `category_description` VARCHAR(500) COMMENT '资讯分类描述'
+) ENGINE=INNODB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='资讯分类表';
+
+INSERT INTO cms_article_category_i18n (article_category_id, language, category_name, category_description) VALUES
+    (1, 'zh', '科技创新', '前沿科技与创新动态'),
+    (1, 'en', 'Technological Innovation', 'Frontier Technology and Innovation Trends'),
+    (2, 'zh', '健康生活', '为你解析情感与人际关系'),
+    (2, 'zh', 'Healthy life', 'For you to analyze emotions and relationships'),
+    (3, 'zh', '情感关系', '为你解析情感与人际关系'),
+    (3, 'en', 'Emotional Relationships', 'Analyze Emotions and Interpersonal Relationships'),
+    (4, 'zh', '旅行探索', '探索世界各地的旅行分享'),
+    (4, 'en', 'Travel Exploration', 'Discover Travel Experiences from Around the World'),
+    (5, 'zh', '美食烹饪', '养眼美食与烹饪技巧'),
+    (5, 'en', 'Culinary Delights', 'Eye-pleasing Dishes and Cooking Techniques')
+;
+

+ 56 - 0
src/main/java/com/backendsys/modules/cms/article/controller/ArticleCategoryController.java

@@ -0,0 +1,56 @@
+package com.backendsys.modules.cms.article.controller;
+
+import com.backendsys.modules.cms.article.entity.ArticleCategory;
+import com.backendsys.modules.cms.article.service.ArticleCategoryService;
+import com.backendsys.modules.common.utils.Result;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+@Validated
+@RestController
+@Tag(name = "资讯分类管理")
+public class ArticleCategoryController {
+
+    @Autowired
+    private ArticleCategoryService articleCategoryService;
+
+    @Operation(summary = "获取资讯分类列表")
+    @PreAuthorize("@ss.hasPermi('10')")
+    @GetMapping("/api/v2/cms/article/getArticleCategory")
+    public Result getArticleCategory(@Validated ArticleCategory articleCategory) {
+        return Result.success().put("data", articleCategoryService.selectArticleCategoryList(articleCategory));
+    }
+
+    @Operation(summary = "获取资讯分类详情")
+    @PreAuthorize("@ss.hasPermi('10.2.1')")
+    @GetMapping("/api/v2/cms/article/getArticleCategoryDetail")
+    public Result getArticleCategoryDetail(@Validated(ArticleCategory.Detail.class) ArticleCategory articleCategory) {
+        return Result.success().put("data", articleCategoryService.selectArticleCategoryDetail(articleCategory));
+    }
+
+    @Operation(summary = "创建资讯分类")
+    @PreAuthorize("@ss.hasPermi('10.2.2')")
+    @PostMapping("/api/v2/cms/article/createArticleCategory")
+    public Result createArticleCategory(@Validated(ArticleCategory.Create.class) @RequestBody ArticleCategory articleCategory) {
+        return Result.success().put("data", articleCategoryService.insertArticleCategory(articleCategory));
+    }
+
+    @Operation(summary = "编辑资讯分类")
+    @PreAuthorize("@ss.hasPermi('10.2.3')")
+    @PutMapping("/api/v2/cms/article/updateArticleCategory")
+    public Result updateArticleCategory(@Validated(ArticleCategory.Update.class) @RequestBody ArticleCategory articleCategory) {
+        return Result.success().put("data", articleCategoryService.updateArticleCategory(articleCategory));
+    }
+
+    @Operation(summary = "删除资讯分类")
+    @PreAuthorize("@ss.hasPermi('10.2.4')")
+    @DeleteMapping("/api/v2/cms/article/deleteArticleCategory")
+    public Result deleteArticleCategory(@Validated(ArticleCategory.Delete.class) @RequestBody ArticleCategory articleCategory) {
+        return Result.success().put("data", articleCategoryService.deleteArticleCategory(articleCategory));
+    }
+
+}

+ 5 - 0
src/main/java/com/backendsys/modules/cms/article/dao/ArticleCategoryDao.java

@@ -4,6 +4,11 @@ import com.backendsys.modules.cms.article.entity.ArticleCategory;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import org.apache.ibatis.annotations.Mapper;
 
+import java.util.List;
+import java.util.Map;
+
 @Mapper
 public interface ArticleCategoryDao extends BaseMapper<ArticleCategory> {
+    List<ArticleCategory> selectArticleCategoryList(ArticleCategory articleCategory);
+    Map<String, Object> selectArticleCategoryDetail(ArticleCategory articleCategory);
 }

+ 15 - 0
src/main/java/com/backendsys/modules/cms/article/dao/ArticleCategoryI18nDao.java

@@ -0,0 +1,15 @@
+package com.backendsys.modules.cms.article.dao;
+
+import com.backendsys.modules.cms.article.entity.ArticleCategoryI18n;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+@Mapper
+public interface ArticleCategoryI18nDao extends BaseMapper<ArticleCategoryI18n> {
+
+    int insertBatch(List<ArticleCategoryI18n> translations);
+    int updateBatch(List<ArticleCategoryI18n> translations);
+
+}

+ 0 - 1
src/main/java/com/backendsys/modules/cms/article/dao/ArticleDao.java

@@ -9,7 +9,6 @@ import java.util.Map;
 
 @Mapper
 public interface ArticleDao extends BaseMapper<Article> {
-
     List<Article> selectArticleList(Article article);
     Map<String, Object> selectArticleDetail(Article article);
 }

+ 14 - 5
src/main/java/com/backendsys/modules/cms/article/entity/ArticleCategory.java

@@ -6,12 +6,13 @@ import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
-import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
 import lombok.Data;
 import org.hibernate.validator.constraints.Range;
 
+import java.util.List;
+
 @Data
 @TableName("cms_article_category")
 public class ArticleCategory {
@@ -21,17 +22,25 @@ public class ArticleCategory {
     public static interface Update{}
     public static interface Delete{}
 
+    @TableField(exist = false)
+    private String lang;
+
     @TableId(type = IdType.AUTO)
     private Long id;
     @TableField("id")
     @NotNull(message="article_category_id 不能为空", groups = { Detail.class, Update.class })
     private Long article_category_id;
     private Long parent_id;
-    @Size(max = 20, message = "资讯分类名称长度不超过 {max} 字符", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class})
-    @NotBlank(message="资讯分类名称不能为空", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class, })
+
+    @TableField(exist = false)
     private String category_name;
-    @Size(max = 200, message = "资讯分类描述长度不超过 {max} 字符", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class})
+    @TableField(exist = false)
     private String category_description;
+
+    @TableField(exist = false)
+    @NotEmpty(message="内容不能为空", groups = { Create.class, Update.class})
+    private List<ArticleCategoryI18n> translations;
+
     @Range(min = 1, max = 9999, message = "排序必须在 {min} 到 {max} 之间", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class})
     private Integer sort;
     @RangeArray(message="状态取值有误,范围应是(-1禁用, 1启用)", value = {"-1", "1"}, groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class})

+ 39 - 0
src/main/java/com/backendsys/modules/cms/article/entity/ArticleCategoryI18n.java

@@ -0,0 +1,39 @@
+package com.backendsys.modules.cms.article.entity;
+
+import com.backendsys.entity.Cms.CmsArticleCategoryDTO;
+import com.backendsys.entity.validator.RangeArray;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+import org.hibernate.validator.constraints.Range;
+
+@Data
+@TableName("cms_article_category_i18n")
+public class ArticleCategoryI18n {
+
+    public static interface Detail{}
+    public static interface Create{}
+    public static interface Update{}
+    public static interface Delete{}
+
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    @TableField("id")
+    @NotNull(message="article_category_id 不能为空", groups = { Detail.class, Update.class })
+    private Long article_category_id;
+    @NotEmpty(message="语言不能为空")
+    private String language;
+
+    @Size(max = 20, message = "资讯分类名称长度不超过 {max} 字符", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class})
+    @NotBlank(message="资讯分类名称不能为空", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class, })
+    private String category_name;
+    @Size(max = 200, message = "资讯分类描述长度不超过 {max} 字符", groups = {CmsArticleCategoryDTO.Create.class, CmsArticleCategoryDTO.Update.class})
+    private String category_description;
+}

+ 2 - 0
src/main/java/com/backendsys/modules/cms/article/entity/ArticleI18n.java

@@ -13,10 +13,12 @@ import lombok.Data;
 public class ArticleI18n {
     @TableId(type = IdType.AUTO)
     private Long id;
+
     @NotNull(message="article_id 不能为空")
     private Long article_id;
     @NotEmpty(message="语言不能为空")
     private String language;
+
     @Size(max = 100, message = "资讯标题长度不超过 {max} 字符")
     @NotEmpty(message="资讯标题不能为空")
     private String title;

+ 7 - 0
src/main/java/com/backendsys/modules/cms/article/service/ArticleCategoryI18nService.java

@@ -0,0 +1,7 @@
+package com.backendsys.modules.cms.article.service;
+
+import com.backendsys.modules.cms.article.entity.ArticleCategoryI18n;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+public interface ArticleCategoryI18nService {
+}

+ 16 - 2
src/main/java/com/backendsys/modules/cms/article/service/ArticleCategoryService.java

@@ -1,7 +1,21 @@
 package com.backendsys.modules.cms.article.service;
 
 import com.backendsys.modules.cms.article.entity.ArticleCategory;
-import com.baomidou.mybatisplus.extension.service.IService;
+import com.backendsys.utils.response.PageEntity;
+
+import java.util.Map;
+
+public interface ArticleCategoryService {
+
+    // 获取资讯列表
+    PageEntity selectArticleCategoryList(ArticleCategory article);
+    // 获取资讯详情
+    Map<String, Object> selectArticleCategoryDetail(ArticleCategory article);
+    // 创建资讯
+    Map<String, Object> insertArticleCategory(ArticleCategory article);
+    // 编辑资讯
+    Map<String, Object> updateArticleCategory(ArticleCategory article);
+    // 删除资讯
+    Map<String, Object> deleteArticleCategory(ArticleCategory article);
 
-public interface ArticleCategoryService extends IService<ArticleCategory> {
 }

+ 8 - 0
src/main/java/com/backendsys/modules/cms/article/service/impl/ArticleCategoryI18nServiceImpl.java

@@ -0,0 +1,8 @@
+package com.backendsys.modules.cms.article.service.impl;
+
+import com.backendsys.modules.cms.article.service.ArticleCategoryI18nService;
+import org.springframework.stereotype.Service;
+
+@Service
+public class ArticleCategoryI18nServiceImpl implements ArticleCategoryI18nService {
+}

+ 109 - 1
src/main/java/com/backendsys/modules/cms/article/service/impl/ArticleCategoryServiceImpl.java

@@ -1,11 +1,119 @@
 package com.backendsys.modules.cms.article.service.impl;
 
+import cn.hutool.core.util.IdUtil;
+import com.backendsys.exception.CustException;
 import com.backendsys.modules.cms.article.dao.ArticleCategoryDao;
+import com.backendsys.modules.cms.article.dao.ArticleCategoryDao;
+import com.backendsys.modules.cms.article.dao.ArticleCategoryI18nDao;
+import com.backendsys.modules.cms.article.entity.ArticleCategory;
 import com.backendsys.modules.cms.article.entity.ArticleCategory;
+import com.backendsys.modules.cms.article.entity.ArticleCategoryI18n;
 import com.backendsys.modules.cms.article.service.ArticleCategoryService;
+import com.backendsys.modules.common.config.security.utils.HttpRequestUtil;
+import com.backendsys.utils.response.PageEntity;
+import com.backendsys.utils.response.PageInfoResult;
+import com.backendsys.utils.v2.PageUtils;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 @Service
-public class ArticleCategoryServiceImpl extends ServiceImpl<ArticleCategoryDao, ArticleCategory> implements ArticleCategoryService {
+public class ArticleCategoryServiceImpl implements ArticleCategoryService {
+
+    @Autowired
+    private ArticleCategoryDao articleCategoryDao;
+    @Autowired
+    private ArticleCategoryI18nDao articleCategoryI18nDao;
+
+    /**
+     * 获取资讯分类列表
+     */
+    @Override
+    public PageEntity selectArticleCategoryList(ArticleCategory article) {
+        PageUtils.startPage();  // 分页
+        List<ArticleCategory> list = articleCategoryDao.selectArticleCategoryList(article);
+        return new PageInfoResult(list).toEntity();
+    }
+
+    /**
+     * 获取资讯分类详情
+     */
+    @Override
+    public Map<String, Object> selectArticleCategoryDetail(ArticleCategory article) {
+        Map<String, Object> detail = articleCategoryDao.selectArticleCategoryDetail(article);
+        if (detail == null) throw new CustException("资讯分类不存在");
+        return detail;
+    }
+
+    /**
+     * 创建资讯分类
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> insertArticleCategory(ArticleCategory articleCategory) {
+        
+        // 插入
+        articleCategoryDao.insert(articleCategory);
+
+        Long article_category_id = articleCategory.getId();
+
+        // 批量插入 (翻译字段)
+        List<ArticleCategoryI18n> translations = articleCategory.getTranslations().stream()
+            .map(t -> { t.setArticle_category_id(article_category_id); return t; })
+            .collect(Collectors.toList());
+        articleCategoryI18nDao.insertBatch(translations);
+
+        return Map.of("article_category_id", article_category_id);
+    }
+
+    /**
+     * 编辑资讯分类
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> updateArticleCategory(ArticleCategory articleCategory) {
+
+        Long article_category_id = articleCategory.getArticle_category_id();
+
+        ArticleCategory detail = articleCategoryDao.selectById(article_category_id);
+        if (detail == null) throw new CustException("资讯分类不存在");
+
+        // 更新
+        articleCategory.setId(article_category_id);
+        articleCategoryDao.updateById(articleCategory);
+
+        // 批量更新 (翻译字段)
+        List<ArticleCategoryI18n> translations = articleCategory.getTranslations().stream()
+                .map(t -> { t.setArticle_category_id(article_category_id); return t; })
+                .collect(Collectors.toList());
+        articleCategoryI18nDao.updateBatch(translations);
+
+        return Map.of("article_category_id", article_category_id);
+    }
+
+
+    /**
+     * 删除资讯分类
+     */
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> deleteArticleCategory(ArticleCategory articleCategory) {
+
+        Long article_category_id = articleCategory.getArticle_category_id();
+
+        ArticleCategory articleDetail = articleCategoryDao.selectById(article_category_id);
+        if (articleDetail == null) throw new CustException("资讯分类不存在");
+
+        articleCategoryDao.deleteById(article_category_id);
+        articleCategoryI18nDao.delete(new QueryWrapper<ArticleCategoryI18n>().eq("article_category_id", article_category_id));
+
+        return Map.of("article_category_id", article_category_id);
+    }
+
 }

+ 2 - 2
src/main/java/com/backendsys/modules/cms/article/service/impl/ArticleServiceImpl.java

@@ -111,8 +111,8 @@ public class ArticleServiceImpl implements ArticleService {
 
         Long article_id = article.getArticle_id();
 
-        Article articleDetail = articleDao.selectById(article_id);
-        if (articleDetail == null) throw new CustException("资讯不存在");
+        Article detail = articleDao.selectById(article_id);
+        if (detail == null) throw new CustException("资讯不存在");
 
         articleDao.deleteById(article_id);
         articleI18nDao.delete(new QueryWrapper<ArticleI18n>().eq("article_id", article_id));

+ 98 - 0
src/main/resources/mapper/cms/article/ArticleCategoryDao.xml

@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.backendsys.modules.cms.article.dao.ArticleCategoryDao">
+
+    <sql id="includeArticleCategory">
+        ac.id id,
+        ac.id article_category_id,
+        ac.parent_id,
+        act.category_name category_name,
+        COALESCE(act.category_description, '') category_description,
+        ac.sort,
+        ac.status
+    </sql>
+    <sql id="includeArticleCategoryDetail">
+        ac.id id,
+        ac.id article_category_id,
+        ac.parent_id,
+        ac.sort,
+        ac.status
+    </sql>
+
+    <sql id="includeArticleCategoryTranslation">
+        id,
+        article_category_id,
+        language,
+        category_name,
+        COALESCE(category_description, '') category_description
+    </sql>
+
+    <sql id="leftJoinTranslations">
+        LEFT JOIN cms_article_category_i18n act ON ac.id = act.article_category_id
+    </sql>
+
+    <resultMap id="resultMapArticleCategory" type="java.util.LinkedHashMap">
+        <id property="id" column="id" jdbcType="BIGINT" />
+        <result property="article_category_id" column="article_category_id" javaType="java.lang.Long" />
+        <result property="parent_id" column="parent_id" javaType="java.lang.Long" />
+        <result property="category_name" column="category_name" />
+        <result property="category_description" column="category_description" />
+        <result property="sort" column="sort" javaType="java.lang.Integer" />
+        <result property="status" column="status" javaType="java.lang.Integer" />
+    </resultMap>
+
+    <resultMap id="resultMapArticleCategoryDetail" type="java.util.LinkedHashMap">
+        <id property="id" column="id" jdbcType="BIGINT" />
+        <result property="article_category_id" column="article_category_id" javaType="java.lang.Long" />
+        <result property="parent_id" column="parent_id" javaType="java.lang.Long" />
+        <result property="sort" column="sort" javaType="java.lang.Integer" />
+        <result property="status" column="status" javaType="java.lang.Integer" />
+        <collection property="translations" javaType="java.util.List"
+            select="queryTranslationsById" column="id">
+            <result property="category_name" column="category_name" />
+            <result property="category_description" column="category_description" />
+        </collection>
+    </resultMap>
+
+
+    <!-- 查 列表 -->
+    <select id="selectArticleCategoryList" resultMap="resultMapArticleCategory">
+        SELECT <include refid="includeArticleCategory" /> FROM cms_article_category ac
+        <include refid="leftJoinTranslations" />
+        <where>
+            act.language = #{lang}
+            <if test="category_name != null and category_name != ''">
+                AND act.category_name LIKE CONCAT('%', #{category_name}, '%')
+            </if>
+        </where>
+    </select>
+
+    <!-- 查 详情 -->
+    <select id="selectArticleCategoryDetail" resultMap="resultMapArticleCategoryDetail">
+        SELECT <include refid="includeArticleCategoryDetail" />
+        FROM cms_article_category ac
+        <where>
+            <if test="article_category_id != null and article_category_id != ''">
+                AND ac.id = #{article_category_id}
+            </if>
+        </where>
+    </select>
+
+    <!-- 查 翻译详情 (子查询) -->
+    <select id="queryTranslationsById" resultType="java.util.LinkedHashMap">
+        SELECT <include refid="includeArticleCategoryTranslation" />
+        FROM cms_article_category_i18n
+        WHERE article_category_id = #{id}
+    </select>
+
+    <!-- 查 详情 (公共) (带翻译 Object) (关联查询) -->
+<!--    <select id="queryArticleCategoryDetailPublic" resultMap="resultMapArticleCategory">-->
+<!--        SELECT <include refid="includeArticleCategory" />, content-->
+<!--        FROM cms_article_category a-->
+<!--        <include refid="leftJoinCategory" />-->
+<!--        <include refid="leftJoinUser" />-->
+<!--        <include refid="leftJoinTranslations" />-->
+<!--        WHERE a.uid = #{uid} AND act.language = #{lang}-->
+<!--    </select>-->
+
+</mapper>

+ 34 - 0
src/main/resources/mapper/cms/article/ArticleCategoryI18nDao.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.backendsys.modules.cms.article.dao.ArticleCategoryI18nDao">
+
+    <!-- 批量插入 -->
+    <insert id="insertBatch" parameterType="java.util.List">
+        INSERT INTO cms_article_category_i18n (
+            article_category_id, language, category_name, category_description
+        )
+        VALUES
+        <foreach collection="translations" item="item" separator=",">
+        (
+            #{item.article_category_id}, #{item.language}, #{item.category_name}, #{item.category_description}
+        )
+        </foreach>
+    </insert>
+
+    <!-- 批量更新 -->
+    <update id="updateBatch" parameterType="com.backendsys.modules.cms.article.entity.ArticleCategoryI18n">
+        <foreach collection="translations" item="item" separator=";">
+            UPDATE cms_article_category_i18n
+            <set>
+                <trim suffixOverrides="," suffix=" ">
+                    category_name = #{item.category_name},
+                    <if test="item.category_description != null and item.category_description != ''">
+                        category_description = #{item.category_description},
+                    </if>
+                </trim>
+            </set>
+            WHERE article_category_id = #{item.article_category_id} AND language = #{item.language}
+        </foreach>
+    </update>
+
+</mapper>