Explorar el Código

新增模板引擎

tsurumure hace 8 meses
padre
commit
baaf89f42e
Se han modificado 70 ficheros con 1581 adiciones y 133 borrados
  1. 1 1
      src/main/java/com/backendsys/exception/GlobalExceptionHandler.java
  2. 112 0
      src/main/java/com/backendsys/modules/cms/article/controller/AppArticleController.java
  3. 4 0
      src/main/java/com/backendsys/modules/cms/article/entity/ArticleI18n.java
  4. 0 1
      src/main/java/com/backendsys/modules/cms/article/service/impl/ArticleServiceImpl.java
  5. 9 0
      src/main/java/com/backendsys/modules/common/config/WebConfig.java
  6. 61 60
      src/main/java/com/backendsys/modules/common/config/security/CorsConfig.java
  7. 5 4
      src/main/java/com/backendsys/modules/common/config/security/SecurityConfig.java
  8. 11 10
      src/main/java/com/backendsys/modules/common/config/security/filter/JwtAuthenticationFilter.java
  9. 0 2
      src/main/resources/application-local.yml
  10. 0 2
      src/main/resources/application-prod.yml
  11. 34 8
      src/main/resources/application.yml
  12. 0 45
      src/main/resources/mapper/cms.article/ArticleDao.xml
  13. 399 0
      src/main/resources/static/css/default.css
  14. 274 0
      src/main/resources/static/css/public.css
  15. 17 0
      src/main/resources/static/css/reset.css
  16. BIN
      src/main/resources/static/images/favicon.ico
  17. 1 0
      src/main/resources/static/images/icon-ce.svg
  18. BIN
      src/main/resources/static/images/icon-menu.png
  19. 1 0
      src/main/resources/static/images/icon-product.svg
  20. BIN
      src/main/resources/static/images/icon-search-white.png
  21. 1 0
      src/main/resources/static/images/icon-video.svg
  22. 1 0
      src/main/resources/static/images/icon-watch.svg
  23. 0 0
      src/main/resources/static/images/icon-wechat.svg
  24. BIN
      src/main/resources/static/images/index-banner.jpg
  25. BIN
      src/main/resources/static/images/index-section-1.jpg
  26. BIN
      src/main/resources/static/images/index-section-2.jpg
  27. BIN
      src/main/resources/static/images/logo.png
  28. BIN
      src/main/resources/static/images/nav-active.png
  29. BIN
      src/main/resources/static/images/p1.jpg
  30. BIN
      src/main/resources/static/images/qrcode-wechat.jpg
  31. BIN
      src/main/resources/static/images/sub-banner.jpg
  32. 43 0
      src/main/resources/static/js/default.js
  33. 2 0
      src/main/resources/static/js/plugins/jquery.cookie.min.js
  34. 1 0
      src/main/resources/static/js/plugins/jquery.min.js
  35. 0 0
      src/main/resources/static/js/plugins/layui/css/layui.css
  36. 1 0
      src/main/resources/static/js/plugins/layui/css/modules/code.css
  37. 0 0
      src/main/resources/static/js/plugins/layui/css/modules/laydate/default/laydate.css
  38. BIN
      src/main/resources/static/js/plugins/layui/css/modules/layer/default/icon-ext.png
  39. BIN
      src/main/resources/static/js/plugins/layui/css/modules/layer/default/icon.png
  40. 0 0
      src/main/resources/static/js/plugins/layui/css/modules/layer/default/layer.css
  41. BIN
      src/main/resources/static/js/plugins/layui/css/modules/layer/default/loading-0.gif
  42. BIN
      src/main/resources/static/js/plugins/layui/css/modules/layer/default/loading-1.gif
  43. BIN
      src/main/resources/static/js/plugins/layui/css/modules/layer/default/loading-2.gif
  44. BIN
      src/main/resources/static/js/plugins/layui/font/iconfont.eot
  45. 25 0
      src/main/resources/static/js/plugins/layui/font/iconfont.svg
  46. BIN
      src/main/resources/static/js/plugins/layui/font/iconfont.ttf
  47. BIN
      src/main/resources/static/js/plugins/layui/font/iconfont.woff
  48. BIN
      src/main/resources/static/js/plugins/layui/font/iconfont.woff2
  49. 0 0
      src/main/resources/static/js/plugins/layui/layui.js
  50. 14 0
      src/main/resources/static/js/plugins/swiper/swiper.min.css
  51. 14 0
      src/main/resources/static/js/plugins/swiper/swiper.min.js
  52. 97 0
      src/main/resources/templates/__article.html
  53. 24 0
      src/main/resources/templates/__layout/head.html
  54. 73 0
      src/main/resources/templates/__layout/layout-footer.html
  55. 61 0
      src/main/resources/templates/__layout/layout-header.html
  56. 8 0
      src/main/resources/templates/__layout/layout-top.html
  57. 10 0
      src/main/resources/templates/__layout/layout.html
  58. 3 0
      src/main/resources/templates/article.html
  59. 68 0
      src/main/resources/templates/articleDetail.html
  60. 20 0
      src/main/resources/templates/components/language.html
  61. 22 0
      src/main/resources/templates/components/search-input.html
  62. 2 0
      src/main/resources/templates/components/sub-banner.html
  63. 16 0
      src/main/resources/templates/error.html
  64. 88 0
      src/main/resources/templates/index.html
  65. 8 0
      src/main/resources/templates/layout/head.html
  66. 3 0
      src/main/resources/templates/layout/layout-footer.html
  67. 3 0
      src/main/resources/templates/layout/layout-header.html
  68. 3 0
      src/main/resources/templates/layout/layout-top.html
  69. 10 0
      src/main/resources/templates/layout/layout.html
  70. 31 0
      src/main/resources/templates/page.html

+ 1 - 1
src/main/java/com/backendsys/exception/GlobalExceptionHandler.java

@@ -293,7 +293,7 @@ public class GlobalExceptionHandler implements ResponseBodyAdvice<Object> {
     @ExceptionHandler(NoHandlerFoundException.class)
     public Result handleNoHandlerFoundException(NoHandlerFoundException e) {
         System.out.println("****** NoHandlerFoundException.class: ******");
-        printErrorException(e, true);
+        printErrorException(e, false);
         return Result.error(ResultEnum.INTERNAL_ERROR.getCode(), e.getMessage());
     }
 

+ 112 - 0
src/main/java/com/backendsys/modules/cms/article/controller/AppArticleController.java

@@ -0,0 +1,112 @@
+package com.backendsys.modules.cms.article.controller;
+
+import com.backendsys.modules.common.config.security.annotations.Anonymous;
+import jakarta.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 关于我们
+ */
+@Controller
+public class AppArticleController {
+
+//    @Autowired
+//    private CmsSiteInfoService cmsSiteInfoService;
+//    @Autowired
+//    private CmsNavigationService cmsNavigationService;
+//    @Autowired
+//    private CmsArticleService articleService;
+//    @Autowired
+//    private CmsArticleCategoryService articleCategoryService;
+
+//    @Anonymous
+    @GetMapping({"/article"})
+    public String article(Model model, HttpServletRequest request,
+        @RequestParam(value = "page_num", defaultValue = "1") Integer pageNum,
+        @RequestParam(value = "page_size", defaultValue = "10") Integer pageSize,
+        @RequestParam(value = "title", required = false) String title,
+        @RequestParam(value = "category_id", required = false) Long categoryId
+    ) {
+
+//        // -- 初始化公共事件 ---------------------------------------------
+//        RequestUtil.initResponse(model, request, cmsSiteInfoService, cmsNavigationService);
+//        String lang = (String) model.getAttribute("lang");
+//        // -- Header ---------------------------------------------
+//        model.addAttribute("title", "zh".equals(lang) ? "资讯中心": "Aricle");
+//        // -------------------------------------------------------
+//
+//        // [Get] 资讯列表
+//        CmsArticleDTO cmsArticleDTO = new CmsArticleDTO();
+//        cmsArticleDTO.setTitle(title);
+//        cmsArticleDTO.setCategory_id(categoryId);
+//        cmsArticleDTO.setLang(lang);
+//        Map<String, Object> articleList = articleService.queryArticle(pageNum, pageSize, cmsArticleDTO);
+//        model.addAttribute("article", articleList);
+//
+//        // [Get] 资讯分类
+//        List<Map<String, Object>> categoryList = articleCategoryService.queryArticleCategoryActive();
+//        String categoryName = null;
+//        if ("zh".equals(lang)) {
+//            categoryName = (String) categoryList.stream()
+//                    .filter(cate -> cate.get("id").equals(categoryId))
+//                    .map(cate -> cate.get("category_name"))
+//                    .findFirst().orElse(null);
+//        }
+//        if ("en".equals(lang)) {
+//            categoryName = (String) categoryList.stream()
+//                    .filter(cate -> cate.get("id").equals(categoryId))
+//                    .map(cate -> cate.get("category_name_en"))
+//                    .findFirst().orElse(null);
+//        }
+//
+//
+//        model.addAttribute("isBrand", true);
+//        model.addAttribute("articleCategory", categoryList);
+//
+//        Map<String, Object> parameters = new LinkedHashMap<>();
+//        parameters.put("title", title);
+//        parameters.put("category_id", categoryId);
+//        parameters.put("category_name", categoryName);
+//        model.addAttribute("parameters", parameters);
+
+        System.out.println("article layout!");
+
+        // -- Layout ---------------------------------------------
+        model.addAttribute("layout", "article");
+        return "layout/layout";
+    }
+
+
+//    @GetMapping({"/articleDetail/{id}"})
+//    public String articleDetail(Model model, HttpServletRequest request, @PathVariable("id") Long id) {
+//
+//        // -- 初始化公共事件 ---------------------------------------------
+//        RequestUtil.initResponse(model, request, cmsSiteInfoService, cmsNavigationService);
+//        // -- Header ---------------------------------------------
+//        model.addAttribute("title","资讯中心");
+//        // -------------------------------------------------------
+//
+//        // [Get] 资讯详情
+//        CmsArticleDTO cmsArticleDTO = new CmsArticleDTO();
+//        cmsArticleDTO.setArticle_id(id);
+//        cmsArticleDTO.setLang((String) model.getAttribute("lang"));
+//
+//        Map<String, Object> detail = articleService.queryArticleDetailPublic(cmsArticleDTO);
+//        model.addAttribute("articleDetail", detail);
+//
+//        // [Get] 资讯分类
+//        model.addAttribute("articleCategory", articleCategoryService.queryArticleCategoryActive());
+//
+//        // -- Layout ---------------------------------------------
+//        model.addAttribute("layout", "articleDetail");
+//        return "layout/layout";
+//    }
+
+}

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

@@ -1,5 +1,7 @@
 package com.backendsys.modules.cms.article.entity;
 
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
 import jakarta.validation.constraints.NotEmpty;
 import jakarta.validation.constraints.NotNull;
@@ -9,6 +11,8 @@ import lombok.Data;
 @Data
 @TableName("cms_article_i18n")
 public class ArticleI18n {
+    @TableId(type = IdType.AUTO)
+    private Long id;
     @NotNull(message="article_id 不能为空")
     private Long article_id;
     @NotEmpty(message="语言不能为空")

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

@@ -10,7 +10,6 @@ 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.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;

+ 9 - 0
src/main/java/com/backendsys/modules/common/config/WebConfig.java

@@ -5,6 +5,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
 @Configuration
@@ -20,4 +21,12 @@ public class WebConfig implements WebMvcConfigurer {
         // [拦截器] API日志
         if (API_LOG) registry.addInterceptor(apiLogInterceptor);
     }
+
+    // 静态资源映射
+    @Override
+    public void addResourceHandlers(ResourceHandlerRegistry registry) {
+        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
+        registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/static/images/");
+    }
+
 }

+ 61 - 60
src/main/java/com/backendsys/modules/common/config/security/CorsConfig.java

@@ -1,65 +1,66 @@
-package com.backendsys.modules.common.config.security;
-
-import com.backendsys.config.Interceptor.PreAuthorizeInterceptor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.core.Ordered;
-import org.springframework.web.cors.CorsConfiguration;
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
-import org.springframework.web.filter.CorsFilter;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-public class CorsConfig implements WebMvcConfigurer {
-
+//package com.backendsys.modules.common.config.security;
+//
+//import com.backendsys.config.Interceptor.PreAuthorizeInterceptor;
+//import org.springframework.beans.factory.annotation.Autowired;
+//import org.springframework.beans.factory.annotation.Value;
+//import org.springframework.boot.web.servlet.FilterRegistrationBean;
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.core.Ordered;
+//import org.springframework.web.cors.CorsConfiguration;
+//import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+//import org.springframework.web.filter.CorsFilter;
+//import org.springframework.web.servlet.config.annotation.CorsRegistry;
+//import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+//import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+//
+//@Configuration
+//public class CorsConfig implements WebMvcConfigurer {
+//
+////    @Autowired
+////    private TranslationInterceptor translationInterceptor;
+////
+////    @Override
+////    public void addInterceptors(InterceptorRegistry registry) {
+////        registry.addInterceptor(translationInterceptor).addPathPatterns("/**");
+////    }
+//
 //    @Autowired
-//    private TranslationInterceptor translationInterceptor;
+//    private PreAuthorizeInterceptor preAuthorizeInterceptor;
 //
 //    @Override
 //    public void addInterceptors(InterceptorRegistry registry) {
-//        registry.addInterceptor(translationInterceptor).addPathPatterns("/**");
+//        registry.addInterceptor(preAuthorizeInterceptor)
+//            .addPathPatterns("/**")
+//            .excludePathPatterns("/swagger-ui/**")
+//            .excludePathPatterns("/images/**")
+//            .excludePathPatterns("/favicon.ico")
+//        ;
+//    }
+//
+//    @Override
+//    public void addCorsMappings(CorsRegistry registry) {
+//        registry.addMapping("/**")
+//            .allowedOriginPatterns("*")
+//            .allowedMethods("GET", "POST", "PUT", "DELETE")
+//            .allowedHeaders("*")
+//            .allowCredentials(true)
+//            .maxAge(3600)
+//            .exposedHeaders("Authorization");
+//    }
+//
+//    @Bean
+//    public FilterRegistrationBean<CorsFilter> corsFilter() {
+//        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+//        CorsConfiguration config = new CorsConfiguration();
+//        config.addAllowedOriginPattern("*");
+//        config.addAllowedHeader("*");
+//        config.addAllowedMethod("*");
+//        config.setAllowCredentials(true);
+//        config.setMaxAge(3600L);
+//        source.registerCorsConfiguration("/**", config);
+//        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
+//        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
+//        return bean;
 //    }
-
-    @Autowired
-    private PreAuthorizeInterceptor preAuthorizeInterceptor;
-
-    @Override
-    public void addInterceptors(InterceptorRegistry registry) {
-
-        registry.addInterceptor(preAuthorizeInterceptor)
-                .addPathPatterns("/**")
-                .excludePathPatterns("/swagger-ui/**")
-        ;
-
-    }
-
-    @Override
-    public void addCorsMappings(CorsRegistry registry) {
-        registry.addMapping("/**")
-            .allowedOriginPatterns("*")
-            .allowedMethods("GET", "POST", "PUT", "DELETE")
-            .allowedHeaders("*")
-            .allowCredentials(true)
-            .maxAge(3600)
-            .exposedHeaders("Authorization");
-    }
-
-    @Bean
-    public FilterRegistrationBean<CorsFilter> corsFilter() {
-        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
-        CorsConfiguration config = new CorsConfiguration();
-        config.addAllowedOriginPattern("*");
-        config.addAllowedHeader("*");
-        config.addAllowedMethod("*");
-        config.setAllowCredentials(true);
-        config.setMaxAge(3600L);
-        source.registerCorsConfiguration("/**", config);
-        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
-        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
-        return bean;
-    }
-}
+//}

+ 5 - 4
src/main/java/com/backendsys/modules/common/config/security/SecurityConfig.java

@@ -85,10 +85,11 @@ public class SecurityConfig {
             // 设置白名单
             .authorizeHttpRequests((authorizeHttpRequests) ->
                 authorizeHttpRequests
-                    .requestMatchers(whiteUrls).permitAll()
-                    .requestMatchers(anonymousUrls).permitAll()
-                    .anyRequest().authenticated()
-//                    .anyRequest().permitAll() // 开放所有
+//                    .requestMatchers("/api/**").permitAll()
+//                    .requestMatchers(whiteUrls).permitAll()
+//                    .requestMatchers(anonymousUrls).permitAll()
+//                    .anyRequest().authenticated()
+                    .anyRequest().permitAll() // 开放所有mvc页面
             )
 
             // "/api/auth/login",

+ 11 - 10
src/main/java/com/backendsys/modules/common/config/security/filter/JwtAuthenticationFilter.java

@@ -70,24 +70,20 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
      * 校验路径是否是要忽略鉴权路径
      * @param url
      */
-    private boolean checkUrl(String url){
+    private boolean isPassWithRule(String url){
 
-        // 使用了 @Anonymous 注解的地址
+        // 使用了 @Anonymous 注解的地址不需要鉴权
         String[] anonymousUrls = anonymousProperties.getUrls();
-        // System.out.println("(JwtAuthenticationFilter) anonymousUrls:");
-        // System.out.println(Arrays.toString(anonymousUrls));
 
         // 在配置文件中的 白名单地址
         String[] whiteUrls = ArrayUtil.addAll(JWT_WHITELIST, STATIC_WHITELIST, anonymousUrls);
 
         for (String item : whiteUrls) {
             String method = item.toString().trim();
-            if (Arrays.asList("/**", "**").contains(method)) {
-                return false;
-            }
+            if (Arrays.asList("/**", "**").contains(method)) return false;
             if (method.endsWith("/**")) {
                 String prefix = method.substring(0, method.length() - 3);
-                 if (url.startsWith(prefix + "/")) {  // 模糊匹配
+                if (url.startsWith(prefix + "/")) {
                     return true;
                 }
             } else if (url.equals(method.toString().trim())) {
@@ -100,12 +96,17 @@ public class JwtAuthenticationFilter extends OncePerRequestFilter {
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, MalformedJwtException {
 
-        // 获取当前请求的URI,检查是否放行
-        if (checkUrl(request.getRequestURI())) {
+        // -- 放行 ------------------------------------------------------------------------------
+        // - 获取当前请求的URI,检查是否放行 (白名单)
+        // - 如果不是 /api 路由,则直接放行
+        Boolean isNotAPIUrI = !request.getRequestURI().startsWith("/api");
+        if (isPassWithRule(request.getRequestURI()) || isNotAPIUrI) {
             filterChain.doFilter(request, response);
             return;
         }
 
+        // -- 鉴权 ------------------------------------------------------------------------------
+
         // [Header][拦截] 从请求头中获取认证信息
         final String authHeader = request.getHeader("Authorization");
         if(authHeader == null || !authHeader.startsWith("Bearer ")) {

+ 0 - 2
src/main/resources/application-local.yml

@@ -40,8 +40,6 @@ spring:
       host: 127.0.0.1
       port: 6388
       password: 123456
-  mvc:
-    static-path-pattern: /uploads/**
 
 
 springdoc:

+ 0 - 2
src/main/resources/application-prod.yml

@@ -40,8 +40,6 @@ spring:
       host: 172.19.0.7
       port: 6388
       password: p1FM!fkfPdBQ%@5o
-  mvc:
-    static-path-pattern: /uploads/**
 
 
 springdoc:

+ 34 - 8
src/main/resources/application.yml

@@ -15,13 +15,9 @@ spring:
   mvc:
     async:
       request-timeout: 600000           # 接口超时时间,默认 60 秒
+    static-path-pattern: /uploads/**
     throw-exception-if-no-handler-found: true
-  web:
-    resources:
-      add-mappings: false               # (false) 禁用静态资源反射
-  data:
-    redis:
-      timeout: 3000ms
+
 #      lettuce:
 #        pool:
 #          max-active: 20    # 最大连接数,负值表示没有限制,默认8
@@ -29,6 +25,38 @@ spring:
 #          max-idle: 8       # 最大空闲连接,默认8
 #          min-idle: 0       # 最小空闲连接,默认0
 
+  web:
+    resources:
+      static-locations: classpath:/static/
+      # (false) 禁用静态资源反射
+      add-mappings: true
+#      add-mappings: false
+
+  thymeleaf:
+    # 开启视图解析
+    enabled: true
+    #编码格式
+    encoding: UTF-8
+    #前缀配置
+    prefix: classpath:/templates/
+    # 后缀配置
+    suffix: .html
+    #是否使用缓存 开发环境时不设置缓存
+    cache: false
+    # 格式为 HTML 格式
+    mode: HTML
+    # 配置类型
+    servlet:
+      content-type: text/html
+
+#  messages:
+#    basename: i18n/locale
+
+
+
+
+
+
 # MyBatis ORM
 #mybatis:
 mybatis-plus:
@@ -97,10 +125,8 @@ whitelist:
     /api/webhook,
     /api/public/**,
     /api/v2/public/**,
-    
     /api/system/auth/**,
     /api/v2/system/auth/**,
-    
     /api/b2c/member/auth/**,
     /api/test/**,
     /ws/**,

+ 0 - 45
src/main/resources/mapper/cms.article/ArticleDao.xml

@@ -130,7 +130,6 @@
         WHERE article_id = #{id}
     </select>
 
-
     <!--&lt;!&ndash; 查 详情 (公共) (带翻译 Object) (关联查询) &ndash;&gt;-->
     <!--<select id="queryArticleDetailPublic" resultMap="resultMapArticle">-->
     <!--    SELECT <include refid="includeArticle" />, content-->
@@ -141,49 +140,5 @@
     <!--    WHERE a.id = #{article_id} AND at.language = #{lang}-->
     <!--</select>-->
 
-    <!--<update id="updateArticle" parameterType="com.backendsys.entity.Cms.CmsArticleDTO"-->
-    <!--        useGeneratedKeys="true" keyProperty="article_id">-->
-    <!--    UPDATE cms_article-->
-    <!--    SET-->
-    <!--    category_id = #{category_id}-->
-    <!--    <if test="meta_keyword != null and meta_keyword != ''">, meta_keyword = #{meta_keyword}</if>-->
-    <!--    <if test="meta_description != null and meta_description != ''">, meta_description = #{meta_description}</if>-->
-    <!--    <if test="status != null and status != ''">, status = #{status}</if>-->
-    <!--    <if test="is_top != null and is_top != ''">, is_top = #{is_top}</if>-->
-    <!--    WHERE id = #{article_id};-->
-
-    <!--    <foreach collection="translations" item="translation" separator=";">-->
-    <!--        UPDATE cms_article_i18n-->
-    <!--        <set>-->
-    <!--            title = #{translation.title},-->
-    <!--            content = #{translation.content},-->
-    <!--            <if test="translation.description != null and translation.description != ''">-->
-    <!--                description = #{translation.description}-->
-    <!--            </if>-->
-    <!--        </set>-->
-    <!--        WHERE article_id = ${article_id} AND language = #{translation.language}-->
-    <!--    </foreach>-->
-
-    <!--</update>-->
-    <!--&lt;!&ndash; <if test="audit_status != null and audit_status != ''">, audit_status = #{audit_status}</if> &ndash;&gt;-->
-
-    <!--&lt;!&ndash; 删除 &ndash;&gt;-->
-    <!--<delete id="deleteArticle" parameterType="java.lang.Long">-->
-    <!--    DELETE FROM cms_article WHERE id = #{article_id};-->
-    <!--    DELETE FROM cms_article_i18n WHERE article_id = #{article_id};-->
-    <!--</delete>-->
-
-    <!--&lt;!&ndash; 删除 (批量) &ndash;&gt;-->
-    <!--<delete id="deleteArticleBatch" parameterType="java.lang.Long">-->
-    <!--    DELETE FROM cms_article WHERE id IN-->
-    <!--    <foreach collection="ids" item="id" open="(" separator="," close=")">-->
-    <!--        #{id}-->
-    <!--    </foreach>;-->
-
-    <!--    DELETE FROM cms_article_i18n WHERE article_id IN-->
-    <!--    <foreach collection="ids" item="id" open="(" separator="," close=")">-->
-    <!--        #{id}-->
-    <!--    </foreach>;-->
-    <!--</delete>-->
 
 </mapper>

+ 399 - 0
src/main/resources/static/css/default.css

@@ -0,0 +1,399 @@
+/**
+ * This style power by Mure.Yang (2024/05/11)
+ 
+ - Colors:
+    - black { color: rgb(31 41 55); }
+    - gray { color: rgb(156 163 175); }
+    - red { color: rgb(220 38 38); }
+    - green { color: rgb(22 163 74); }
+    - blue, .link, a.link { color: rgb(59 130 246); }
+    - prima { color: #e5ac00; }
+ */
+
+.hjcl-layout-top {
+    height: 35px; border-bottom: 1px solid #e8e8e8;
+    display: flex; justify-content: space-between;
+}
+.hjcl-layout-top > .wrapper { display: flex; align-items: center; justify-content: space-between; }
+
+.hjcl-layout-header {
+    position: relative; height: 100px;
+    display: flex; justify-content: space-between;
+}
+.hjcl-layout-header > .wrapper {
+    display: flex; align-items: center; justify-content: center;
+}
+.hjcl-layout-header .header-logo { display: block; height: 46px; margin: 0 40px;}
+
+.hjcl-layout-header .nav-menu,
+.hjcl-layout-header .nav-right-bar { display: none; }
+
+.hjcl-layout-header .nav { display: flex; align-items: center; }
+.hjcl-layout-header .nav-mask { display: none; }
+.hjcl-layout-header .nav-mask.active { display: block; }
+.hjcl-layout-header .nav li {
+    position: relative; font-size: 16px; margin: 0 40px;
+    display: flex; align-items: center; justify-content: center;
+    height: 100px;
+}
+.hjcl-layout-header .nav li.first-nav-item { display: none; }
+.hjcl-layout-header .nav li.middle-l { margin-right: 100px; }
+.hjcl-layout-header .nav li.middle-r { margin-left: 100px; }
+
+.hjcl-layout-header .nav li a { display: block; padding: 15px 0;color: #444; }
+.hjcl-layout-header .nav li a:hover,
+.hjcl-layout-header .nav li a.active {
+    color: #e5ac00; text-decoration: none;
+    background: url("/images/nav-active.png") no-repeat center bottom;
+}
+
+.hjcl-layout-header .nav li .navSub {
+    display: none;
+    position: absolute; left: 50%; top: 101px; z-index: 9901; background: #fff;
+    width: 100px; max-height: 300px; overflow-y: scroll;
+    margin-left: -50px; text-align: center; font-size: 14px;
+}
+.hjcl-layout-header .nav li:hover .navSub { display: block; }
+.hjcl-layout-header .nav li .navSub a { padding: 10px 0; background: none; }
+
+.hjcl-layout-header .nav li .nav-more { display: none; }
+
+.header-logo-link {
+    position: absolute; top: 50%; left: 50%;
+    display: flex; align-items: center; justify-content: center;
+    width: 120px; height: 46px; margin-top: -23px; margin-left: -60px;
+}
+
+
+.hjcl-layout-container {}
+
+/* 首页 */
+/*height: 500px;*/
+.index-banner { position: relative; max-height: 500px; background: rgba(42, 49, 57, 1); }
+.index-banner .swiper-slide { background: transparent; }
+.index-banner .swiper-pagination { bottom: 20px; }
+.index-banner .swiper-pagination .swiper-pagination-bullet { width: 12px; height: 12px; }
+.index-banner .swiper-pagination .swiper-pagination-bullet.swiper-pagination-bullet-active {
+    background: #e5ac00;
+}
+
+.index-banner .banner-img { max-width: 1440px; max-height: 500px; }
+
+
+
+
+
+
+.hjcl-layout-footer { color: #777; height: 80px; font-size: 12px; background: #2a3138; transition: color 0.3s; }
+.hjcl-layout-footer a { color: #777; }
+.hjcl-layout-footer a:hover { color: #aaa; }
+
+.index-search-bar {
+    position: absolute; top: 0; left: 0; right: 0; bottom: 0;
+    z-index: 10; width: 450px; height: 40px; margin: auto;
+    box-sizing: border-box;
+    padding-top: 35px;
+}
+.index-search {
+    display: flex; justify-content: space-between; align-items: center;
+    width: 100%; height: 40px;
+    border-radius: 20px; background: #fff;
+}
+.index-search .index-search-input {
+    width: 100%;
+    font-size: 16px;
+    margin: 0 18px;
+    border: 0;
+}
+.index-search .index-search-btn {
+    display: flex; align-items: center; justify-content: center;
+    width: 60px; height: 36px; margin-right: 2px; border-radius: 18px; background: #f4c231;
+    transition: background-color 0.3s;
+}
+.index-search .index-search-btn:hover { background: #dbaf2c; }
+.index-search .index-search-btn:active { background: #c29b27; }
+
+.icon-search-white {
+    display: block;
+    width: 16px;
+    height: 16px;
+    background: url("/images/icon-search-white.png") no-repeat;
+}
+
+.sub-banner {
+    width: 100%;
+    height: 120px;
+    background: url("/images/sub-banner.jpg") repeat-x;
+}
+
+.article-list { margin-top: 10px; }
+.article-list .article-item {
+    display: flex; justify-content: space-between;
+    margin-bottom: 10px; padding: 20px; box-sizing: border-box;
+    background: #fff;
+}
+.article-list .article-item .article-thumb img { display: block; width: 220px; height: 220px; }
+
+.article-info { position: relative; width: 440px; height: 220px; padding: 10px 0; box-sizing: border-box; }
+.article-info .article-info-title { display: block; font-size: 18px; color: #333e46; margin-bottom: 10px; }
+.article-info .article-info-title:hover { color: #e5ac00; }
+.article-info .article-info-description {
+    font-size: 14px; color: #aaa; line-height: 24px;
+    display: -webkit-box; overflow: hidden; text-overflow: -o-ellipsis-lastline;
+    -webkit-line-clamp: 5; -webkit-box-orient: vertical; text-overflow: ellipsis;
+}
+.article-info .article-info-bottom { position: absolute; bottom: 0; width: 100%; display: flex; align-items: center; justify-content: space-between; }
+.article-info .article-info-time { font-size: 12px; color: #aaa; }
+.article-info .article-info-btn {
+    display: flex; align-items: center; justify-content: center;
+    height: 32px; padding: 0 16px; border-radius: 16px;
+    font-size: 12px; color: #fff; background: #333e46; transition: background-color 0.3s;
+}
+.article-info .article-info-btn:hover { background-color: #45545e; }
+.article-info .article-info-btn:active { background-color: #3c4852; }
+
+
+
+/* 新闻列表布局 一行三列 */
+.article-list.column { overflow: hidden; }
+.article-list.column .article-item { display: block; float: left; width: 220px; margin: 0 10px 20px; }
+.article-list.column .article-item .article-thumb img { width: 180px; height: 180px; }
+.article-list.column .article-item .article-info { width: auto; height: auto; padding-bottom: 0; }
+.article-list.column .article-item .article-info .article-info-title {
+    font-size: 14px; margin-bottom: 5px;
+    text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
+}
+.article-list.column .article-item .article-info .article-info-bottom { display: none; }
+.article-list.column .article-item .article-info .article-info-description { font-size: 12px; line-height: 18px; height: 36px; -webkit-line-clamp: 2; }
+/* **************** */
+
+
+
+.article-detail {}
+.article-detail-title { display: flex; align-items: end; margin-bottom: 10px; }
+.article-detail-subtitle {
+    display: flex; align-items: center; justify-content: space-between;
+    font-size: 14px; color: #aaa;
+}
+
+.article-video-bar { text-align: center; }
+.article-video { width: 500px; height: 320px; margin: 20px auto; }
+
+.article-category ul li { margin-bottom: 20px; }
+.article-category ul li:last-child { margin-bottom: 0; }
+.article-category ul li a.active { color: #e5ac00; font-weight: bold; }
+
+.article-category.horizontal ul li { display: inline-block; margin: 0 10px 10px 0; }
+
+.index-section { padding: 30px 0; }
+.index-section-hd { margin-bottom: 20px; display: flex; justify-content: space-between; align-items: center }
+.index-section-hd .index-section-title { position: relative; padding-left: 20px; box-sizing: border-box; }
+.index-section-hd .index-section-title:before {
+    display: block; content: ''; width: 4px; height: 100%; background: #f4c231;
+    position: absolute; left: 0; top: 0;
+}
+.index-section-hd .index-section-title .index-section-maintitle { font-size: 18px; }
+.index-section-hd .index-section-title .index-section-subtitle { font-size: 12px; color: #aaa; }
+.index-section-hd index-section-more a { font-size: 14px; color: #aaa; }
+
+.index-article-list { overflow: hidden; }
+.index-article-list .index-article-item { float: left; width: 250px; margin: 10px; }
+.index-article-list .index-article-item a { display: block; text-align: center; }
+.index-article-list .index-article-item .article-item-thumb { display: block; width: 250px; height: 250px; text-align: center; }
+.index-article-list .index-article-item .article-item-title { margin-top: 10px; font-size: 14px; line-height: 18px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
+
+.footer-menutabs {
+    display: none; align-items: center; background: #2a3138;
+    position: fixed; bottom: 0; z-index: 6000; width: 100%; height: 60px;
+}
+.footer-menutabs .footer-menutabs-item {
+    flex: 1; text-align: center; font-size: 12px; color: #fff;
+    height: 60px; padding: 8px 0; box-sizing: border-box;
+    transition: background-color 0.3s;
+}
+.footer-menutabs .footer-menutabs-item > img { display: block; width: 22px; height: 22px; margin: 0 auto 5px; }
+.footer-menutabs .footer-menutabs-item:active,
+.footer-menutabs .footer-menutabs-item.active { background: #21262b; }
+
+@media (max-width: 1199px) {
+    .hjcl-layout-header, .hjcl-layout-header .nav li { height: 80px; }
+    .hjcl-layout-header .nav li .navSub { top: 81px; }
+
+    .header-logo-link, .hjcl-layout-header .header-logo { height: 40px; }
+    .header-logo-link { margin-top: -20px; }
+    .hjcl-layout-header .nav li { font-size: 14px; }
+    .hjcl-layout-header .nav li.middle-l { margin-right: 80px; }
+    .hjcl-layout-header .nav li.middle-r { margin-left: 80px; }
+
+
+    .index-article-list .index-article-item { width: 210px; }
+    .index-article-list .index-article-item .article-item-thumb { width: 210px; height: 210px; }
+
+
+
+    .index-banner, .index-banner .banner-img { max-height: 400px; }
+    .index-search-bar { padding-top: 30px; }
+    .sub-banner { height: 100px; }
+
+    .article-list .article-item .article-thumb img { width: 180px; height: 180px; }
+    .article-info { width: 360px; height: 180px; }
+
+    .article-list.column .article-item { width: 180px; padding: 10px; }
+    .article-list.column .article-item .article-thumb img { width: 160px; height: 160px; }
+}
+@media (max-width: 960px) {
+    .hjcl-layout-header, .hjcl-layout-header .nav li { height: 60px; }
+    .hjcl-layout-header .nav li .navSub { top: 61px; }
+
+    .header-logo-link, .hjcl-layout-header .header-logo { height: 30px; }
+    .header-logo-link { margin-top: -15px; }
+    .hjcl-layout-header .nav li { margin: 0 20px; }
+    .hjcl-layout-header .nav li.middle-l { margin-right: 60px; }
+    .hjcl-layout-header .nav li.middle-r { margin-left: 60px; }
+    .hjcl-layout-header .nav li a:hover, .hjcl-layout-header .nav li a.active { background: none; }
+
+    .index-article-list .index-article-item { width: 160px; }
+    .index-article-list .index-article-item .article-item-thumb { width: 160px; height: 160px; }
+
+    .index-banner, .index-banner .banner-img { max-height: 300px; }
+    .index-search-bar { padding-top: 30px; }
+    .index-search .index-search-input { font-size: 14px; }
+    .sub-banner { height: 80px; }
+
+    .article-category ul li { margin-bottom: 10px; }
+    .article-list .article-item .article-thumb img { width: 140px; height: 140px; }
+    .article-info { width: 280px; height: 140px; }
+    .article-info .article-info-title { font-size: 16px; }
+    .article-info .article-info-btn { height: 32px; padding: 0 16px; }
+    .article-info .article-info-description { -webkit-line-clamp: 2; }
+
+    .article-list.column .article-item { width: 220px; }
+    .article-list.column .article-item .article-thumb img { width: 200px; height: 200px; }
+
+    .article-detail-subtitle, .sub-section-container .sub-section-container-title a { font-size: 12px; }
+    .article-video { width: 400px; height: 280px;}
+}
+@media (max-width: 767px) {
+
+    body { padding-top: 60px; }
+    .hjcl-layout-top { display: none; }
+
+    .hjcl-layout-header, .hjcl-layout-header .nav { position: fixed; z-index: 8000; width: 100%; background: #fff; }
+    .hjcl-layout-header { top: 0; z-index: 8001; }
+
+
+
+    .hjcl-layout-header .nav-right-bar,
+    .hjcl-layout-header .nav-menu {
+        position: absolute; display: block;
+    }
+    .hjcl-layout-header .nav-menu {
+        left: 20px; cursor: pointer; opacity: 0.4; transition: opacity 0.3;
+        width: 24px; height: 24px; background: url("/images/icon-menu.png") no-repeat; background-size: 100%;
+    }
+
+    .hjcl-layout-header .nav-right-bar {
+        right: 10px;
+    }
+    .hjcl-layout-header .nav-menu:hover { opacity: 0.6; }
+    .hjcl-layout-header .nav-menu:active, .hjcl-layout-header .nav-menu.active { opacity: 0.8; }
+
+
+    /* 移动端导航 上下排版 */
+    /*.hjcl-layout-header .nav {*/
+    /*    top: 60px; z-index: 8000; display: block; border-top: 1px solid #eee; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);*/
+    /*    height: 0; opacity: 0; transition: height 0.3s, opacity 0.3s;*/
+    /*}*/
+    /*.hjcl-layout-header .nav.active { height: auto; opacity: 1; }*/
+    /*.hjcl-layout-header .nav.active li { display: block; }*/
+
+    /* 移动端导航 左右排版 */
+    .hjcl-layout-header .nav {
+        display: none;
+        top: 0; left: 0;
+        /*width: 220px;*/
+        width: 75%;
+        height: 100vh; z-index: 9900;
+    }
+    .hjcl-layout-header .nav.active { display: block; }
+
+    .hjcl-layout-header .nav li.first-nav-item,
+    .hjcl-layout-header .nav.active li.first-nav-item {
+        display: flex; align-items: center; justify-content: start;
+        height: 60px; font-size: 18px; font-weight: bold;
+        padding: 0 20px; box-sizing: border-box;
+    }
+
+    .hjcl-layout-header .nav-mask {
+        position: fixed; left: 0; top: 0; z-index: 9899;
+        width: 100%; height: 100%; background: rgba(0, 0, 0, 0.5);
+    }
+    /*display: flex; align-items: center; justify-content: space-between;*/
+    .hjcl-layout-header .nav li,
+    .hjcl-layout-header .nav.active li { display: block; height: auto; }
+    .hjcl-layout-header .nav li a { padding: 5px 0; }
+    .hjcl-layout-header .nav li:hover .navSub { display: none; }
+    .hjcl-layout-header .nav li.active .navSub { display: block; }
+    .hjcl-layout-header .nav li .nav-more {
+        display: flex; align-items: center; justify-content: center;
+        width: 22px; cursor: pointer; font-size: 18px;
+    }
+
+    .hjcl-layout-header .nav li {
+        display: none; border-bottom: 1px solid #eee; margin: 0;
+        padding: 15px 20px; box-sizing: border-box;
+        font-size: 16px;
+    }
+    .hjcl-layout-header .nav li:last-child { border-bottom: 0; }
+    .hjcl-layout-header .nav li.middle-l, .hjcl-layout-header .nav li.middle-r { margin: 0; }
+    .hjcl-layout-header .nav li a:hover, .hjcl-layout-header .nav li a.active { background: none; }
+
+    .hjcl-layout-header .nav li .navSub { display: none; }
+    .hjcl-layout-header .nav li .navSub.active { display: block; }
+
+    .hjcl-layout-header .nav li .navSub, .hjcl-layout-header .nav li:hover .navSub {
+        position: initial; width: 100%; text-align: left;
+        margin-left: 0; padding: 10px 0; margin-bottom: 15px;
+        font-size: 14px;
+    }
+    .hjcl-layout-header .nav li .navSub a { padding: 10px 0; }
+
+
+
+
+    .hjcl-layout-top > .wrapper { padding: 0 15px; box-sizing: border-box; }
+
+    .index-banner, .index-banner .banner-img { max-height: 200px; }
+    .index-search-bar { display: none; padding-top: 0; }
+    .index-search .index-search-input { font-size: 12px; }
+    .sub-banner { height: 60px; }
+
+    .index-section { padding: 20px; }
+    .index-section-hd .index-section-title .index-section-maintitle { font-size: 16px; }
+    .index-section-hd .index-section-more { font-size: 12px; }
+    .index-subbanner { display: none; }
+
+    .index-article-list .index-article-item { width: 50%; margin: 0 0 10px; padding: 0 10px; box-sizing: border-box; }
+    .index-article-list .index-article-item .article-item-thumb { width: 100%; height: 100%; }
+
+    .article-list .article-item { padding: 10px; }
+    .article-list .article-item .article-thumb { float: left; }
+    .article-list .article-item .article-thumb img { width: 80px; height: 80px; }
+    .article-info { float: left; width: 100%; height: auto; margin-left: -80px; padding: 0 0 0 90px; box-sizing: border-box; }
+    .article-info .article-info-title { margin-bottom: 5px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
+    .article-info .article-info-description { -webkit-line-clamp: 1; }
+    .article-info .article-info-btn { display: none; }
+
+    .article-list.column .article-item { display: flex; float: none; width: 100%; justify-content: start; }
+    .article-list.column .article-item .article-thumb img { width: 80px; height: 80px; }
+    .article-list.column .article-item .article-info .article-info-description { -webkit-line-clamp: 3; }
+
+    .hjcl-layout-footer { height: 35px; }
+    .hjcl-layout-footer .footer-nav { display: none; }
+
+    .article-video { width: 80%; max-height: 280px;}
+}
+@media (max-width: 479px) {
+    body { padding-bottom: 60px; }
+    .footer-menutabs { display: flex; }
+}

+ 274 - 0
src/main/resources/static/css/public.css

@@ -0,0 +1,274 @@
+/**
+ * This style power by Mure.Yang (2024/05/11)
+ * Get a lite style from tailwindcss3!
+ * https://tailwindcss.com/doc
+ */
+
+::selection { background: #444; color: #fff; }
+
+::-webkit-input-placeholder{ color:#ccc !important; }
+::-moz-placeholder{ color:#ccc !important; }
+:-ms-input-placeholder { color:#ccc !important; } /* ie */
+input:-moz-placeholder { color:#ccc !important; }
+
+::-webkit-scrollbar { width: 14px; height: 14px; }
+::-webkit-scrollbar-track, ::-webkit-scrollbar-thumb { border-radius: 999px; border: 5px solid transparent; }
+::-webkit-scrollbar-track { box-shadow: 1px 1px 5px rgba(0,0,0,.2) inset; }
+::-webkit-scrollbar-thumb { min-height: 20px; background-clip: content-box; box-shadow: 0 0 0 5px rgba(0,0,0,.2) inset; }
+::-webkit-scrollbar-corner { background: transparent; }
+
+.wrapper { width: 1080px; margin: auto; }
+
+.sub-section-main { padding: 40px 0; box-sizing: border-box; background: #f8f8f8; }
+.sub-section-main .wrapper { display: flex; justify-content: space-between; }
+
+.sub-section-container { width: 720px; }
+.sub-section-container .sub-section-container-title { font-size: 24px; margin-bottom: 10px; }
+.sub-section-container .sub-section-container-title a { font-size: 14px; }
+.sub-section-container .sub-section-container-content { }
+.sub-section-container .sub-section-container-content .content-detail { padding: 10px 0; }
+.sub-section-container .sub-section-container-description {
+    padding: 10px; box-sizing: border-box;
+    font-size: 12px; line-height: 18px; color: #aaa; background: #eee;
+}
+
+.sub-section-sider { width: 330px; }
+.sub-section-sider .sub-section-sider-title { display: flex; align-items: center; height: 24px; font-size: 16px; font-weight: bold; margin-bottom: 18px; }
+.sub-section-sider .sub-section-sider-content { padding: 20px; box-sizing: border-box; background: #fff; }
+
+.sub-search { margin-top: 15px; margin-bottom: 15px; }
+
+.float-left { float: left; }
+.float-right { float: right; }
+.float-none { float: none; }
+.clear-both { clear: both; }
+
+.flex { display: flex; }
+.flex-auto { flex: 1 1 auto; }
+.flex-none { flex: none; }
+
+.block { display: block; }
+.inline-block { display: inline-block; }
+.inline { display: inline; }
+
+.items-start { align-items: flex-start; }
+.items-end { align-items: flex-end; }
+.items-center { align-items: center; }
+
+.justify-start { justify-content: flex-start; }
+.justify-end { justify-content: flex-end; }
+.justify-center { justify-content: center; }
+.justify-between { justify-content: space-between; }
+
+.grow { flex-grow: 1; }
+
+.text-black { color: rgb(31 41 55); }
+.text-gray { color: rgb(156 163 175); }
+.text-red { color: rgb(220 38 38); }
+.text-green { color: rgb(22 163 74); }
+.text-blue, .link, a.link { color: rgb(59 130 246); }
+
+.underline { text-decoration-line: underline; }
+.underline-hover:hover { text-decoration-line: underline; }
+.decoration-2 { text-decoration-thickness: 2px; }
+.underline-offset-2 { text-underline-offset: 2px; }
+.underline-offset-4 { text-underline-offset: 4px; }
+.underline-offset-8 { text-underline-offset: 8px; }
+.line-through { text-decoration-line: line-through; }
+
+.bg-transparent { background-color: transparent; }
+.bg-white { background-color: #fff; }
+
+.box-border { box-sizing: border-box; }
+
+.text-xs {
+    font-size: 0.75rem; /* 12px */
+    line-height: 1rem; /* 16px */
+}
+.text-sm {
+    font-size: 0.875rem; /* 14px */
+    line-height: 1.25rem; /* 20px */
+}
+.text-base {
+    font-size: 1rem; /* 16px */
+    line-height: 1.5rem; /* 24px */
+}
+.text-lg {
+    font-size: 1.125rem; /* 18px */
+    line-height: 1.75rem; /* 28px */
+}
+.text-xl {
+    font-size: 1.25rem; /* 20px */
+    line-height: 1.75rem; /* 28px */
+}
+.text-2xl {
+    font-size: 1.5rem; /* 24px */
+    line-height: 2rem; /* 32px */
+}
+
+.leading-3 { line-height: .75rem; /* 12px */ }
+.leading-6 { line-height: 1.5rem; /* 24px */ }
+
+.text-left { text-align: left; }
+.text-center { text-align: center; }
+.text-right { text-align: right; }
+.text-justify { text-align: justify; }
+
+.text-ellipsis { text-overflow: ellipsis; white-space: nowrap; overflow: hidden; }
+.line-clamp-2 {
+    display: -webkit-box; overflow: hidden; text-overflow: -o-ellipsis-lastline;
+    text-overflow: ellipsis; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
+}
+.overflow-hidden { overflow: hidden; }
+
+.font-sans { font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; }
+.font-serif { font-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; }
+.font-mono { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; }
+
+.font-normal { font-weight: 400; }
+.font-bold { font-weight: 700; }
+
+.rounded { border-radius: 0.25rem; /* 4px */ }
+.rounded-lg { border-radius: 0.5rem; /* 8px */ }
+.rounded-xl { border-radius: 0.75rem; /* 12px */ }
+
+.border { border-width: 1px; }
+.border-t { border-top-width: 1px; }
+.border-b { border-bottom-width: 1px; }
+.border-l { border-left-width: 1px; }
+.border-r { border-right-width: 1px; }
+.border-gray { border-color: rgb(209 213 219); }
+.border-solid { border-style: solid; }
+
+.outline-0 { outline-width: 0px; }
+
+.shadow { box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); }
+
+.opacity-0 { opacity: 0; }
+.opacity-25 { opacity: 0.25; }
+.opacity-50 { opacity: 0.5; }
+.opacity-75 { opacity: 0.75; }
+.opacity-100 { opacity: 1; }
+
+.w-full { width: 100%; }
+.w-64 { width: 16rem; /* 256px */ }
+
+.h-full { height: 100%; }
+
+/* Margin */
+
+.m-auto { margin: auto; }
+.m-0 { margin: 0px; }
+
+.m-1 { margin: 0.25rem; /* 4px */ }
+.mx-1 { margin-left: 0.25rem; margin-right: 0.25rem; }
+.my-1 { margin-top: 0.25rem; margin-bottom: 0.25rem; }
+.mt-1 { margin-top: 0.25rem; /* 4px */ }
+.mb-1 { margin-bottom: 0.25rem; /* 4px */ }
+.ml-1 { margin-left: 0.25rem; /* 4px */ }
+.mr-1 { margin-right: 0.25rem; /* 4px */ }
+
+.m-2 { margin: 0.5rem; /* 8px */ }
+.mx-2 { margin-left: 0.5rem; margin-right: 0.5rem; }
+.my-2 { margin-top: 0.5rem; margin-bottom: 0.5rem; }
+.mt-2 { margin-top: 0.5rem; /* 8px */ }
+.mb-2 { margin-bottom: 0.5rem; /* 8px */ }
+.ml-2 { margin-left: 0.5rem; /* 8px */ }
+.mr-2 { margin-right: 0.5rem; /* 8px */ }
+
+.m-3 { margin: 0.75rem; /* 12px */ }
+.mx-3 { margin-left: 0.75rem; margin-right: 0.75rem; }
+.my-3 { margin-top: 0.75rem; margin-bottom: 0.75rem; }
+.mt-3 { margin-top: 0.75rem; /* 12px */ }
+.mb-3 { margin-bottom: 0.75rem; /* 12px */ }
+.ml-3 { margin-left: 0.75rem; /* 12px */ }
+.mr-3 { margin-right: 0.75rem; /* 12px */ }
+
+.m-4 { margin: 1rem; /* 16px */ }
+.mx-4 { margin-left: 1rem; margin-right: 1rem; }
+.my-4 { margin-top: 1rem; margin-bottom: 1rem; }
+.mt-4 { margin-top: 1rem; /* 16px */ }
+.mb-4 { margin-bottom: 1rem; /* 16px */ }
+.ml-4 { margin-left: 1rem; /* 16px */ }
+.mr-4 { margin-right: 1rem; /* 16px */ }
+
+/* Padding */
+
+.p-0 { padding: 0px; }
+.p-1 { padding: 0.25rem; /* 4px */ }
+.px-1 { padding-left: 0.25rem; padding-right: 0.25rem; }
+.py-1 { padding-top: 0.25rem; padding-bottom: 0.25rem; }
+.pt-1 { padding-top: 0.25rem; /* 4px */ }
+.pb-1 { padding-bottom: 0.25rem; /* 4px */ }
+.pl-1 { padding-left: 0.25rem; /* 4px */ }
+.pr-1 { padding-right: 0.25rem; /* 4px */ }
+
+.p-2 { padding: 0.5rem; /* 8px */ }
+.px-2 { padding-left: 0.5rem; padding-right: 0.5rem; }
+.py-2 { padding-top: 0.5rem; padding-bottom: 0.5rem; }
+.pt-2 { padding-top: 0.5rem; /* 8px */ }
+.pb-2 { padding-bottom: 0.5rem; /* 8px */ }
+.pl-2 { padding-left: 0.5rem; /* 8px */ }
+.pr-2 { padding-right: 0.5rem; /* 8px */ }
+
+.p-3 { padding: 0.75rem; /* 12px */ }
+.px-3 { padding-left: 0.75rem; padding-right: 0.75rem; }
+.py-3 { padding-top: 0.75rem; padding-bottom: 0.75rem; }
+.pt-3 { padding-top: 0.75rem; /* 12px */ }
+.pb-3 { padding-bottom: 0.75rem; /* 12px */ }
+.pl-3 { padding-left: 0.75rem; /* 12px */ }
+.pr-3 { padding-right: 0.75rem; /* 12px */ }
+
+.p-4 { padding: 1rem; /* 16px */ }
+.px-4 { padding-left: 1rem; padding-right: 1rem; }
+.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
+.pt-4 { padding-top: 1rem; /* 16px */ }
+.pb-4 { padding-bottom: 1rem; /* 16px */ }
+.pl-4 { padding-left: 1rem; /* 16px */ }
+.pr-4 { padding-right: 1rem; /* 16px */ }
+
+.swiper-container {
+    width: 100%;
+    height: 100%;
+}
+.swiper-slide {
+    text-align: center;
+    font-size: 18px;
+    background: #fff;
+    display: -webkit-box;
+    display: -ms-flexbox;
+    display: -webkit-flex;
+    display: flex;
+    -webkit-box-pack: center;
+    -ms-flex-pack: center;
+    -webkit-justify-content: center;
+    justify-content: center;
+    -webkit-box-align: center;
+    -ms-flex-align: center;
+    -webkit-align-items: center;
+    align-items: center;
+}
+
+
+@media (max-width: 1199px) {
+    .wrapper { width: 920px; }
+    .sub-section-container { width: 600px; }
+    .sub-section-sider { width: 300px; }
+    .sub-section-container .sub-section-container-title { font-size: 18px; }
+}
+@media (max-width: 960px) {
+    .wrapper { width: 720px; }
+    .sub-section-main { padding: 30px 0; }
+    .sub-section-container { width: 480px; }
+    .sub-section-sider { width: 220px; }
+}
+@media (max-width: 767px) {
+    .wrapper { width: 100%; }
+    .sub-section-main { padding: 20px; }
+    .sub-section-main .wrapper { display: block; }
+    .sub-section-container, .sub-section-sider { width: 100%; }
+    .sub-section-container { margin-bottom: 20px; }
+    .sub-section-container .sub-section-container-title { font-size: 16px; font-weight: bold; }
+    .sub-section-sider .sub-section-sider-title { margin-bottom: 10px; }
+}
+@media (max-width: 479px) {}

+ 17 - 0
src/main/resources/static/css/reset.css

@@ -0,0 +1,17 @@
+/* This style power by Mure.Yang (2024/05/11) */
+blockquote,body,button,caption,dd,div,dl,dt,fieldset,figure,form,h1,h2,h3,h4,h5,h6,hr,html,input,legend,li,menu,ol,p,pre,table,td,textarea,th,ul{margin:0;padding:0;}
+address,article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block;}
+table{border-collapse:collapse;border-spacing:0;}
+caption,th{text-align:left;font-weight:400;}
+abbr,body,fieldset,html,iframe,img{border:0;}
+address,cite,dfn,em,i,var{font-style:normal;}
+[hidefocus],summary{outline:0;}
+li{list-style:none;}
+code,kbd,pre,samp{font-family:inherit;}
+q:after,q:before{content:none;}
+textarea{overflow:auto;resize:none;}
+label,summary{cursor:default;}
+a,button{cursor:pointer;}
+b,h1,h2,h3,h4,h5,h6,strong{font-weight:700;}
+a,a:hover{text-decoration:none;}
+body,button,input,keygen,legend,select,textarea{outline:0;}

BIN
src/main/resources/static/images/favicon.ico


+ 1 - 0
src/main/resources/static/images/icon-ce.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723654101176" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1390" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M935.57333333 658.88c-10.56-17.28-23.52-33.12-38.4-46.56-14.88-14.4-31.68-26.88-49.44-36.96l30.24-29.28c23.52 0 46.56 7.2 65.28 21.12 14.4 17.76 22.08 39.84 21.6 62.88l-29.28 28.8m-269.76 262.56h-91.2V833.6l11.04-10.56c19.68 9.12 37.92 21.12 53.76 36.48 15.36 14.88 28.32 32.16 37.92 51.36l-11.52 10.56m244.32-238.56l-206.88 202.08c-11.04-18.24-24.48-34.56-39.84-48.96-15.36-14.88-33.12-27.84-51.84-38.4l210.72-199.2c18.72 8.64 36 20.16 51.36 34.56 15.36 14.4 27.36 31.2 36.48 49.92m-428.16 152.64c43.68-57.6 93.12-110.4 147.36-157.92H272.69333333c-18.24 0.48-33.6-13.44-34.56-32.16-0.48-18.24 13.44-33.6 32.16-34.56h405.6c6.24 0 12 1.44 17.28 4.32 70.08-67.2 138.24-131.04 169.44-160.32v-302.4c-0.96-41.28-35.04-73.92-75.84-72.96h-609.6c-40.8 0-74.88 32.16-75.84 73.44v718.08c0.96 41.28 35.04 73.44 75.84 72.96h304.8c0.48-40.32 0.48-93.12 0-108.48m-244.8-540c0.48-18.72 15.84-33.6 34.56-33.12h405.12c18.24-0.48 33.6 13.44 34.56 32.16s-13.44 33.6-32.16 34.56h-408c-18.72 0-34.08-14.88-34.08-33.6m0.96 176.16c0.48-18.72 15.84-33.6 34.56-33.12h403.2c18.24-0.48 33.6 13.44 34.56 32.16 0.48 18.24-13.44 33.6-32.16 34.56H273.17333333c-18.72 0-34.08-14.88-35.04-33.6" p-id="1391" fill="#ffffff"></path></svg>

BIN
src/main/resources/static/images/icon-menu.png


+ 1 - 0
src/main/resources/static/images/icon-product.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723654111626" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1589" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M235.52 596.58666667h194.24c33.17333333 0 55.57333333 22.4 55.57333333 55.46666666v248.32c0 33.06666667-33.17333333 55.46666667-66.34666666 55.46666667H179.94666667c-33.17333333 0-54.61333333-22.4-54.61333334-55.46666667V652.05333333c0-33.06666667 22.4-55.46666667 55.57333334-55.46666666h54.61333333z m415.78666667 0h248.85333333c33.17333333 0 55.57333333 28.26666667 55.57333333 61.33333333v238.61333333c0 33.06666667-26.34666667 59.41333333-59.52 59.41333334H657.17333333c-33.17333333 0-61.44-22.4-61.44-55.46666667V652.05333333c0-33.06666667 28.26666667-54.50666667 61.44-54.50666666l-5.86666666-0.96z m0-469.44h248.85333333c33.17333333 0 55.57333333 19.52 55.57333333 52.58666666v250.34666667c0 33.06666667-22.4 55.46666667-55.57333333 55.46666667H651.30666667c-33.17333333 0-55.57333333-22.4-55.57333334-55.46666667V181.65333333c-0.10666667-33.06666667 22.4-54.50666667 55.57333334-54.50666666zM87.25333333 257.6L257.06666667 88.21333333c23.46666667-23.36 61.44-23.36 84.90666666 0L509.86666667 257.70666667c23.46666667 23.36 23.46666667 61.33333333 0 84.69333333L341.01333333 510.93333333c-23.46666667 23.36-61.44 23.36-84.90666666 0L87.25333333 341.44c-22.50666667-23.46666667-22.50666667-61.44 0-83.84z" fill="#ffffff" p-id="1590"></path></svg>

BIN
src/main/resources/static/images/icon-search-white.png


+ 1 - 0
src/main/resources/static/images/icon-video.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723654166411" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1991" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M55.68690659 98.58813763v702.02014408H980.01342883v-702.02014408H55.68690659z m358.81029595 503.11443678v-308.10884186l265.20760916 152.10436557-265.20760916 156.00447629zM851.30973579 859.10996051H180.49048729c-23.40067086 0-39.00111866 15.60044779-39.00111867 39.00111865s15.60044779 39.00111866 39.00111867 39.00111866h670.8192485c23.40067086 0 39.00111866-15.60044779 39.00112031-39.00111866 0-19.50056016-15.60044779-39.00111866-39.00112031-39.00111865z" fill="#ffffff" p-id="1992"></path></svg>

+ 1 - 0
src/main/resources/static/images/icon-watch.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1723654120544" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1792" xmlns:xlink="http://www.w3.org/1999/xlink" width="64" height="64"><path d="M513.038 225.136c42.179 0 82.236 9.106 118.295 25.464v-84.031h24.23l46.989 130.09a278.848 278.848 0 0 1 13.328 12.514c51.917 51.917 84.053 123.638 84.053 202.836s-32.136 150.924-84.053 202.842a290.762 290.762 0 0 1-13.691 12.841l-46.626 129.072h-24.23v-83.34c-36.059 16.358-76.116 25.471-118.295 25.471-43.313 0-84.386-9.615-121.216-26.808v84.677h-24.215l-48.021-132.946a279.023 279.023 0 0 1-9.375-8.967c-51.917-51.917-84.053-123.644-84.053-202.842s32.136-150.919 84.053-202.836a285.667 285.667 0 0 1 8.997-8.625l48.399-133.979h24.215v85.367c36.815-17.2 77.903-26.8 121.216-26.8z m-107.452-22.107h212.522V94.936c0-18.786-15.364-34.155-34.142-34.155H439.741c-18.793 0-34.155 15.37-34.155 34.155v108.093z m212.522 616.302H405.586v108.1c0 18.786 15.362 34.148 34.155 34.148h144.224c18.778 0 34.142-15.362 34.142-34.148v-108.1h0.001zM476.382 523.149l23.313 23.451 14.041-13.931a20.595 20.595 0 0 0 3.358-0.385l17.513 23.588 13.285-9.847-17.223-23.197a20.523 20.523 0 0 0 3.038-9.97l71.654-71.139-23.328-23.452-74.255 73.72-87.729-118.208-13.285 9.847 88.049 118.645a21.492 21.492 0 0 0-1.701 4.273l-16.73 16.605z m335.483-68.261h29.098c12.63 0 22.965 10.326 22.965 22.963v76.561c0 12.63-10.335 22.957-22.965 22.957h-29.098V454.888zM659.11 365.945c-37.384-37.375-89.024-60.506-146.071-60.506-57.032 0-108.674 23.132-146.056 60.506-37.382 37.382-60.506 89.03-60.506 146.064 0 57.04 23.124 108.688 60.506 146.07 37.382 37.382 89.024 60.506 146.056 60.506 57.047 0 108.688-23.124 146.071-60.506 37.382-37.382 60.506-89.03 60.506-146.07 0-57.034-23.124-108.682-60.506-146.064z" fill="#ffffff" p-id="1793"></path></svg>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/main/resources/static/images/icon-wechat.svg


BIN
src/main/resources/static/images/index-banner.jpg


BIN
src/main/resources/static/images/index-section-1.jpg


BIN
src/main/resources/static/images/index-section-2.jpg


BIN
src/main/resources/static/images/logo.png


BIN
src/main/resources/static/images/nav-active.png


BIN
src/main/resources/static/images/p1.jpg


BIN
src/main/resources/static/images/qrcode-wechat.jpg


BIN
src/main/resources/static/images/sub-banner.jpg


+ 43 - 0
src/main/resources/static/js/default.js

@@ -0,0 +1,43 @@
+/**
+ * This script power by Mure.Yang (2024/05/11)
+ */
+
+// -- 获取指定参数值 (地址链接模式) ----------------------------------------------------
+function getUrlParam(name) {
+    var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)");
+    var r = window.location.search.substr(1).match(reg);
+    if (r != null) return unescape(r[2]); return null;
+}
+
+// -- 参数字符串 --------------------------------------------------------------------
+const QueryString = {
+    // 解析当前URL中的查询字符串,并返回一个对象
+    parse: function(query) {
+        const params = new URLSearchParams(query);
+        const result = {};
+        params.forEach((value, key) => {
+            result[key] = value;
+        });
+        return result;
+    },
+    // 构建查询字符串
+    build: function(params) {
+        return new URLSearchParams(params).toString();
+    },
+    // 更新URL中的多个参数
+    updateParams: function(params) {
+        // 获取当前URL
+        const url = new URL(window.location);
+        // 解析当前URL的查询字符串
+        let queryParams = this.parse(url.search);
+        // 遍历传入的对象,更新参数值
+        Object.keys(params).forEach(key => {
+            queryParams[key] = params[key];
+        });
+        // 更新查询字符串
+        url.search = this.build(queryParams);
+        // 返回更新后的URL
+        return url.href;
+    }
+};
+// -------------------------------------------------------------------------------

+ 2 - 0
src/main/resources/static/js/plugins/jquery.cookie.min.js

@@ -0,0 +1,2 @@
+/*! jquery.cookie v1.4.1 | MIT */
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?a(require("jquery")):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}});

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 1 - 0
src/main/resources/static/js/plugins/jquery.min.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/main/resources/static/js/plugins/layui/css/layui.css


+ 1 - 0
src/main/resources/static/js/plugins/layui/css/modules/code.css

@@ -0,0 +1 @@
+html #layuicss-skincodecss{display:none;position:absolute;width:1989px}.layui-code-h3,.layui-code-view{position:relative;font-size:12px}.layui-code-view{display:block;margin:10px 0;padding:0;border:1px solid #eee;border-left-width:6px;background-color:#FAFAFA;color:#333;font-family:Courier New}.layui-code-h3{padding:0 10px;height:40px;line-height:40px;border-bottom:1px solid #eee}.layui-code-h3 a{position:absolute;right:10px;top:0;color:#999}.layui-code-view .layui-code-ol{position:relative;overflow:auto}.layui-code-view .layui-code-ol li{position:relative;margin-left:45px;line-height:20px;padding:0 10px;border-left:1px solid #e2e2e2;list-style-type:decimal-leading-zero;*list-style-type:decimal;background-color:#fff}.layui-code-view .layui-code-ol li:first-child{padding-top:10px}.layui-code-view .layui-code-ol li:last-child{padding-bottom:10px}.layui-code-view pre{margin:0}.layui-code-notepad{border:1px solid #0C0C0C;border-left-color:#3F3F3F;background-color:#0C0C0C;color:#C2BE9E}.layui-code-notepad .layui-code-h3{border-bottom:none}.layui-code-notepad .layui-code-ol li{background-color:#3F3F3F;border-left:none}.layui-code-demo .layui-code{visibility:visible!important;margin:-15px;border-top:none;border-right:none;border-bottom:none}.layui-code-demo .layui-tab-content{padding:15px;border-top:none}

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/main/resources/static/js/plugins/layui/css/modules/laydate/default/laydate.css


BIN
src/main/resources/static/js/plugins/layui/css/modules/layer/default/icon-ext.png


BIN
src/main/resources/static/js/plugins/layui/css/modules/layer/default/icon.png


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/main/resources/static/js/plugins/layui/css/modules/layer/default/layer.css


BIN
src/main/resources/static/js/plugins/layui/css/modules/layer/default/loading-0.gif


BIN
src/main/resources/static/js/plugins/layui/css/modules/layer/default/loading-1.gif


BIN
src/main/resources/static/js/plugins/layui/css/modules/layer/default/loading-2.gif


BIN
src/main/resources/static/js/plugins/layui/font/iconfont.eot


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 25 - 0
src/main/resources/static/js/plugins/layui/font/iconfont.svg


BIN
src/main/resources/static/js/plugins/layui/font/iconfont.ttf


BIN
src/main/resources/static/js/plugins/layui/font/iconfont.woff


BIN
src/main/resources/static/js/plugins/layui/font/iconfont.woff2


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 0
src/main/resources/static/js/plugins/layui/layui.js


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 14 - 0
src/main/resources/static/js/plugins/swiper/swiper.min.css


La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 14 - 0
src/main/resources/static/js/plugins/swiper/swiper.min.js


+ 97 - 0
src/main/resources/templates/__article.html

@@ -0,0 +1,97 @@
+<div class="hjcl-layout-container" th:fragment="body">
+
+  <!-- 内页 幻灯片区域 -->
+  <div th:replace="~{components/sub-banner::sub-banner}"></div>
+
+  <!-- 内容 -->
+  <div class="sub-section-main">
+    <div class="wrapper">
+
+      <!-- 主要位置 -->
+      <div class="sub-section-container">
+        <div class="sub-section-container-title" th:text="${parameters.category_name}"></div>
+        <div class="sub-section-container-content">
+
+          <!-- 搜索框 -->
+          <div class="sub-search">
+            <div th:replace="~{components/search-input::search-input}"></div>
+          </div>
+
+          <div class="article-list" th:classappend="${isBrand ? 'column' : ''}">
+            <div class="article-item" th:each="item, itemStat : ${article.list}">
+              <a class="article-thumb" th:href="@{'/articleDetail/' + ${item.id}}"><img th:src="${item.thumb}" /></a>
+              <div class="article-info">
+                <a class="article-info-title" th:href="@{'/articleDetail/' + ${item.id}}">
+                  <span th:text="${item.title}"></span>
+                  <span th:if="${item.is_top == 1}" th:text="@{'[' + #{settop} + ']'}"></span>
+                </a>
+                <div class="article-info-description" th:text="${item.description}"></div>
+                <div class="article-info-bottom">
+                  <div class="article-info-time" th:text="${item.create_time}"></div>
+                  <a class="article-info-btn" th:href="@{'/articleDetail/' + ${item.id}}" th:text="#{viewdetail}"></a>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div id="pagination-bar"></div>
+
+        </div>
+      </div>
+
+      <!-- 侧边 -->
+      <div class="sub-section-sider">
+        <div class="sub-section-sider-title" th:text="#{category}"></div>
+
+        <div class="sub-section-sider-content">
+          <div class="article-category horizontal">
+            <ul id="category-bar">
+<!--              <li class="mb-4"><a href="javascript:;" th:classappend="${parameters.category_id == null ? 'font-bold text-blue' : ''}">全部</a></li>-->
+              <li th:each="item, itemStat : ${articleCategory}" th:if="${item.is_brand == 1}">
+                <a href="javascript:;" th:text="${lang} == 'zh' ? ${item.category_name} : ${item.category_name_en}" th:data-category-id="${item.article_category_id}"
+                   th:classappend="(${item.article_category_id} == ${parameters.category_id} ? 'active' : '')"></a>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="sub-section-sider-content mt-2">
+          <p th:text="#{sub.sider.welcome}"></p>
+          <p th:text="@{#{sub.sider.wechat} + ' cpnana8 / anywayto'}"></p>
+        </div>
+      </div>
+
+    </div>
+  </div>
+
+</div>
+<script th:inline="javascript">
+  var lang = $.cookie('lang')
+
+  // [Click] 分类
+    $('#category-bar > li > a').on('click', function(){
+        var category_id = $(this).attr('data-category-id')
+        if (category_id) {
+            window.location.href = QueryString.updateParams({ category_id: parseInt(category_id) })
+        } else {
+            window.location.href = window.location.href.split('?')[0];
+        }
+    })
+    // [Click] 分页
+  console.log(lang)
+    layui.use('laypage', function(){
+        var laypage = layui.laypage
+        laypage.render({
+            elem: 'pagination-bar', theme: '#333e46',
+            prev: (lang == 'zh' ? '上一页' : 'Prev'),
+            next: (lang == 'zh' ? '下一页' : 'Next'),
+            count: [[${article.total}]], curr: [[${article.page_num}]], limit: [[${article.page_size}]],
+            jump: function(obj, first) {
+                // console.log(obj)
+                // 首次不执行
+                if (!first) {
+                  //do something
+                  window.location.href = QueryString.updateParams({ page_num: obj.curr, page_size: obj.limit })
+                }
+            }
+        })
+    })
+</script>

+ 24 - 0
src/main/resources/templates/__layout/head.html

@@ -0,0 +1,24 @@
+<head th:fragment="header">
+  <meta charset="UTF-8" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+  <title th:text="${title} + ' - ' + ${siteInfo.name}"></title>
+  <meta name="keywords" th:content="${siteInfo.meta_keyword}" />
+  <meta name="description" th:content="${siteInfo.meta_description}" />
+  <link rel="shortcut icon" th:href="@{'/images/favicon.ico'}" type="image/x-icon"/>
+  <link rel="stylesheet" th:href="@{'/css/reset.css'}">
+
+  <link rel="stylesheet" th:href="@{'/js/plugins/layui/css/layui.css'}">
+  <script th:src="@{'/js/plugins/layui/layui.js'}"></script>
+
+  <link rel="stylesheet" th:href="@{'/js/plugins/swiper/swiper.min.css'}">
+  <script th:src="@{'/js/plugins/swiper/swiper.min.js'}"></script>
+
+  <link rel="stylesheet" th:href="@{'/css/public.css?v=' + ${requestVO.timestamp}}">
+  <link rel="stylesheet" th:href="@{'/css/default.css?v=' + ${requestVO.timestamp}}">
+  <script th:src="@{'/js/plugins/jquery.min.js'}"></script>
+  <script th:src="@{'/js/plugins/jquery.cookie.min.js'}"></script>
+  <script th:src="@{'/js/default.js?v=' + ${requestVO.timestamp}}"></script>
+</head>

+ 73 - 0
src/main/resources/templates/__layout/layout-footer.html

@@ -0,0 +1,73 @@
+<div th:fragment="layout-footer">
+
+  <div class="footer-menutabs">
+    <a href="/" class="footer-menutabs-item"
+       th:classappend="${(requestVO.uri == '/' ? 'active' : '')}">
+       <img src="/images/icon-watch.svg" />
+      <span th:text="#{footer.menu.home}"></span>
+    </a>
+    <a href="/article?category_id=1" class="footer-menutabs-item"
+       th:classappend="${(requestVO.uri + '?' + requestVO.queryString) == '/article?category_id=1' ? 'active' : ''}">
+      <img src="/images/icon-product.svg" />
+      <span th:text="#{footer.menu.product}"></span>
+    </a>
+    <a href="/article?category_id=42" class="footer-menutabs-item"
+       th:classappend="${(requestVO.uri + '?' + requestVO.queryString) == '/article?category_id=42' ? 'active' : ''}">
+      <img src="/images/icon-video.svg" />
+      <span th:text="#{footer.menu.video}"></span>
+    </a>
+    <a href="/article?category_id=43" class="footer-menutabs-item"
+       th:classappend="${(requestVO.uri + '?' + requestVO.queryString) == '/article?category_id=43' ? 'active' : ''}">
+      <img src="/images/icon-ce.svg" />
+      <span th:text="#{footer.menu.ce}"></span>
+    </a>
+
+    <!-- 微信联系 -->
+    <a href="javascript:;" class="footer-menutabs-item" id="menuWechat"
+       th:attr="data-text1=#{footer.menu.wechatinfo.text1}, data-text2=#{footer.menu.wechatinfo.text2}"
+      >
+      <img src="/images/icon-wechat.svg" />
+      <span th:text="#{footer.menu.wechat}"></span>
+    </a>
+    <script>
+      // [Click] 点击 微信联系
+      $('#menuWechat').on('click', function() {
+        var text1 = $(this).attr('data-text1')
+        var text2 = $(this).attr('data-text2')
+        layer.open({
+          title: false, shadeClose: true, closeBtn: false,
+          content: '<div class="menu-wechat-dialog-content">' +
+              '<img src="/images/qrcode-wechat.jpg"/><div>' + text1 + '<br/>' + text2 + ':cpnana8</div>' +
+              '</div>',
+          btn: []
+        })
+      })
+    </script>
+    <style>
+      .menu-wechat-dialog-content > img { display: block; width: 160px; height: 160px; margin: 10px auto; }
+      .menu-wechat-dialog-content > div { font-size: 14px; text-align: center; line-height: 18px; }
+    </style>
+
+  </div>
+
+
+  <div class="hjcl-layout-footer flex items-center justify-center">
+    <div class="wrapper">
+
+      <ul class="footer-nav flex items-center justify-center mb-2">
+        <li th:each="nav, iterStat : ${navigation}" class="mx-2">
+          <a th:href="${nav.link}" th:class="${'link underline-hover underline-offset-4 '}">
+            <span th:text="${nav.navigation_name}"></span>
+          </a>
+          <span class="ml-3" th:if="${iterStat.index != navigation.size - 1}">|</span>
+        </li>
+      </ul>
+
+      <div class="footer-copyright flex items-center justify-center">
+        <span class="mx-1" th:utext="${siteInfo.copyright}"></span>
+        <span class="mx-1" th:utext="${siteInfo.icp}"></span>
+      </div>
+
+    </div>
+  </div>
+</div>

+ 61 - 0
src/main/resources/templates/__layout/layout-header.html

@@ -0,0 +1,61 @@
+<div th:fragment="layout-header" class="hjcl-layout-header">
+
+  <div class="wrapper">
+
+    <div class="nav-menu" id="navMenu"></div>
+    <div class="nav-right-bar">
+      <div th:replace="~{components/language::language}"></div>
+    </div>
+
+    <!-- 导航 -->
+    <ul class="nav" id="nav">
+
+      <li class="first-nav-item" th:text="#{sub.sider.title.nav}"></li>
+
+      <li th:each="nav, iterStat : ${navigation}"
+          th:class="${(iterStat.index + 1 == (navigation.size + 1) / 2) ? 'middle-l' : (iterStat.index == (navigation.size + 1) / 2) ? 'middle-r' : ''}">
+        <div class="flex justify-between">
+          <a th:href="${nav.link}"
+             th:class="${'link underline-hover underline-offset-4 ' + (requestVO.uri == nav.link ? 'active' : '') + (nav.is_blank == 1 ? 'underline' : '')}">
+            <span th:text="${nav.navigation_name}"></span>
+          </a>
+          <span th:if="${nav.children.size > 0}" class="nav-more" id="navMore">+</span>
+        </div>
+        <!-- 子级导航 -->
+        <div th:if="${nav.children.size > 0}" class="navSub">
+          <div th:each="navChild : ${nav.children}">
+            <a th:href="${navChild.link}" th:text="${navChild.navigation_name}"></a>
+          </div>
+        </div>
+
+      </li>
+    </ul>
+    <div class="nav-mask" id="navMask"></div>
+    <script>
+      // [Click] 点击显示左侧 (或顶部) 导航
+      $('#navMenu').on('click', function() {
+          $(this).toggleClass('active')
+          $('#nav, #navMask').toggleClass('active')
+      })
+      // [Click] 导航 遮罩层
+      $('#navMask').on('click', function() {
+          $('#nav, #navMask').toggleClass('active')
+      })
+      // [Click] 点击子级导航
+      $('#navMore').on('click', function() {
+          // 切换文本内容
+          $(this).text(function(index, currentText) {
+              return currentText === '+' ? '-' : '+'
+          })
+          // 显示/隐藏菜单
+          $(this).parent().next('.navSub').toggleClass('active');
+      })
+    </script>
+
+    <!-- Logo -->
+    <a href="/" class="header-logo-link">
+      <img class="header-logo" th:src="@{/images/logo.png}" />
+    </a>
+
+  </div>
+</div>

+ 8 - 0
src/main/resources/templates/__layout/layout-top.html

@@ -0,0 +1,8 @@
+<div th:fragment="layout-top" class="hjcl-layout-top">
+  <div class="wrapper">
+    <div class="text-xs"><span th:text="#{top.welcome}"></span>:cpnana8 / anywayto</div>
+    <div class="text-xs">
+      <div th:replace="~{components/language::language}"></div>
+    </div>
+  </div>
+</div>

+ 10 - 0
src/main/resources/templates/__layout/layout.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head th:replace="~{layout/head::head}"></head>
+<body>
+<div th:replace="~{layout/layout-top::layout-top}"></div>
+<div th:replace="~{layout/layout-header::layout-header}"></div>
+<th:block th:replace="~{${layout}}" />
+<div th:replace="~{layout/layout-footer::layout-footer}"></div>
+</body>
+</html>

+ 3 - 0
src/main/resources/templates/article.html

@@ -0,0 +1,3 @@
+<div class="hjcl-layout-container" th:fragment="body">
+  article
+</div>

+ 68 - 0
src/main/resources/templates/articleDetail.html

@@ -0,0 +1,68 @@
+<div class="hjcl-layout-container" th:fragment="body">
+
+  <!-- 内页 幻灯片区域 -->
+  <div th:replace="~{components/sub-banner::sub-banner}"></div>
+
+  <!-- 内容 -->
+  <div class="sub-section-main">
+    <div class="wrapper">
+      <div class="sub-section-container">
+
+        <div class="article-detail">
+          <div class="sub-section-container-title">
+            <div class="article-detail-title" th:text="${articleDetail.title}"></div>
+            <div class="article-detail-subtitle">
+                <div th:text="${articleDetail.create_time}"></div>
+                <a class="back" href="javascript:history.back();" th:text="#{back}"></a>
+            </div>
+          </div>
+          <div class="sub-section-container-content bg-white" style="padding: 20px; box-sizing: border-box">
+            <div class="sub-section-container-description" th:text="${articleDetail.description}"></div>
+            <div class="content-detail" >
+
+              <div th:if="${articleDetail.video != null && articleDetail.video != ''}" class="article-video-bar">
+                <video class="article-video" th:src="${articleDetail.video}" controls></video>
+              </div>
+
+              <div th:utext="${articleDetail.content}"></div>
+
+            </div>
+          </div>
+        </div>
+
+      </div>
+
+      <!-- 侧边 -->
+      <div class="sub-section-sider">
+        <div class="sub-section-sider-title" th:text="#{category}"></div>
+        <div class="sub-section-sider-content">
+          <div class="article-category horizontal">
+            <ul id="category-bar">
+<!--              <li class="mb-4"><a href="javascript:;">全部</a></li>-->
+              <li th:each="item, itemStat : ${articleCategory}" th:if="${item.is_brand == 1}">
+                <a href="javascript:;" th:text="${lang} == 'zh' ? ${item.category_name} : ${item.category_name_en}" th:data-category-id="${item.article_category_id}"></a>
+              </li>
+            </ul>
+          </div>
+        </div>
+        <div class="sub-section-sider-content mt-2">
+            <p th:text="#{sub.sider.welcome}"></p>
+            <p th:text="@{#{sub.sider.wechat} + ' cpnana8 / anywayto'}"></p>
+        </div>
+      </div>
+      <script th:inline="javascript">
+          // [Click] 分类
+          $('#category-bar > li > a').on('click', function(){
+              var category_id = $(this).attr('data-category-id')
+              if (category_id) {
+                  window.location.href = '/article?category_id=' + parseInt(category_id)
+              } else {
+                  window.location.href = '/article';
+              }
+          })
+      </script>
+
+    </div>
+  </div>
+
+</div>

+ 20 - 0
src/main/resources/templates/components/language.html

@@ -0,0 +1,20 @@
+<div th:fragment="language">
+
+  <ul class="flex items-center">
+    <li class="ml-4">
+      <a href="javascript:;" onclick="setLangAndRefresh('zh');"
+         th:classappend="${lang} == 'zh' ? 'font-bold' : ''">中文</a>
+    </li>
+    <li class="ml-4">
+      <a href="javascript:;" onclick="setLangAndRefresh('en');"
+         th:classappend="${lang} == 'en' ? 'font-bold' : ''">English</a>
+    </li>
+  </ul>
+  <script>
+      function setLangAndRefresh(lang) {
+          document.cookie = "lang=" + lang + ";max-age=2592000;path=/"
+          location.reload()
+      }
+  </script>
+
+</div>

+ 22 - 0
src/main/resources/templates/components/search-input.html

@@ -0,0 +1,22 @@
+<div th:fragment="search-input">
+
+  <div class="index-search">
+    <input class="index-search-input" th:value="${parameters != null ? parameters.title : ''}" id="searchInput" type="text"
+       th:placeholder="#{search.input.placeholder}" maxlength="25">
+    <a href="javascript:;" id="searchBtn" class="index-search-btn"><i class="icon-search-white"></i></a>
+  </div>
+  <script>
+    $('#searchBtn').on('click', function() {
+        var val = $('#searchInput').val()
+        if (val) {
+          window.location.href = '/article?title=' + val
+        } else {
+          window.location.href = '/article'
+        }
+    })
+    $('#searchInput').on('keydown', function(e) {
+        if (e.keyCode === 13) $('#searchBtn').click()
+    })
+  </script>
+
+</div>

+ 2 - 0
src/main/resources/templates/components/sub-banner.html

@@ -0,0 +1,2 @@
+<div th:fragment="sub-banner" class="sub-banner">
+</div>

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 16 - 0
src/main/resources/templates/error.html


+ 88 - 0
src/main/resources/templates/index.html

@@ -0,0 +1,88 @@
+<div class="hjcl-layout-container" th:fragment="body">
+
+
+  <div class="index-banner">
+    <!-- 首页 幻灯片 -->
+    <div class="swiper-container">
+      <div class="swiper-wrapper">
+        <!-- style="background-color: transparent" -->
+        <div th:each="item, itemStat : ${bannerList}" class="swiper-slide">
+          <a th:href="${item.link}">
+            <img th:src="${item.image}" class="banner-img" />
+          </a>
+        </div>
+      </div>
+      <div class="swiper-pagination"></div>
+    </div>
+    <script>
+        var swiper = new Swiper('.swiper-container', {
+            pagination: '.swiper-pagination',
+            paginationClickable: true,
+            loop: true
+        });
+    </script>
+    <!-- 搜索框 -->
+    <div class="index-search-bar">
+      <div th:replace="~{components/search-input::search-input}"></div>
+    </div>
+  </div>
+
+
+  <div class="index-section index-section-1">
+
+    <div class="wrapper">
+      <div class="wrapper">
+        <div class="index-section-hd">
+          <div class="index-section-title">
+            <div class="index-section-maintitle" th:text="#{index.section1.title}"></div>
+          </div>
+          <div class="index-section-more"><a href="/article?category_id=1"><span th:text="#{more}"></span>+</a></div>
+        </div>
+      </div>
+
+      <div class="index-article-list">
+        <div class="index-article-item" th:each="item, itemStat : ${articleList1.list}">
+          <a th:href="@{'/articleDetail/' + ${item.id}}">
+            <img class="article-item-thumb" th:src="${item.thumb}" />
+            <div class="article-item-title" th:text="${item.title}"></div>
+          </a>
+        </div>
+      </div>
+
+    </div>
+
+  </div>
+
+  <div class="index-subbanner w-full text-center" style="background-color: rgba(1, 6, 10, 1);">
+    <img class="wrapper" th:src="@{/images/index-section-1.jpg}" />
+  </div>
+
+
+  <div class="index-section index-section-2">
+    <div class="wrapper">
+      <div class="index-section-hd">
+        <div class="index-section-title">
+          <div class="index-section-maintitle" th:text="#{index.section2.title}"></div>
+        </div>
+        <div class="index-section-more"><a href="/article?category_id=2"><span th:text="#{more}"></span>+</a></div>
+      </div>
+
+      <div>
+        <div class="index-article-list">
+          <div class="index-article-item" th:each="item, itemStat : ${articleList2.list}">
+            <a th:href="@{'/articleDetail/' + ${item.id}}">
+              <img class="article-item-thumb" th:src="${item.thumb}" />
+              <div class="article-item-title" th:text="${item.title}"></div>
+            </a>
+          </div>
+        </div>
+      </div>
+
+    </div>
+  </div>
+
+  <div class="index-subbanner w-full text-center" style="background-color: rgba(38, 47, 54, 1);">
+    <img class="wrapper" th:src="@{/images/index-section-2.jpg}" />
+  </div>
+
+</div>

+ 8 - 0
src/main/resources/templates/layout/head.html

@@ -0,0 +1,8 @@
+<head th:fragment="header">
+  <meta charset="UTF-8" />
+  <meta http-equiv="pragma" content="no-cache" />
+  <meta http-equiv="expires" content="0" />
+  <meta http-equiv="cache-control" content="no-cache, no-store, must-revalidate" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
+  <link rel="shortcut icon" th:href="@{'/images/favicon.ico'}" type="image/x-icon"/>
+</head>

+ 3 - 0
src/main/resources/templates/layout/layout-footer.html

@@ -0,0 +1,3 @@
+<div th:fragment="layout-footer">
+  footer
+</div>

+ 3 - 0
src/main/resources/templates/layout/layout-header.html

@@ -0,0 +1,3 @@
+<div th:fragment="layout-header" class="hjcl-layout-header">
+  header
+</div>

+ 3 - 0
src/main/resources/templates/layout/layout-top.html

@@ -0,0 +1,3 @@
+<div th:fragment="layout-top" class="hjcl-layout-top">
+  top
+</div>

+ 10 - 0
src/main/resources/templates/layout/layout.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en" xmlns:th="http://www.thymeleaf.org">
+<head th:replace="~{layout/head::head}"></head>
+<body>
+<div th:replace="~{layout/layout-top::layout-top}"></div>
+<div th:replace="~{layout/layout-header::layout-header}"></div>
+<th:block th:replace="~{${layout}}" />
+<div th:replace="~{layout/layout-footer::layout-footer}"></div>
+</body>
+</html>

+ 31 - 0
src/main/resources/templates/page.html

@@ -0,0 +1,31 @@
+<div class="hjcl-layout-container" th:fragment="body">
+
+  <!-- 内页 幻灯片区域 -->
+  <div th:replace="~{components/sub-banner::sub-banner}"></div>
+
+  <!-- 内容 -->
+  <div class="sub-section-main">
+    <div class="wrapper">
+
+      <!-- 主要位置 -->
+      <div class="sub-section-container">
+        <div class="sub-section-container-title" th:text="${pageDetail.title}"></div>
+        <div class="sub-section-container-content">
+          <div class="bg-white" style="padding: 30px; box-sizing: border-box"
+             th:utext="${pageDetail.content}"></div>
+        </div>
+      </div>
+
+      <!-- 侧边 -->
+      <div class="sub-section-sider">
+        <div class="sub-section-sider-title" th:text="#{sub.sider.title.nav}"></div>
+        <div class="sub-section-sider-content">
+          <p th:text="#{sub.sider.welcome}"></p>
+          <p th:text="@{#{sub.sider.wechat} + ' cpnana8 / anywayto'}"></p>
+        </div>
+      </div>
+
+    </div>
+  </div>
+
+</div>

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio