Browse Source

供应商文章列表

喻文俊 3 years ago
parent
commit
ed84348fd1

+ 9 - 1
src/main/java/com/caimei/www/controller/unlimited/EncyclopediaController.java

@@ -2,8 +2,11 @@ package com.caimei.www.controller.unlimited;
 
 import com.caimei.www.controller.BaseController;
 import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
 import org.springframework.web.bind.annotation.GetMapping;
 
+import java.util.ArrayList;
+
 /**
  * 采美文库
  *
@@ -59,7 +62,12 @@ public class EncyclopediaController extends BaseController {
      * 查看更多
      */
     @GetMapping("/encyclopedia/more.html")
-    public String getMoreList() {
+    public String getMoreList(final Model model) {
+        ArrayList<Object> list = new ArrayList<>();
+        for (int i=0; i< 1000 ; i++){
+            list.add(new Object());
+        }
+        model.addAttribute("list", list);
         return MORE_LIST;
     }
 

+ 8 - 8
src/main/resources/config/dev/application-dev.yml

@@ -4,13 +4,13 @@ spring:
   #数据源连接--start
   datasource:
     #本地连接数据库
-#    url: jdbc:mysql://192.168.2.100:3306/caimei?characterEncoding=UTF8&serverTimezone=Asia/Shanghai
-#    username: developer
-#    password: 05bZ/OxTB:X+yd%1
-    #测试连接数据库
-    url: jdbc:mysql://120.79.25.27:3306/caimei?characterEncoding=UTF8&serverTimezone=Asia/Shanghai
+    url: jdbc:mysql://192.168.2.100:3306/caimei?characterEncoding=UTF8&serverTimezone=Asia/Shanghai
     username: developer
-    password: J5p3tgOVazNl4ydf
+    password: 05bZ/OxTB:X+yd%1
+    #测试连接数据库
+#     url: jdbc:mysql://120.79.25.27:3306/caimei?characterEncoding=UTF8&serverTimezone=Asia/Shanghai
+#     username: developer
+#     password: J5p3tgOVazNl4ydf
     #type: com.zaxxer.hikari.HikariDataSource
     hikari:
       minimum-idle: 5
@@ -54,8 +54,8 @@ logging:
 caimei:
   siteEnv: 0 #网站环境,(2:正式环境,1:测试环境,0:开发环境)
   spiServer: http://192.168.2.68:8008
-  coreServer: https://core-b.caimei365.com
-#  coreServer: http://192.168.2.68:18002
+#  coreServer: https://core-b.caimei365.com
+  coreServer: http://192.168.2.68:18002
 #  coreServer: http://192.168.2.75:18002
   imageDomain: https://img-b.caimei365.com
   wwwDomain: http:localhost:8009

+ 12 - 1
src/main/resources/static/css/supplier-center/article/article-edit.css

@@ -1,3 +1,4 @@
+@charset "UTF-8";
 input[hidden] {
     display: none !important;
 }
@@ -230,7 +231,7 @@ input[hidden] {
 
 .article-edit .tag-list {
     width: 100%;
-    padding: 16px 0;
+    padding-bottom: 32px;
     display: flex;
     justify-content: flex-start;
     align-items: center;
@@ -240,6 +241,7 @@ input[hidden] {
 .article-edit .tag-list .tag {
     position: relative;
     padding: 0 6px;
+    margin: 8px 8px 0 0;
     height: 28px;
     line-height: 28px;
     background: #FFF3E5;
@@ -247,9 +249,18 @@ input[hidden] {
     font-size: 14px;
     font-weight: 400;
     color: #4A4F58;
+    cursor: pointer;
+    border: 1px solid #FFF3E5;
+}
+
+.article-edit .tag-list .tag.active{
+    color: #E15616;
+    background: #FFE6DC;
+    border-color: #E15616;
 }
 
 .article-edit .tag-list .tag .close {
+    display: none;
     position: absolute;
     top: -8px;
     right: -8px;

+ 1 - 0
src/main/resources/static/css/supplier-center/article/article-list.css

@@ -1,3 +1,4 @@
+@charset "UTF-8";
 .top-row {
     width: 968px;
     padding: 12px 0 12px 236px;

+ 1 - 0
src/main/resources/static/css/supplier-center/article/table.css

@@ -1,3 +1,4 @@
+@charset "UTF-8";
 /*!
  * Generated using the Bootstrap Customizer (https://v3.bootcss.com/customize/)
  */

+ 36 - 0
src/main/resources/static/js/base.js

@@ -60,6 +60,16 @@ var globalHead = new Vue({
         isFiexd:false,
         classifyIndex:1
     },
+    watch:{
+        isFiexd: function(nVal,oVal){
+            // 防止跳动
+            if(nVal && isPC){
+                $("body").css('paddingTop', $("#globalHead").height() + "px");
+            }else{
+                $("body").css('paddingTop', "0px");
+            }
+        }
+    },
     methods: {
         changeClassify: function(value){
             this.classifyIndex=value;
@@ -767,3 +777,29 @@ function dialog(txt,callback) {
     });
 }
 
+
+/** 时间格式化
+ * @param {Date} date 标准时间格式 -> new Date()
+ * @param {string} format 时间格式化的格式 'yyyy-MM-dd hh:mm:ss'
+ * @returns {string} 格式化后的时间  '2017-01-01 01:00:00'
+ */
+function dateFormat(date = new Date(), format = 'yyyy-MM-dd hh:mm:ss') {
+	var o = {
+		'M+': date.getMonth() + 1, // month
+		'd+': date.getDate(), // day
+		'h+': date.getHours(), // hour
+		'm+': date.getMinutes(), // minute
+		's+': date.getSeconds(), // second
+		'q+': Math.floor((date.getMonth() + 3) / 3), // quarter
+		S: date.getMilliseconds(), // millisecond
+	};
+	if (/(y+)/.test(format)) {
+		format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
+	}
+	for (var k in o) {
+		if (new RegExp('(' + k + ')').test(format)) {
+			format = format.replace(RegExp.$1, RegExp.$1.length === 1 ? o[k] : ('00' + o[k]).substr(('' + o[k]).length))
+		}
+	}
+	return format
+}

+ 77 - 0
src/main/resources/static/js/common/serviceapi/supplier.service.js

@@ -4,6 +4,83 @@
  * auther ZHJY
  */
 var SupplierApi = {
+        UploadFile: function(params, callback){ // 供应商文章上传图片
+            Http.AjaxService({
+                url:'/tools/image/upload/ckeditor',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+        GetArticleList: function(params, callback){ //供应商文章列表
+            Http.AjaxService({
+                url:'/user/shop/article/list',
+                type:'get',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+        GetArticleForm: function(params, callback){ //供应商文章信息回显
+            Http.AjaxService({
+                url:'/user/shop/article/form',
+                type:'get',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+        ArticleSubmitSave: function(params, callback){ //供应商文章保存
+            Http.AjaxService({
+                url:'/user/shop/article/save',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+        ArticleStatusChange: function(params, callback){ //供应商文章状态修改
+            Http.AjaxService({
+                url:'/user/shop/article/status/update',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+        ArticleRemove: function(params, callback){ //供应商文章状态修改
+            Http.AjaxService({
+                url:'/user/shop/article/delete',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+        ArticleCategory: function(params, callback){
+            Http.AjaxService({
+                url:'/user/shop/article/type/list',
+                type:'get',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
         GetSearchShopList:function (params, callback) {//搜索供应商列表查询
             Http.AjaxService({
                 url:'/commodity/search/query/shop',

+ 174 - 8
src/main/resources/static/js/supplier-center/article/article-edit.js

@@ -1,24 +1,190 @@
+
+
 new Vue({
     el: '#articleEdit',
-    mixins: [formMixin],
+    mixins: [formMixin, uploadMixin],
     data: {
+        NODE_ENV_BASE_URL: '',
+        editor: null,
+        shopId: GLOBAL_SHOP_ID, // 供应商id
         formData: {
-            title: '',
-            desc: ''
+            articleId: 0, // 文章id
+            title: '', // 标题
+            articleContent: '', // 内容
+            guidanceImage: '', // 引导图
+            keyword: '', // seo关键词
+            label: '', // 标签
+            publisher: '', // 发布人
+            recommendContent: '', // 推荐语
+            source: '', // 来源
+            status: 1, // 状态
+            typeId: '', // 文章分类
         },
+        articleLabels: [],
+        chooseLabels: [],
+        articleTypeList: [],
+        addLabelName: '',
+    },
+    watch: {
+        chooseLabels: function (newVal) {
+            this.formData.label = newVal.join(',');
+        },
+        'formData.label': function (newVal, oldVal) {
+            if (!newVal.trim()) {
+                return this.chooseLabels = [];
+            }
+            if (newVal === oldVal) return;
+            this.chooseLabels = newVal.split(',');
+        }
+    },
+    created() {
+        this.init();
     },
     mounted() {
-        this.initEditor();
+        this.NODE_ENV_BASE_URL = $('#coreServer').val();
+        // console.log(this.NODE_ENV_BASE_URL);
         $('.navLayout').find('.navList').removeClass("on").find('.con').hide().find('a').removeClass("on");
         $('.navLayout').find('.navList').eq(2).addClass("on").find('.con').show().find('a').eq(0).addClass("on");
+        this.initEditor();
+    },
+    beforeDestroy() {
+        // 销毁编辑器
+        this.editor.destroy();
+        this.editor = null;
     },
     methods: {
+        // 页面初始化
+        init() {
+            const articleId = localStorage.getItem('articleId') || 0;
+            localStorage.removeItem('articleId');
+            this.formData.articleId = articleId;
+            this.fetchArticleCatagory();
+            // 文章id就是修改文章
+            this.fetchFormList();
+        },
+        // 获取标签列表和分类列表
+        fetchFormList() {
+            const that = this;
+            SupplierApi.GetArticleForm({articleId: this.formData.articleId}, function (res) {
+                if (res.code === 0) {
+                    // console.log(res);
+                    that.articleLabels = res.data.articleLabels.split(',');
+                    // 初始化表单数据
+                    if (res.data.shopArticle) {
+                        that.setFormData(res.data.shopArticle)
+                    }
+                } else {
+                    CAIMEI.Alert(res.msg, '确定', false);
+                }
+            })
+        },
+        setFormData(shopArticle) {
+            for (let key in this.formData) {
+                if(key === 'status' || key === 'typeId'){
+                    this.formData[key] = shopArticle[key].toString();
+                }else{
+                    this.formData[key] = shopArticle[key];
+                }
+            }
+            this.editor.txt.html(this.formData.articleContent);
+        },
+        fetchArticleCatagory() {
+            const that = this;
+            SupplierApi.ArticleCategory({}, function (res) {
+                if (res.code === 0) {
+                    // console.log(res);
+                    that.articleTypeList = res.data;
+                } else {
+                    CAIMEI.Alert(res.msg, '确定', false);
+                }
+            })
+        },
+        labelClick(index) {
+            const newLabel = this.articleLabels[index];
+            const popIndex = this.chooseLabels.indexOf(newLabel);
+            if (popIndex > -1) {
+                this.chooseLabels.splice(popIndex, 1);
+            } else {
+                this.chooseLabels.push(newLabel);
+            }
+        },
+        addLabel() {
+            if (!this.addLabelName.trim()) return;
+            if (this.chooseLabels.indexOf(this.addLabelName) > -1) return this.addLabelName = '';
+            this.chooseLabels.push(this.addLabelName);
+            this.addLabelName = ''
+        },
+        checkLabel(index) {
+            return this.chooseLabels.indexOf(this.articleLabels[index]) > -1
+        },
+        // 引导图上传
+        fileInputChange(e) {
+            this.uploadImage(e.target.files[0]).then(res => {
+                this.formData.guidanceImage = res;
+            })
+        },
+        // 初始化富文本
         initEditor() {
             const E = window.wangEditor;
-            const editor = new E("#editor");
-            editor.config.zIndex = 333;
-            editor.config.height = 500;
-            editor.create();
+            this.editor = new E("#editor");
+            this.initEditorOptions(this.editor, this.NODE_ENV_BASE_URL);
+            this.editor.create();
+        },
+        // 保存 提交表单
+        handleSave() {
+            this.formData.articleContent = this.editor.txt.html();
+            this.handleFormData();
+            // console.log(this.formData);
+            this.validAll(this.formData).then(valid => {
+                console.log(valid);
+                this.save()
+            }).catch(err => {
+                console.log(err);
+            })
+        },
+        // 保存接口
+        save() {
+            this.formData.shopId = this.shopId;
+            SupplierApi.ArticleSubmitSave(this.formData, function (res) {
+                if (res.code === 0) {
+                    CAIMEI.dialog('保存成功');
+                    localStorage.setItem('refreshType', '1'); // 通知文章列表需要刷新
+                    setTimeout(function () {
+                        window.location.href = '/supplier/article/list.html';
+                    }, 2000)
+                } else {
+                    CAIMEI.Alert(res.msg, '确定', false);
+                }
+            })
+        },
+        // 处理表单数据
+        handleFormData() {
+            const that = this;
+            $('.form').submit(function (eventData) {
+                const formData = that.serializeArrayToObj($(this).serializeArray());
+                for (let key in formData) {
+                    if (key === 'typeId' || key === 'status') {
+                        that.formData[key] = Number(formData[key]);
+                    } else {
+                        that.formData[key] = formData[key];
+                    }
+                }
+                return false;
+            })
+        },
+        // 表单数据转为对象
+        serializeArrayToObj(serializeArray) {
+            const obj = Object.create(null);
+            serializeArray.forEach(function (item) {
+                obj[item.name] = item.value
+            });
+            return obj;
+        },
+        handleBack() {
+            window.close();
         }
     }
 });
+
+
+

+ 141 - 8
src/main/resources/static/js/supplier-center/article/article-list.js

@@ -1,12 +1,24 @@
 var articleList = new Vue({
     el: '#articleList',
     data: {
+        refreshType: '',
+        hidden: '',
+        visibilityChange: '',
         listRecord: 30,
+        shopId: GLOBAL_SHOP_ID || 0,
         listQuery: {
+            articleId: '',
+            title: '',
+            publisher: '',
+            auditStatus: '',
+            typeId: '',
             pageNum: 1,
-            pageSize: 10,
+            pageSize: 10
         },
         pageInput: 1,
+        pageTotal: 0,
+        articleList: [],
+        articleTypeList: [],
     },
     computed: {
         pageTotal: function () {
@@ -28,39 +40,123 @@ var articleList = new Vue({
             return [1, 0, index - 2, index - 1, index, index + 1, index + 2, 0, total];
         }
     },
+    filters: {
+        formatDate(date) {
+            if (!date) return '---';
+            return dateFormat(new Date(date))
+        }
+    },
+    created() {
+        this.getArticleList();
+        this.fetchArticleCatagory()
+    },
     mounted() {
+        this.bindWindowHiddenOrVis()
         $('.navLayout').find('.navList').removeClass("on").find('.con').hide().find('a').removeClass("on");
         $('.navLayout').find('.navList').eq(2).addClass("on").find('.con').show().find('a').eq(0).addClass("on");
     },
     methods: {
+        // 获取文章列表
+        getArticleList() {
+            const that = this;
+            this.listQuery.shopId = this.shopId;
+            SupplierApi.GetArticleList(this.listQuery, function (res) {
+                console.log(res);
+                if (res.code === 0) {
+                    that.listRecord = res.data.total;
+                    that.articleList = res.data.list;
+                    that.pageTotal = res.data.pages
+                } else {
+                    CAIMEI.Alert(res.msg, '确定', false);
+                }
+            })
+        },
         //表格操作按钮点击
-        clickOption(type) {
+        clickOption(article, type) {
             const handles = {
                 1: this.toEdit,
                 2: this.changeStatus,
                 3: this.toDetail,
                 4: this.handleDelete,
             };
-            handles[type]()
+            handles[type](article)
         },
         //编辑
-        toEdit() {
-            window.open('/supplier/article/edit.html', '_blank')
+        toEdit(article) {
+            localStorage.setItem('articleId', article.articleId);
+            window.open('/supplier/article/edit.html')
         },
         //修改状态
-        changeStatus() {
+        changeStatus(article) {
+            let newStatus = 1;
+            if (article.status === 1) {
+                newStatus = 0
+            }
+            // return;
+            SupplierApi.ArticleStatusChange({
+                articleId: article.articleId,
+                shopId: this.shopId,
+                status: newStatus
+            }, function (res) {
+                if (res.code === 0) {
+                    // 不刷新数据更新
+                    article.status = newStatus;
+                    CAIMEI.dialog('修改文章状态成功!');
+                } else {
+                    CAIMEI.dialog('修改文章状态失败!');
+                }
+            })
         },
         //查看
         toDetail() {
         },
+        handleAddArticle() {
+            window.open('/supplier/article/edit.html')
+        },
+        handleSearchList() {
+            this.listQuery.pageNum = 1;
+            this.getArticleList();
+        },
+        fetchArticleCatagory() {
+            const that = this;
+            SupplierApi.ArticleCategory({}, function (res) {
+                if (res.code === 0) {
+                    // console.log(res);
+                    that.articleTypeList = res.data;
+                } else {
+                    CAIMEI.Alert(res.msg, '确定', false);
+                }
+            })
+        },
         //删除
-        handleDelete() {
+        handleDelete(article) {
+            const that = this;
+            const params = {
+                content: '确认删除改文章?',
+                cancelBtnText: '取消',
+                confitmBtnText: '删除'
+            };
+            CAIMEI.Popup(params, function () {
+                that.articleDelete(article)
+            })
+        },
+        articleDelete(article) {
+            const that = this;
+            SupplierApi.ArticleRemove({articleId: article.articleId}, function (res) {
+                if (res.code === 0) {
+                    that.getArticleList();
+                    CAIMEI.dialog('删除文章成功!');
+                } else {
+                    CAIMEI.dialog('删除文章失败!');
+                }
+            })
         },
         //页码跳转
         toPagination: function (pageNum) {
             if (pageNum <= this.pageTotal) {
                 this.listQuery.pageNum = pageNum;
-                console.log('页码跳转')
+                console.log('页码跳转');
+                this.getArticleList();
             }
         },
         checkNum: function () {
@@ -70,5 +166,42 @@ var articleList = new Vue({
                 this.pageInput = 1;
             }
         },
+        bindWindowHiddenOrVis() {
+            // 设置隐藏属性和改变可见属性的事件的名称
+            if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
+                this.hidden = "hidden";
+                this.visibilityChange = "visibilitychange";
+            } else if (typeof document.msHidden !== "undefined") {
+                this.hidden = "msHidden";
+                this.visibilityChange = "msvisibilitychange";
+            } else if (typeof document.webkitHidden !== "undefined") {
+                this.hidden = "webkitHidden";
+                this.visibilityChange = "webkitvisibilitychange";
+            }
+            // 如果浏览器不支持addEventListener 或 Page Visibility API 给出警告
+            if (typeof document.addEventListener === "undefined" || typeof document[this.hidden] === "undefined") {
+                console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
+            } else {
+                // 处理页面可见属性的改变
+                document.addEventListener(this.visibilityChange, this.handleVisibilityChange, false);
+            }
+        },
+        // 如果页面是展示状态 && 需要刷新列表,则刷新列表
+        handleVisibilityChange() {
+            const that = this;
+            this.refreshType = window.localStorage.getItem('refreshType');
+            if (document[that.hidden]) {
+                console.log(this.refreshType);
+                console.log('article list page is show');
+                if (this.refreshType) {
+                    that.listQuery.pageNum = 1;
+                    window.localStorage.removeItem('refreshType');
+                    that.getArticleList()
+                }
+            }
+        }
     }
 });
+
+
+

+ 68 - 13
src/main/resources/static/js/supplier-center/article/formMixin.js

@@ -4,21 +4,54 @@ var formMixin = {
         rules: {
             title: [{
                 required: true,
+                type: 'string',
                 message: '请输入文章标题',
                 trigger: 'blur'
             }, {
                 maxLength: 10,
                 minLength: 2,
                 message: '最大字符长度为10,最小字符长度为2',
-            }, {
-                pattern: /^abc/,
-                message: '必须以字符串abc开通',
             }],
-            desc:[{
+            label: [{
+                required: true,
+                message: '请输入文章标签',
+                trigger: ['blur','change']
+            }],
+            keyword: [{
                 required: true,
-                message: '请输入推荐语',
+                message: '请输入文章seo关键词',
                 trigger: 'blur'
-            }]
+            }],
+            publisher: [{
+                required: true,
+                message: '请输入发布人',
+                trigger: 'blur'
+            }],
+            recommendContent: [{
+                required: true,
+                message: '请输入文章推荐语',
+                trigger: 'blur'
+            }],
+            articleContent: [{
+                required: true,
+                message: '请输入文章内容',
+                trigger: 'change'
+            }],
+            typeId: [{
+                required: true,
+                message: '请选择文章分类',
+                trigger: 'change'
+            }],
+            guidanceImage: [{
+                required: true,
+                message: '请上传文章引导图',
+                trigger: 'change'
+            }],
+            status: [{
+                required: true,
+                message: '请选择文章状态',
+                trigger: 'change'
+            }],
         }
     },
     mounted() {
@@ -46,13 +79,22 @@ var formMixin = {
                 const rules = this.rules[key];
                 const input = document.querySelector(`.form-item[prop="${key}"] input`);
                 const textarea = document.querySelector(`.form-item[prop="${key}"] textarea`);
-                if (input) {
-                    input.addEventListener(rules[0].trigger, function () {
-                        that.validInputHandle(formData, key, rules)
-                    })
+                const trigger = rules[0].trigger.toString();
+                if(trigger.indexOf('blur') > -1){
+                    if (input) {
+                        input.addEventListener('blur', function () {
+                            that.validInputHandle(formData, key, rules)
+                        })
+                    }
+                    if (textarea) {
+                        textarea.addEventListener('blur', function () {
+                            that.validInputHandle(formData, key, rules)
+                        })
+                    }
                 }
-                if (textarea) {
-                    textarea.addEventListener(rules[0].trigger, function () {
+                if(trigger.indexOf('change') > -1){
+                    const  str = 'formData.' + key;
+                    that.$watch(str, function(newVal, oldVal){
                         that.validInputHandle(formData, key, rules)
                     })
                 }
@@ -67,7 +109,7 @@ var formMixin = {
             rules.forEach(function (rule, index) {
                 if (!validData.valid) return;
                 // 字符长度
-                const len = formData[key].trim().length;
+                const len = formData[key].toString().trim().length;
                 // 是否必填
                 if (rule.required && !formData[key]) {
                     validData.valid = false;
@@ -85,6 +127,19 @@ var formMixin = {
                 }
             });
             this.validData[key] = validData;
+        },
+        validAll(formData) {
+            for (let key in this.rules) {
+                const rules = this.rules[key];
+                this.validInputHandle(formData, key, rules);
+            }
+            for(let key in this.validData){
+                // console.log(key, this.validData[key].valid);
+                if(!this.validData[key].valid) {
+                    return Promise.reject(false)
+                }
+            }
+            return Promise.resolve(true)
         }
     }
 };

+ 33 - 0
src/main/resources/static/js/supplier-center/article/uploadMixin.js

@@ -0,0 +1,33 @@
+var uploadMixin = {
+    methods: {
+        initEditorOptions(editor, baseUrl) {
+            const that = this;
+            this.editor.config.zIndex = 333;
+            this.editor.config.height = 400;
+            this.editor.config.uploadImgMaxSize = 2 * 1024 * 1024;
+            this.editor.config.uploadImgMaxLength = 5; // 一次最多上传 5 个图片
+            this.editor.config.customUploadImg = function (resultFiles, insertImgFn) {
+                resultFiles.forEach(function (file) {
+                    // resultFiles 是 input 中选中的文件列表
+                    // insertImgFn 是获取图片 url 后,插入到编辑器的方法
+                    that.uploadImage(file).then(res => {
+                        insertImgFn(res);
+                    })
+                });
+            }
+        },
+        // 上传图片
+        uploadImage(file) {
+            const formData = new FormData();
+            formData.append('file', file);
+            return new Promise(function (resolve, reject) {
+                PublicApi.uploadimg(formData, function (res) {
+                    if (res.code === 0) {
+                        resolve(res.data);
+                    }
+                    reject()
+                });
+            })
+        }
+    }
+};

+ 2 - 1
src/main/resources/static/js/utils.js

@@ -300,4 +300,5 @@ CAIMEI.returnedTarget = function(){//对象合并 IE 兼容方法
             return target;
         };
     }
-}
+};
+

+ 1 - 1
src/main/resources/templates/encyclopedia/more.html

@@ -22,7 +22,7 @@
         <img src="/img/encyclopedia/01.png" alt="中胚层产品"/>
     </div>
     <article class="article">
-        <section class="section">
+        <section class="section" th:each="prod: ${list}">
             <a href="/encyclopedia/product-detail.html">
                 <div class="cover">
                     <img src="https://picsum.photos/246/246" alt=""/>

+ 83 - 42
src/main/resources/templates/supplier-center/article/article-edit.html

@@ -6,10 +6,12 @@
     <template th:replace="components/head-link"></template>
     <link th:href="@{/css/base/center.css(v=${version})}" rel="stylesheet" type="text/css">
     <link th:if="${pageId==1026}" th:href="@{/css/base/form.css(v=${version})}" rel="stylesheet" type="text/css">
-    <link th:href="@{/css/supplier-center/article/article-edit.css(v=${version})}" charset="UTF-8" rel="stylesheet" type="text/css">
+    <link th:href="@{/css/supplier-center/article/article-edit.css(v=${version})}" charset="UTF-8" rel="stylesheet"
+          type="text/css">
     <template th:replace="components/analysis"></template>
 </head>
 <body>
+<input type="hidden" th:value="${coreServer}" id="coreServer">
 <!-- 引用头部 -->
 <template th:replace="components/header"></template>
 
@@ -30,88 +32,125 @@
                 <div class="row">
                     <div class="top-tip">温馨提示:多发布文章,有利于曝光您的产品以及提高您产品的销售量,文章发布并且审核通过后<br/>可在信息中心搜索您的文章</div>
                     <form class="form">
+                        <!-- 标题 -->
                         <div class="form-item" required prop="title">
                             <label for="title" class="form-label"><em>*</em>标题:</label>
-                            <input id="title" class="form-control" placeholder="请输入文章标题" v-model="formData.title"/>
+                            <input id="title" name="title" class="form-control" placeholder="请输入文章标题"
+                                   v-model="formData.title"/>
                             <template v-if="validData['title'] && !validData['title'].valid">
                                 <div class="errTips" v-html="validData['title'].message"></div>
                             </template>
                         </div>
-                        <div class="form-item">
+                        <!-- 文章标签 -->
+                        <div class="form-item" required prop="label">
                             <label for="tag" class="form-label"><em>*</em>文章标签:</label>
-                            <input id="tag" class="form-control" placeholder=""/>
-                            <div class="errTips">请添加文章标签</div>
+                            <input id="tag" name="label" class="form-control" placeholder="多个标签请用英文逗号( , )分割,例如:美白,祛痘"
+                                   v-model="formData.label"/>
+                            <template v-if="validData['label'] && !validData['label'].valid">
+                                <div class="errTips" v-html="validData['label'].message"></div>
+                            </template>
                         </div>
+                        <!-- 预选标签列表 -->
                         <div class="tag-list">
-                            <div class="tag">美白<span class="close">×</span></div>
+                            <div v-for="(label, index) in articleLabels" class="tag"
+                                 :class="{active: checkLabel(index)}" @click.stop="labelClick(index)">{{label}}<span
+                                    class="close">×</span></div>
                         </div>
+                        <!-- 新增标签 -->
                         <div class="control-group">
-                            <input id="tagName" class="form-control tagName" placeholder="请输入标签名"/>
-                            <button class="form-button addTag">添加</button>
+                            <input id="tagName" name="addLabel" class="form-control tagName" placeholder="请输入标签名"
+                                   v-model="addLabelName"/>
+                            <button class="form-button addTag" type="button" @click.stop="addLabel">添加</button>
                         </div>
-                        <div class="form-item">
-                            <label for="seo" class="form-label"><em>*</em>SEO关键词:</label>
-                            <input id="seo" class="form-control" placeholder="请输入SEO关键词"/>
-                            <div class="errTips">请输入SEO关键词</div>
+                        <!-- SEO关键词 -->
+                        <div class="form-item" required prop="keyword">
+                            <label for="keyword" class="form-label"><em>*</em>SEO关键词:</label>
+                            <input id="keyword" type="text" name="keyword" class="form-control" placeholder="请输入SEO关键词"
+                                   v-model="formData.keyword"/>
+                            <template v-if="validData['keyword'] && !validData['keyword'].valid">
+                                <div class="errTips" v-html="validData['keyword'].message"></div>
+                            </template>
                         </div>
-                        <div class="form-item">
+                        <!-- 发布人 -->
+                        <div class="form-item" required prop="publisher">
                             <label for="postAuthor" class="form-label"><em>*</em>发布人:</label>
-                            <input id="postAuthor" class="form-control" placeholder="请输入发布人"/>
-                            <div class="errTips">请输入发布人</div>
+                            <input id="postAuthor" name="publisher" class="form-control" placeholder="请输入发布人"
+                                   v-model="formData.publisher"/>
+                            <template v-if="validData['publisher'] && !validData['publisher'].valid">
+                                <div class="errTips" v-html="validData['publisher'].message"></div>
+                            </template>
                         </div>
+                        <!-- 来源 -->
                         <div class="form-item">
                             <label for="source" class="form-label"><em>*</em>来源:</label>
-                            <input id="source" class="form-control" placeholder="请输入文章来源"/>
-                            <div class="errTips">请输入文章来源</div>
+                            <input id="source" name="source" class="form-control" placeholder="请输入文章来源"
+                                   v-model="formData.source"/>
+                            <template v-if="validData['source'] && !validData['source'].valid">
+                                <div class="errTips" v-html="validData['source'].message"></div>
+                            </template>
                         </div>
-                        <div class="form-item" required prop="desc">
+                        <!-- 推荐语 -->
+                        <div class="form-item" required prop="recommendContent">
                             <label for="desc" class="form-label"><em>*</em>推荐语:</label>
-                            <textarea id="desc" placeholder="请输入推荐语" rows="4" v-model="formData.desc" class="form-control"></textarea>
-                            <template v-if="validData['desc'] && !validData['desc'].valid">
-                                <div class="errTips" v-html="validData['desc'].message"></div>
+                            <textarea id="desc" name="recommendContent" placeholder="请输入推荐语" rows="4"
+                                      v-model="formData.recommendContent" class="form-control"></textarea>
+                            <template v-if="validData['recommendContent'] && !validData['recommendContent'].valid">
+                                <div class="errTips" v-html="validData['recommendContent'].message"></div>
                             </template>
                         </div>
-                        <div class="form-item" required prop="desc">
+                        <!-- 文章内容 -->
+                        <div class="form-item" required prop="articleContent">
                             <label class="form-label"><em>*</em>文章内容:</label>
                             <div id="editor"></div>
-                            <template v-if="validData['desc'] && !validData['desc'].valid">
-                                <div class="errTips" v-html="validData['desc'].message"></div>
+                            <template v-if="validData['articleContent'] && !validData['articleContent'].valid">
+                                <div class="errTips" v-html="validData['articleContent'].message"></div>
                             </template>
                         </div>
-                        <div class="form-item">
+                        <!-- 文章分类 -->
+                        <div class="form-item" required prop="typeId">
                             <label for="category" class="form-label"><em>*</em>文章分类:</label>
-                            <select id="category" class="form-control form-select">
-                                <option>请选择</option>
-                                <option>西游记</option>
-                                <option>红楼梦</option>
-                                <option>水浒卷</option>
-                                <option>三国演义</option>
+                            <select id="category" name="typeId" class="form-control form-select"
+                                    v-model="formData.typeId">
+                                <option value="">请选择</option>
+                                <template v-for="(typeInfo, index) in articleTypeList">
+                                    <option :value="typeInfo.typeId" :key="index">{{typeInfo.typeName}}</option>
+                                </template>
                             </select>
-                            <div class="errTips">请选择文章分类</div>
+                            <template v-if="validData['typeId'] && !validData['typeId'].valid">
+                                <div class="errTips" v-html="validData['typeId'].message"></div>
+                            </template>
                         </div>
-                        <div class="form-item">
+                        <!-- 引导图 -->
+                        <div class="form-item" required prop="guidanceImage">
                             <label class="form-label"><em>*</em>引导图:</label>
                             <label for="cover" class="upload-control">
-                                <span>+</span>
-                                <span>添加图片</span>
+                                <template v-if="!formData.guidanceImage">
+                                    <span>+</span>
+                                    <span>添加图片</span>
+                                </template>
+                                <img :src="formData.guidanceImage" alt="guidanceImage" v-show="formData.guidanceImage">
                             </label>
-                            <input type="file" id="cover" class="form-control" hidden/>
-                            <div class="errTips">请上传引导图</div>
+                            <input type="file" name="guidanceImage" id="cover" class="form-control" hidden
+                                   @change="fileInputChange(event)"/>
+                            <template v-if="validData['guidanceImage'] && !validData['guidanceImage'].valid">
+                                <div class="errTips" v-html="validData['guidanceImage'].message"></div>
+                            </template>
                         </div>
-                        <div class="form-item radio-group">
+                        <!-- 状态 -->
+                        <div class="form-item radio-group" required prop="status">
                             <div class="form-label"><em>*</em>状态:</div>
                             <div class="radio-control">
-                                <input id="on" type="radio" name="status" checked/>
+                                <input id="on" type="radio" value="1" name="status" v-model="formData.status"/>
                                 <label for="on" class="radio">启用</label>
                             </div>
                             <div class="radio-control">
-                                <input id="off" type="radio" name="status"/>
+                                <input id="off" type="radio" value="0" name="status" v-model="formData.status"/>
                                 <label for="off" class="radio">停用</label>
                             </div>
                         </div>
                         <div class="form-item btns">
-                            <button class="btn break">返回</button>
-                            <button class="btn submit">保存</button>
+                            <button class="btn break" @click="handleBack">返回</button>
+                            <button class="btn submit" @click="handleSave">保存</button>
                         </div>
                     </form>
                 </div>
@@ -128,6 +167,8 @@
         th:src="@{/js/common/serviceapi/supplier.service.js(v=${version})}"></script>
 <script charset="UTF-8" type="text/javascript"
         th:src="@{/js/supplier-center/article/formMixin.js(v=${version})}"></script>
+<script charset="UTF-8" type="text/javascript"
+        th:src="@{/js/supplier-center/article/uploadMixin.js(v=${version})}"></script>
 <script charset="UTF-8" type="text/javascript"
         th:src="@{/js/supplier-center/article/article-edit.js(v=${version})}"></script>
 </body>

+ 52 - 39
src/main/resources/templates/supplier-center/article/article-list.html

@@ -36,33 +36,37 @@
                     <div class="form-section">
                         <div class="form-item">
                             <label for="articleId" class="form-label">文章ID:</label>
-                            <input id="articleId" class="form-control" type="text" placeholder="请输入文章ID"/>
+                            <input id="articleId" class="form-control" v-model="listQuery.articleId" type="text" placeholder="请输入文章ID"/>
                         </div>
                         <div class="form-item">
                             <label for="articleTitle" class="form-label">文章标题:</label>
-                            <input id="articleTitle" class="form-control" type="text" placeholder="请输入文章标题"/>
+                            <input id="articleTitle" class="form-control" v-model="listQuery.title" type="text" placeholder="请输入文章标题"/>
                         </div>
                         <div class="form-item">
                             <label for="articleAuthor" class="form-label">发布人:</label>
-                            <input id="articleAuthor" class="form-control" type="text" placeholder="输入发布人"/>
+                            <input id="articleAuthor" class="form-control" v-model="listQuery.publisher" type="text" placeholder="输入发布人"/>
                         </div>
                         <div class="form-item">
                             <label for="articleCate" class="form-label">文章分类:</label>
-                            <select id="articleCate" class="form-control form-select">
-                                <option>请选择</option>
-                                <option>医美</option>
+                            <select id="articleCate" class="form-control form-select" v-model="listQuery.typeId" @change="getArticleList">
+                                <option value="">请选择</option>
+                                <template v-for="(typeInfo, index) in articleTypeList">
+                                    <option :value="typeInfo.typeId" :key="index">{{typeInfo.typeName}}</option>
+                                </template>
                             </select>
                         </div>
                         <div class="form-item">
                             <label for="articleStatus" class="form-label">审核状态:</label>
-                            <select id="articleStatus" class="form-control form-select">
-                                <option>全部</option>
-                                <option>审核通过</option>
+                            <select id="articleStatus" class="form-control form-select" v-model="listQuery.auditStatus"  @change="handleSearchList">
+                                <option value="">全部</option>
+                                <option value="1">待审核</option>
+                                <option value="2">审核通过</option>
+                                <option value="3">审核未通过</option>
                             </select>
                         </div>
                         <div class="form-item buttons">
-                            <button class="form-button search" type="button">搜索</button>
-                            <button class="form-button add" type="button">添加</button>
+                            <button class="form-button search" type="button" @click="handleSearchList">搜索</button>
+                            <button class="form-button add" type="button" @click="handleAddArticle">添加</button>
                         </div>
                     </div>
                 </div>
@@ -83,34 +87,43 @@
                             <th>状态</th>
                             <th>操作</th>
                         </tr>
-                        <tr v-for="i in 2" :key="i" class="tr-row">
-                            <td>9280</td>
-                            <td>新品上线</td>
-                            <td>
-                                <img class="cover" src="https://picsum.photos/200/300" alt="新品上线"/></td>
-                            <td class="title">
-                                <div class="title">丝丽焕活盈韧头丝丽焕活盈韧头丝丽焕活盈韧头</div>
-                            </td>
-                            <td>236</td>
-                            <td>236</td>
-                            <td><span class="state warning">待审核</span></td>
-                            <td class="time">
-                                <div class="time">2021-11-20 17:23</div>
-                            </td>
-                            <td>江江</td>
-                            <td class="time">
-                                <div class="time">2021-11-20 17:23</div>
-                            </td>
-                            <td><span class="state primary">已启用</span></td>
-                            <td class="option">
-                                <div class="option">
-                                    <button class="form-button edit" @click="clickOption(1)">编辑</button>
-                                    <button class="form-button stop" @click="clickOption(2)">停用</button>
-                                    <button class="form-button search" @click="clickOption(3)">查看</button>
-                                    <button class="form-button delete" @click="clickOption(4)">删除</button>
-                                </div>
-                            </td>
-                        </tr>
+                        <template v-for="(articleInfo, index) in articleList"  >
+                            <tr :key="index" class="tr-row">
+                                <td v-html="articleInfo.articleId"></td>
+                                <td v-html="articleInfo.typeName"></td>
+                                <td>
+                                    <img class="cover" :src="articleInfo.guidanceImage" :alt="articleInfo.title"/></td>
+                                <td class="title">
+                                    <div class="title" v-html="articleInfo.title"></div>
+                                </td>
+                                <td v-html="articleInfo.praiseNum">236</td>
+                                <td v-html="articleInfo.pvNum">236</td>
+                                <td>
+                                    <span class="state warning" v-if="articleInfo.auditStatus === 1">待审核</span>
+                                    <span class="state success" v-else-if="articleInfo.auditStatus === 2">审核通过</span>
+                                    <span class="state danger" v-else>审核失败</span>
+                                </td>
+                                <td class="time">
+                                    <div class="time">{{ articleInfo.publishDate | formatDate }}</div>
+                                </td>
+                                <td v-html="articleInfo.publisher"></td>
+                                <td class="time" v-if="articleInfo.createDate">
+                                    <div class="time">{{ articleInfo.createDate | formatDate}}</div>
+                                </td>
+                                <td>
+                                    <span class="state primary" v-if="articleInfo.status === 1">已启用</span>
+                                    <span class="state default" v-else>未启用</span>
+                                </td>
+                                <td class="option">
+                                    <div class="option">
+                                        <button class="form-button edit" @click="clickOption(articleInfo, 1)">编辑</button>
+                                        <button class="form-button stop" @click="clickOption(articleInfo, 2)">{{ articleInfo.status === 1 ? '停用':'启用' }}</button>
+                                        <button class="form-button search" @click="clickOption(articleInfo, 3)">查看</button>
+                                        <button class="form-button delete" @click="clickOption(articleInfo, 4)">删除</button>
+                                    </div>
+                                </td>
+                            </tr>
+                        </template>
                     </table>
                 </div>
                 <!--页码-->