Parcourir la source

Merge remote-tracking branch 'origin/developerA' into developerA

Aslee il y a 3 ans
Parent
commit
c8020e2cd5

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

@@ -4,14 +4,14 @@ 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
-    type: com.zaxxer.hikari.HikariDataSource
+    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
       maximum-pool-size: 15
@@ -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

+ 1 - 1
src/main/resources/static/css/supplier-center/encyclopedia/edit-page.css

@@ -98,7 +98,7 @@
         -webkit-box-orient: vertical;
         color: #e74c3c;
         font-size: 12px;
-        display: none;
+        /*display: none;*/
     }
 
     .valid-form .form-label {

+ 1 - 0
src/main/resources/static/js/common/ajax.service.js

@@ -32,6 +32,7 @@ var Http = {
                 dataType: "json",
                 headers: { 'X-Token': REV_TOKEN_ENV },
                 async:false,
+                // contentType: contentType,
                 contentType: option.json ? 'application/json;charset=UTF-8' : 'application/x-www-form-urlencoded',
                 beforeSend:function () {
                     // if (option.mask) {

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

@@ -4,6 +4,79 @@
  * auther ZHJY
  */
 var SupplierApi = {
+        ShopBaikeProductDelete: function(params, callback){ // 百科商品/仪器 删除
+            Http.AjaxService({
+                url:'/user/shop/baike/product/delete',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+
+
+        ShopBaikeProductTypeList: function(params, callback){ // 百科商品/仪器分类列表
+            Http.AjaxService({
+                url:'/user/shop/baike/product/type/list',
+                type:'get',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+
+        ShopBaikeProductStatusUpdate: function(params, callback){ // 供应商百科商品/仪器状态更新
+            Http.AjaxService({
+                url:'/user/shop/baike/product/status/update',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+
+        ShopBaikeProductSave: function(params, callback){ // 供应商百科商品/仪器信息保存
+            Http.AjaxService({
+                url:'/user/shop/baike/product/save',
+                type:'post',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+
+        GetShopBaikeProductList: function(params, callback){ // 供应商百科商品/仪器列表
+            Http.AjaxService({
+                url:'/user/shop/baike/product/list',
+                type:'get',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+
+        GetShopBaikeProductForm: function(params, callback){ // 供应商百科商品表单数据(回显数据)
+            Http.AjaxService({
+                url:'/user/shop/baike/product/form',
+                type:'get',
+                data:params,
+                json:false,
+            })
+            .then(function(res){
+                callback(res);
+            });
+        },
+
         UploadFile: function(params, callback){ // 供应商文章上传图片
             Http.AjaxService({
                 url:'/tools/image/upload/ckeditor',

+ 6 - 0
src/main/resources/static/js/product/alliance-page.js

@@ -110,6 +110,12 @@ var zplm = new Vue({
                 that.productAuthInfo = res.data;
                 that.isRequest = false;
             });
+            setTimeout(function(){
+                if(that.isRequest){
+                    that.isRequest = false;
+                    location.href = '/404.html'
+                }
+            }, 10000)
         },
 
         // 显示授权牌

+ 71 - 40
src/main/resources/static/js/supplier-center/encyclopedia/form-component.js

@@ -74,9 +74,19 @@ function createSelect() {
         data: function data() {
             return {
                 optionsVisible: false,
-                label: ''
+                label: '',
             };
         },
+        watch:{
+            value(nVal){
+                const that = this;
+                this.$children.forEach(function(o){
+                    if(o.value === nVal){
+                        that.label = o.label
+                    }
+                });
+            },
+        },
         mounted: function mounted() {
             var _this = this;
 
@@ -109,7 +119,7 @@ function createOption() {
             handleClick: function handleClick() {
                 this.$parent.$emit('change', this.value);
                 this.$parent.$data.optionsVisible = false;
-                this.$parent.$data.label = this.label;
+                // this.$parent.$data.label = this.label;
             }
         }
     };
@@ -143,61 +153,82 @@ function createUploadImage() {
         data: function data() {
             return {
                 files: [],
-                accept: '.jpg, .jpeg, .png, .gif'
+                accept: '.jpg, .jpeg, .png, .gif',
             };
         },
         created: function created() {
-            this.files = this.handleFilterImage(this.imgList);
+            // 初始化列表
+            this.initImagelist(this.imgList);
         },
-
         computed: {
+            // 当前选中的图片数量
             fileCount: function fileCount() {
                 return this.files.length;
             },
+            // 是否能选择图片
             canChooseImage: function canChooseImage() {
-                return !this.multiple && this.fileCount < 1 && this.fileCount < this.limit;
+                return (this.multiple && this.fileCount < this.limit) || (!this.multiple && this.fileCount === 0);
+            }
+        },
+        watch: {
+            imgList: function(nVal){
+                this.initImagelist(nVal)
             }
         },
+
         methods: {
+
+            // 初始化图片列表
+            initImagelist: function initImagelist(fileList = []){
+                if(fileList.length <=0) return;
+                this.files = [];
+                if(this.multiple){
+                    this.files = fileList.slice(0, this.limit);
+                }else{
+                    this.files.push(fileList[0]);
+                }
+            },
+
+            // 点击事件
             handleClick: function handleClick() {
                 this.$refs.file.click();
             },
 
             // 选择图片
             handleChooseImage: function handleChooseImage(e) {
+                var that = this;
                 var files = [].concat(_toConsumableArray(e.target.files));
-                this.createObjectUrl(files);
-                this.$emit('change', this.files);
-            },
-
-            // 将文件处理成可预览链接
-            createObjectUrl: function createObjectUrl(files) {
-                var _this2 = this;
-
-                if (!this.multiple && this.fileCount === 1) return;
-                if (this.fileCount === this.limit) return;
+                e.target.value = '';
+                // 如果能选取图片
+                if(!this.canChooseImage) return;
+                // 取合适数量的图片
                 files = this.handleFilterImage(files);
-                files.forEach(function (file) {
+                // 图片本地预览链接
+                files.forEach(function(file){
                     file.url = URL.createObjectURL(file);
-                    _this2.files.push(file);
+                    that.files.push(file);
                 });
+                this.$emit('change', this.files);
             },
 
-
-            // 筛选图片
+            // 筛选图片 单张 ||  limit张
             handleFilterImage: function handleFilterImage(files) {
-                if (this.multiple) {
-                    files = files.slice(0, this.limit - this.fileCount);
-                } else {
-                    files = files.slice(0, 1);
+                if(files.length <= 0) return [];
+                if(this.multiple){
+                    console.log(this.limit - this.fileCount);
+                    // 多选
+                    files = files.slice(0, this.limit - this.fileCount)
+                }else{
+                    // 单选
+                    files = files.slice(0, 1)
                 }
-                return files;
+                return files
             },
 
-
             // 删除图片
-            removeImage: function removeImage(index) {
+            removeImage: function removeImage(file, index) {
                 this.files.splice(index, 1);
+                this.$emit('remove', index);
             }
         }
     };
@@ -223,6 +254,10 @@ function createEditorComponent() {
             placeholder:{
                 type: String,
                 default: ''
+            },
+            text: {
+                type: String,
+                default: ''
             }
         },
         data() {
@@ -231,6 +266,12 @@ function createEditorComponent() {
                 editor: null
             }
         },
+        watch:{
+            text(nVal){
+                if(!this.editor) return;
+                this.editor.txt.html(this.value) // 重新设置编辑器内容
+            }
+        },
         created: function created() {
             window.editorCount++;
             this.editorId = 'editorId-' + window.editorCount;
@@ -249,7 +290,7 @@ function createEditorComponent() {
                 this.editor = new E('#' + this.editorId);
                 // 或者 const editor = new E( document.getElementById('div1') )
                 this.initEditorOptions();
-                this.editor.create()
+                this.editor.create();
             },
             // 富文本框配置
             initEditorOptions: function initEditorOptions() {
@@ -337,18 +378,14 @@ function  createInputGroup() {
                 const len = this.dataList.length;
                 if(len >= this.minLimit) return this.dataList;
                 const emptyList = this.setEmptyData(this.minLimit - len);
-                console.log(this.dataList);
-                console.log(emptyList);
                 return this.dataList.concat(emptyList);
             }
         },
         created: function(){
-            console.log(this.list);
             this.dataList = this.list;
         },
         watch:{
             list: function(nVal){
-                console.log(nVal);
                 this.dataList = nVal;
             }
         },
@@ -369,11 +406,10 @@ function  createInputGroup() {
                 }
                 return list
             },
-            handleRemove(item){
-                this.$emit('remove', item);
+            handleRemove(item, index){
+                this.$emit('remove', { item, index});
             },
             handleAddOnce(){
-                console.log(1111);
                 this.$emit('add')
             }
         }
@@ -427,18 +463,14 @@ function createQuestionGroup(){
                 const len = this.dataList.length;
                 if(len >= this.minLimit) return this.dataList;
                 const emptyList = this.setEmptyData(this.minLimit - len);
-                console.log(this.dataList);
-                console.log(emptyList);
                 return this.dataList.concat(emptyList);
             }
         },
         created: function(){
-            console.log(this.list);
             this.dataList = this.list;
         },
         watch:{
             list: function(nVal){
-                console.log(nVal);
                 this.dataList = nVal;
             }
         },
@@ -463,7 +495,6 @@ function createQuestionGroup(){
                 this.$emit('remove', item);
             },
             handleAddOnce(){
-                console.log(1111);
                 this.$emit('add')
             }
         }

+ 496 - 51
src/main/resources/static/js/supplier-center/encyclopedia/instrument-edit.js

@@ -4,11 +4,12 @@ const Option = createOption();
 const UploadImage = createUploadImage();
 const Editor = createEditorComponent();
 const InputGroup = createInputGroup();
-const QuestionGroup = createQuestionGroup()
+const QuestionGroup = createQuestionGroup();
 
 new Vue({
     el: '#productEdit',
-    components:{
+    mixins: [validFormMixin],
+    components: {
         'cm-radio': Radio,
         'cm-select': Select,
         'cm-option': Option,
@@ -17,64 +18,508 @@ new Vue({
         'cm-input-group': InputGroup,
         'cm-question-group': QuestionGroup
     },
-    data:{
-        status: 1,
-        options: [
-            {
-                value: '选项1',
-                label: '黄金糕',
-            },
-            {
-                value: '选项2',
-                label: '双皮奶',
-            },
-            {
-                value: '选项3',
-                label: '蚵仔煎',
-            },
-            {
-                value: '选项4',
-                label: '龙须面',
-            },
-            {
-                value: '选项5',
-                label: '北京烤鸭',
-            },
-        ],
-        selected: '',
-        youdian: '',
-        paramsList: [
-            {
-                name: '品牌',
-                value: '华硕'
-            },
-            {
-                name: '尺寸',
-                value: '30mm*30mm'
-            }
-        ],
-        placeholderList: [{
+    data: {
+        // 商品类型 1: 产品  2: 仪器
+        productId: 0,
+        commodityType: 2,
+        shopId: GLOBAL_SHOP_ID,
+        formData: {
+            // 产品名称
+            name: '',
+            // 产品别名
+            alias: '',
+            // 产品概述
+            discription: '',
+            // 产品图片
+            image: '',
+            // 认证链接
+            authLink: '',
+            // 认证二维码
+            authQrCode: '',
+            // 产品参数
+            paramList: [],
+            // 产品优点
+            advantage: '',
+            // 产品缺点
+            disadvantage: '',
+            // 产品原理
+            principle: '',
+            // 品牌
+            brand: '',
+            // 产地
+            producePlace: '',
+            // 上市时间
+            marketTime: '',
+            // 公司/厂商
+            company: '',
+            // NMPA认证时间
+            nmpaTime: '',
+            // 产品认证
+            authImageList: [],
+            // 适应人群
+            adaptiveMan: '',
+            // 不适应人群
+            unAdaptiveMan: '',
+            // 术前术后
+            aroundOperation: '',
+            // 效果展示图片列表
+            displayImageList: [],
+            // 常见问题
+            questionList: [],
+            // 产品类别
+            typeId: '',
+            // 产品状态
+            status: 1,
+        },
+        // 预览图片列表
+        imageList: [],
+        authImageList: [],
+        displayImageList: [],
+        authQrCodeList: [],
+        // 产品分类
+        typeList: [],
+
+        // 产品参数表单数据
+        paramsPlaceholderList: [{
             label: '例如:名牌',
             value: '请输入名牌信息'
         }],
-        minLimit: 1
+        paramsMinLimit: 2,
+        paramskeyMap: {
+            key: 'name',
+            value: 'content'
+        },
+
+        // 问题数据表单列表
+        questionPlaceHolderList: [{
+            label: '请输入问题',
+            value: '请输入回答'
+        }],
+        questionMinLimit: 2,
+        questionkeyMap: {
+            key: 'question',
+            value: 'answer'
+        },
+        // 表单校验规则
+        rules: {
+            // 产品名称
+            name: [{
+                type: 'string',
+                required: true,
+                message: '名称不能为空',
+                trigger: ['blur','change']
+            }],
+            // 产品别名
+            alias: [{
+                type: 'string',
+                required: true,
+                message: '别名不能为空',
+                trigger: ['blur','change']
+            }],
+            // 产品概述
+            discription: [{
+                type: 'string',
+                required: true,
+                message: '概述不能为空',
+                trigger: ['blur','change']
+            }],
+            // 产品图片
+            image: [{
+                type: 'string',
+                required: true,
+                message: '图片不能为空',
+                trigger: 'change'
+            }],
+            // 认证链接
+            authLink: [{
+                type: 'string',
+                required: true,
+                message: '认证链接不能为空',
+                trigger: ['change', 'blur']
+            }],
+            // 认证二维码
+            authQrCode: [{
+                type: 'string',
+                required: true,
+                message: '认证二维码不能为空',
+                trigger: 'change'
+            }],
+            // 产品参数
+            paramList: [{
+                type: 'array',
+                required: true,
+                message: '参数信息不能为空',
+                trigger: ['change', 'blur'],
+                valid: ['name', 'content']
+            }],
+            // 产品优点
+            advantage: [{
+                type: 'string',
+                required: true,
+                message: '优点不能为空',
+                trigger: 'change'
+            }],
+            // 产品缺点
+            disadvantage: [{
+                type: 'string',
+                required: true,
+                message: '缺点不能为空',
+                trigger: 'change'
+            }],
+            // 产品原理
+            principle: [{
+                type: 'string',
+                required: true,
+                message: '原理不能为空',
+                trigger: 'change'
+            }],
+            // 品牌
+            brand: [{
+                type: 'string',
+                required: true,
+                message: '品牌不能为空',
+                trigger: ['change','blur']
+            }],
+            // 产地
+            producePlace: [{
+                type: 'string',
+                required: true,
+                message: '产地不能为空',
+                trigger: ['change','blur']
+            }],
+            // 上市时间
+            marketTime: [{
+                type: 'string',
+                required: true,
+                message: '上市时间不能为空',
+                trigger: ['change','blur']
+            }],
+            // 公司/厂商
+            company: [{
+                type: 'string',
+                required: true,
+                message: '公司/厂商不能为空',
+                trigger: ['change','blur']
+            }],
+            // NMPA认证时间
+            nmpaTime: [{
+                type: 'string',
+                required: true,
+                message: 'NMPA认证时间不能为空',
+                trigger: ['change','blur']
+            }],
+            // 产品认证
+            authImageList: [{
+                type: 'array',
+                required: true,
+                message: '仪器认证图片不能为空',
+                trigger: 'change'
+            }],
+            // 适应人群
+            adaptiveMan: [{
+                type: 'string',
+                required: true,
+                message: '适应人群不能为空',
+                trigger: 'change'
+            }],
+            // 不适应人群
+            unAdaptiveMan: [{
+                type: 'string',
+                required: true,
+                message: '不适应人群不能为空',
+                trigger: 'change'
+            }],
+            // 术前术后
+            aroundOperation: [{
+                type: 'string',
+                required: true,
+                message: '术前术后内容不能为空',
+                trigger: 'change'
+            }],
+            // 效果展示
+            displayImageList: [{
+                type: 'array',
+                required: true,
+                message: '效果展示图片不能为空',
+                trigger: 'change'
+            }],
+            // 常见问题
+            questionList: [{
+                type: 'array',
+                required: true,
+                message: '常见问题不能为空',
+                trigger: ['change','blur'],
+                valid: ['question', 'answer']
+            }],
+            // 产品类别
+            typeId: [{
+                type: 'number',
+                required: true,
+                message: '仪器类别不能为空',
+                trigger: 'change'
+            }],
+            // 产品状态
+            status: [{
+               type: 'number',
+                required: true,
+                message: '状态不能为空',
+                trigger: 'change'
+            }],
+        },
+    },
+    created() {
+        this.getTypeList();
+        this.getProductFormData();
+        this.resetQuestionListLimit();
+        this.resetParamsListLimit();
+        this.registerForm(this.formData, this.rules);
     },
-    mounted: function(){
+    mounted: function () {
         $('.navLayout').find('.navList').removeClass("on").find('.con').hide().find('a').removeClass("on");
         $('.navLayout').find('.navList').eq(3).addClass("on").find('.con').show().find('a').eq(1).addClass("on");
     },
-    watch: {
-    },
     methods: {
-        handleRemove(item){
-            console.log(item);
+        // 获取分类列表
+        getTypeList() {
+            const that = this;
+            SupplierApi.ShopBaikeProductTypeList({commodityType: this.commodityType}, function (res) {
+                that.typeList = res.data;
+                console.log(res);
+            })
         },
-        handleAdd(){
-            console.log(1111);
-            this.paramsList.push({
-                name: '',
-                value: ''
+
+        // 初始化表单数据
+        initFormData(formData){
+            console.log(formData);
+            // 初始化this.formData
+            for (var key in this.formData) {
+                if (formData.hasOwnProperty(key)) {
+                    // this.$set(this.formData, key, formData[key]);
+                    this.formData[key] = formData[key];
+                }
+            }
+
+            this.formData.marketTime = dateFormat(new Date(this.formData.marketTime), 'yyyy-MM-dd');
+            this.formData.nmpaTime = dateFormat(new Date(this.formData.nmpaTime), 'yyyy-MM-dd');
+
+            // 初始化图片列表 imageList  authImageList  displayImageList
+            this.imageList = this.initPreviewImageList([formData.image], { name: '授权图片' });
+            this.authImageList = this.initPreviewImageList(formData.authImageList, { name: '授权图片' });
+            this.displayImageList = this.initPreviewImageList(formData.displayImageList, { name: '效果图' });
+        },
+
+        // 初始化图片
+        initPreviewImageList(imageList, options){
+            if(!options){
+                options.name = '图片'
+            }
+
+            return imageList.map(function(item){
+                return {
+                    name: options.name,
+                    url: item
+                }
+            });
+        },
+
+
+        // 获取表单数据
+        getProductFormData() {
+            this.productId = localStorage.getItem('productId');
+            localStorage.removeItem('productId');
+
+            if(!this.productId) return;
+
+            const that = this;
+            SupplierApi.GetShopBaikeProductForm({ productId: this.productId }, function(res){
+                if(res.code === 0){
+                    that.initFormData(res.data);
+                }else{
+                    CAIMEI.dialog('获取产品数据失败', false);
+                    setTimeout(function () {
+                        that.handleBack();
+                    }, 2000);
+                }
+            });
+        },
+        // 保存表单数据
+        saveFormData() {
+            const that = this;
+            const params = {
+                ...this.formData,
+                shopId: this.shopId,
+                commodityType: this.commodityType,
+                paramList: JSON.stringify(this.formData.paramList),
+                questionList: JSON.stringify(this.formData.questionList)
+            };
+
+            if(this.productId) params.productId = this.productId;
+
+            SupplierApi.ShopBaikeProductSave(params, function(res){
+                if(res.code === 0) {
+                    CAIMEI.dialog('保存成功', false);
+                    setTimeout(function () {
+                        that.handleBack();
+                    }, 2000);
+                }else{
+                    CAIMEI.Alert(res.msg, '确认', false)
+                }
+            })
+        },
+
+        // 返回文章列表页面
+        handleBack: function handleBack() {
+            localStorage.removeItem('target-name');
+            window.open('/supplier/encyclopedia/product-list.html', 'supplier-instrument-list');
+            window.close();
+        },
+
+        // 保存事件
+        handleSave() {
+            const that = this;
+            // that.saveFormData();
+            this.validFormData(this.formData, this.rules).then(res=>{
+                console.log(res);
+                that.saveFormData()
+            }).catch(()=>{
+                CAIMEI.dialog('必填项不能为空', false)
             })
-        }
+        },
+
+        // 上传封面图片
+        handleUploadProductImage(files){
+            this.uploadImage(files[0]).then(res=>{
+                this.formData.image = res;
+                this.imageList.push({ url: res , name: '封面'})
+            }).catch(err=>{
+                console.log(err)
+            })
+        },
+
+        // 删除上传的封面图片
+        handleRemoveProductImage(){
+            this.formData.image = '';
+            this.imageList = [];
+        },
+
+        // 上传授权图片
+        handleUploadAuthImage(files){
+            const that = this;
+            files.forEach(function (file) {
+                if(file.type){
+                    // resultFiles 是 input 中选中的文件列表
+                    // insertImgFn 是获取图片 url 后,插入到编辑器的方法
+                    that.uploadImage(file).then(function (res) {
+                        that.formData.authImageList.push(res);
+                        that.authImageList.push({ url: res, name: '图片' })
+                    });
+                }
+            });
+        },
+        // 删除上传的授权图片
+        handleRemoveAuthImage(index){
+             this.formData.authImageList.splice(index, 1);
+             this.authImageList.splice(index, 1);
+             console.log(this.formData.authImageList);
+             console.log(this.authImageList);
+        },
+
+        // 上传效果展示图片
+        handleUploadDisplayImageList(files){
+            const that = this;
+            files.forEach(function (file) {
+                if(file.type){
+                    // resultFiles 是 input 中选中的文件列表
+                    // insertImgFn 是获取图片 url 后,插入到编辑器的方法
+                    that.uploadImage(file).then(function (res) {
+                        that.formData.displayImageList.push(res);
+                        that.displayImageList.push({ url: res, name: '图片' })
+                    });
+                }
+            });
+        },
+        // 删除上传的效果展示图片
+        handleRemoveDisplayImageList(index){
+             this.formData.displayImageList.splice(index, 1);
+             this.displayImageList.splice(index, 1);
+        },
+
+
+        // 上传封面图片
+        handleUploadAuthQrCode(files){
+            this.uploadImage(files[0]).then(res=>{
+                this.formData.authQrCode = res;
+                this.authQrCodeList.push({ url: res , name: '封面'})
+            }).catch(err=>{
+                console.log(err)
+            })
+        },
+
+        // 删除上传的封面图片
+        handleRemoveAuthQrCode(){
+            this.formData.authQrCode = '';
+            this.authQrCodeList = [];
+        },
+
+
+        // 上传图片
+        uploadImage: function uploadImage(file) {
+            var 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();
+                });
+            });
+        },
+
+        // 初始化问题表单个数
+        resetParamsListLimit() {
+            for (let i = 0; i < this.paramsMinLimit; i++) {
+                this.formData.paramList.push({
+                    name: '',
+                    content: ''
+                });
+            }
+        },
+        // 移除参数
+        handleRemoveParams(params) {
+            console.log(params);
+            this.formData.paramList.splice(params.index, 1);
+        },
+        // 添加参数
+        handleAddParams() {
+            this.formData.paramList.push({
+                name: '',
+                content: ''
+            });
+            this.registerForm(this.formData, this.rules);
+        },
+
+
+        // 初始化问题表单个数
+        resetQuestionListLimit() {
+            for (let i = 0; i < this.questionMinLimit; i++) {
+                this.formData.questionList.push({
+                    question: '',
+                    answer: '',
+                });
+            }
+        },
+        // 移除问题
+        handleRemoveQuestion(question) {
+            this.formData.paramList.splice(question.index, 1);
+        },
+        // 添加问题
+        handleAddQuestion() {
+            this.formData.questionList.push({
+                question: '',
+                answer: '',
+            });
+            this.registerForm(this.formData, this.rules);
+        },
     }
 });

+ 31 - 31
src/main/resources/static/js/supplier-center/encyclopedia/instrument-list.js

@@ -2,19 +2,19 @@
 
 console.log(123);
 
-var instrumentList = new Vue({
-    el: '#instrumentList',
+var productList = new Vue({
+    el: '#productList',
     data: {
-        name: 'supplier-article-list',
+        name: 'supplier-instrument-list',
         refreshType: '',
         hidden: '',
         visibilityChange: '',
         listRecord: 0,
         shopId: GLOBAL_SHOP_ID || 0,
         listQuery: {
-            articleId: '',
-            title: '',
-            publisher: '',
+            commodityType: 2,
+            productId: '',
+            name: '',
             auditStatus: '',
             typeId: '',
             pageNum: 1,
@@ -22,8 +22,8 @@ var instrumentList = new Vue({
         },
         pageInput: 1,
         pageTotal: 0,
-        articleList: [],
-        articleTypeList: [],
+        productList: [],
+        productTypeList: [],
         categoryKeyMap: {
             name: 'typeName',
             value: 'typeId'
@@ -92,11 +92,11 @@ var instrumentList = new Vue({
         getArticleList: function getArticleList() {
             var that = this;
             this.listQuery.shopId = this.shopId;
-            SupplierApi.GetArticleList(this.listQuery, function (res) {
-                // console.log(res);
+            SupplierApi.GetShopBaikeProductList(this.listQuery, function (res) {
+                console.log(res);
                 if (res.code === 0) {
                     that.listRecord = res.data.total;
-                    that.articleList = res.data.list;
+                    that.productList = res.data.list;
                     that.pageTotal = res.data.pages;
                 } else {
                     CAIMEI.Alert(res.msg, '确定', false);
@@ -104,36 +104,36 @@ var instrumentList = new Vue({
             });
         },
         //表格操作按钮点击
-        clickOption: function clickOption(article, type) {
+        clickOption: function clickOption(product, type) {
             var handles = {
                 1: this.toEdit,
                 2: this.changeStatus,
                 3: this.toDetail,
                 4: this.handleDelete
             };
-            handles[type](article);
+            handles[type](product);
         },
         //跳转编辑页面
-        toEdit: function toEdit(article) {
-            localStorage.setItem('articleId', article.articleId);
+        toEdit: function toEdit(product) {
+            localStorage.setItem('productId', product.productId);
             window.open('/supplier/encyclopedia/instrument-edit.html');
         },
         //修改状态
-        changeStatus: function changeStatus(article) {
+        changeStatus: function changeStatus(product) {
             var newStatus = 1;
 
-            if (article.status === 1) {
+            if (product.status === 1) {
                 newStatus = 0;
             }
 
-            SupplierApi.ArticleStatusChange({
-                articleId: article.articleId,
+            SupplierApi.ShopBaikeProductStatusUpdate({
+                productId: product.productId,
                 shopId: this.shopId,
                 status: newStatus
             }, function (res) {
                 if (res.code === 0) {
                     // 不刷新数据更新
-                    article.status = newStatus;
+                    product.status = newStatus;
                     CAIMEI.dialog('修改状态成功!');
                 } else {
                     CAIMEI.dialog('修改状态失败!');
@@ -141,10 +141,10 @@ var instrumentList = new Vue({
             });
         },
         //查看
-        toDetail: function toDetail(article) {
-            if (article.auditStatus !== 2) return CAIMEI.dialog('请等待审核通过后查看!');
-            if (!article.status) return CAIMEI.dialog('请未启后查看!');
-            window.open('/encyclopedia/instrument-' + article.articleId + '.html');
+        toDetail: function toDetail(product) {
+            if (product.auditStatus !== 2) return CAIMEI.dialog('请等待审核通过后查看!');
+            if (!product.status) return CAIMEI.dialog('请未启后查看!');
+            window.open('/encyclopedia/instrument-' + product.productId + '.html');
         },
         // 跳转添加文章页面
         handleAddArticle: function handleAddArticle() {
@@ -158,16 +158,16 @@ var instrumentList = new Vue({
         // 获取文章列表
         fetchArticleCatagory: function fetchArticleCatagory() {
             var that = this;
-            SupplierApi.ArticleCategory({}, function (res) {
+            SupplierApi.ShopBaikeProductTypeList({ commodityType: 1 }, function (res) {
                 if (res.code === 0) {
-                    that.articleTypeList = res.data;
+                    that.productTypeList = res.data;
                 } else {
                     CAIMEI.Alert(res.msg, '确定', false);
                 }
             });
         },
         //删除确认
-        handleDelete: function handleDelete(article) {
+        handleDelete: function handleDelete(product) {
             var that = this;
             var params = {
                 content: '确认删除该商品信息?',
@@ -175,14 +175,14 @@ var instrumentList = new Vue({
                 confitmBtnText: '删除'
             };
             CAIMEI.Popup(params, function () {
-                that.articleDelete(article);
+                that.productDelete(product);
             });
         },
         // 删除文章
-        articleDelete: function articleDelete(article) {
+        productDelete: function productDelete(product) {
             var that = this;
-            SupplierApi.ArticleRemove({
-                articleId: article.articleId
+            SupplierApi.ShopBaikeProductDelete({
+                productId: product.productId
             }, function (res) {
                 if (res.code === 0) {
                     that.getArticleList();

+ 459 - 50
src/main/resources/static/js/supplier-center/encyclopedia/product-edit.js

@@ -8,7 +8,8 @@ const QuestionGroup = createQuestionGroup()
 
 new Vue({
     el: '#productEdit',
-    components:{
+    mixins: [validFormMixin],
+    components: {
         'cm-radio': Radio,
         'cm-select': Select,
         'cm-option': Option,
@@ -17,64 +18,472 @@ new Vue({
         'cm-input-group': InputGroup,
         'cm-question-group': QuestionGroup
     },
-    data:{
-        status: 1,
-        options: [
-            {
-                value: '选项1',
-                label: '黄金糕',
-            },
-            {
-                value: '选项2',
-                label: '双皮奶',
-            },
-            {
-                value: '选项3',
-                label: '蚵仔煎',
-            },
-            {
-                value: '选项4',
-                label: '龙须面',
-            },
-            {
-                value: '选项5',
-                label: '北京烤鸭',
-            },
-        ],
-        selected: '',
-        youdian: '',
-        paramsList: [
-            {
-                name: '品牌',
-                value: '华硕'
-            },
-            {
-                name: '尺寸',
-                value: '30mm*30mm'
-            }
-        ],
-        placeholderList: [{
+    data: {
+        // 商品类型 1: 产品  2: 仪器
+        productId: 0,
+        commodityType: 1,
+        shopId: GLOBAL_SHOP_ID,
+        formData: {
+            // 产品名称
+            name: '',
+            // 产品别名
+            alias: '',
+            // 产品概述
+            discription: '',
+            // 产品图片
+            image: '',
+            // 产品参数
+            paramList: [],
+            // 产品优点
+            advantage: '',
+            // 产品缺点
+            disadvantage: '',
+            // 产品原理
+            principle: '',
+            // 品牌
+            brand: '',
+            // 产地
+            producePlace: '',
+            // 上市时间
+            marketTime: '',
+            // 公司/厂商
+            company: '',
+            // NMPA认证时间
+            nmpaTime: '',
+            // 产品认证
+            authImageList: [],
+            // 适应人群
+            adaptiveMan: '',
+            // 不适应人群
+            unAdaptiveMan: '',
+            // 术前术后
+            aroundOperation: '',
+            // 效果展示图片列表
+            displayImageList: [],
+            // 常见问题
+            questionList: [],
+            // 产品类别
+            typeId: '',
+            // 产品状态
+            status: 1,
+        },
+        // 预览图片列表
+        imageList: [],
+        authImageList: [],
+        displayImageList: [],
+        // 产品分类
+        typeList: [],
+
+        // 产品参数表单数据
+        paramsPlaceholderList: [{
             label: '例如:名牌',
             value: '请输入名牌信息'
         }],
-        minLimit: 1
+        paramsMinLimit: 2,
+        paramskeyMap: {
+            key: 'name',
+            value: 'content'
+        },
+
+        // 问题数据表单列表
+        questionPlaceHolderList: [{
+            label: '请输入问题',
+            value: '请输入回答'
+        }],
+        questionMinLimit: 2,
+        questionkeyMap: {
+            key: 'question',
+            value: 'answer'
+        },
+        // 表单校验规则
+        rules: {
+            // 产品名称
+            name: [{
+                type: 'string',
+                required: true,
+                message: '名称不能为空',
+                trigger: ['blur','change']
+            }],
+            // 产品别名
+            alias: [{
+                type: 'string',
+                required: true,
+                message: '别名不能为空',
+                trigger: ['blur','change']
+            }],
+            // 产品概述
+            discription: [{
+                type: 'string',
+                required: true,
+                message: '概述不能为空',
+                trigger: ['blur','change']
+            }],
+            // 产品图片
+            image: [{
+                type: 'string',
+                required: true,
+                message: '图片不能为空',
+                trigger: 'change'
+            }],
+            // 产品参数
+            paramList: [{
+                type: 'array',
+                required: true,
+                message: '参数信息不能为空',
+                trigger: ['change', 'blur'],
+                valid: ['name', 'content']
+            }],
+            // 产品优点
+            advantage: [{
+                type: 'string',
+                required: true,
+                message: '优点不能为空',
+                trigger: 'change'
+            }],
+            // 产品缺点
+            disadvantage: [{
+                type: 'string',
+                required: true,
+                message: '缺点不能为空',
+                trigger: 'change'
+            }],
+            // 产品原理
+            principle: [{
+                type: 'string',
+                required: true,
+                message: '原理不能为空',
+                trigger: 'change'
+            }],
+            // 品牌
+            brand: [{
+                type: 'string',
+                required: true,
+                message: '品牌不能为空',
+                trigger: ['change','blur']
+            }],
+            // 产地
+            producePlace: [{
+                type: 'string',
+                required: true,
+                message: '产地不能为空',
+                trigger: ['change','blur']
+            }],
+            // 上市时间
+            marketTime: [{
+                type: 'string',
+                required: true,
+                message: '上市时间不能为空',
+                trigger: ['change','blur']
+            }],
+            // 公司/厂商
+            company: [{
+                type: 'string',
+                required: true,
+                message: '公司/厂商不能为空',
+                trigger: ['change','blur']
+            }],
+            // NMPA认证时间
+            nmpaTime: [{
+                type: 'string',
+                required: true,
+                message: 'NMPA认证时间不能为空',
+                trigger: ['change','blur']
+            }],
+            // 产品认证
+            authImageList: [{
+                type: 'array',
+                required: true,
+                message: '产品认证图片不能为空',
+                trigger: 'change'
+            }],
+            // 适应人群
+            adaptiveMan: [{
+                type: 'string',
+                required: true,
+                message: '适应人群不能为空',
+                trigger: 'change'
+            }],
+            // 不适应人群
+            unAdaptiveMan: [{
+                type: 'string',
+                required: true,
+                message: '不适应人群不能为空',
+                trigger: 'change'
+            }],
+            // 术前术后
+            aroundOperation: [{
+                type: 'string',
+                required: true,
+                message: '术前术后内容不能为空',
+                trigger: 'change'
+            }],
+            // 效果展示
+            displayImageList: [{
+                type: 'array',
+                required: true,
+                message: '效果展示图片不能为空',
+                trigger: 'change'
+            }],
+            // 常见问题
+            questionList: [{
+                type: 'array',
+                required: true,
+                message: '常见问题不能为空',
+                trigger: ['change','blur'],
+                valid: ['question', 'answer']
+            }],
+            // 产品类别
+            typeId: [{
+                type: 'number',
+                required: true,
+                message: '产品类别不能为空',
+                trigger: 'change'
+            }],
+            // 产品状态
+            status: [{
+               type: 'number',
+                required: true,
+                message: '状态不能为空',
+                trigger: 'change'
+            }],
+        },
     },
-    mounted: function(){
+    created() {
+        this.getTypeList();
+        this.getProductFormData();
+        this.resetQuestionListLimit();
+        this.resetParamsListLimit();
+        this.registerForm(this.formData, this.rules);
+    },
+    mounted: function () {
         $('.navLayout').find('.navList').removeClass("on").find('.con').hide().find('a').removeClass("on");
         $('.navLayout').find('.navList').eq(3).addClass("on").find('.con').show().find('a').eq(0).addClass("on");
     },
-    watch: {
-    },
     methods: {
-        handleRemove(item){
-            console.log(item);
+        // 获取分类列表
+        getTypeList() {
+            const that = this;
+            SupplierApi.ShopBaikeProductTypeList({commodityType: this.commodityType}, function (res) {
+                that.typeList = res.data;
+                console.log(res);
+            })
         },
-        handleAdd(){
-            console.log(1111);
-            this.paramsList.push({
-                name: '',
-                value: ''
+
+        // 初始化表单数据
+        initFormData(formData){
+            console.log(formData);
+            // 初始化this.formData
+            for (var key in this.formData) {
+                if (formData.hasOwnProperty(key)) {
+                    // this.$set(this.formData, key, formData[key]);
+                    this.formData[key] = formData[key];
+                }
+            }
+
+            this.formData.marketTime = dateFormat(new Date(this.formData.marketTime), 'yyyy-MM-dd');
+            this.formData.nmpaTime = dateFormat(new Date(this.formData.nmpaTime), 'yyyy-MM-dd');
+
+            // 初始化图片列表 imageList  authImageList  displayImageList
+            this.imageList = this.initPreviewImageList([formData.image], { name: '授权图片' });
+            this.authImageList = this.initPreviewImageList(formData.authImageList, { name: '授权图片' });
+            this.displayImageList = this.initPreviewImageList(formData.displayImageList, { name: '效果图' });
+        },
+
+        // 初始化图片
+        initPreviewImageList(imageList, options){
+            if(!options){
+                options.name = '图片'
+            }
+
+            return imageList.map(function(item){
+                return {
+                    name: options.name,
+                    url: item
+                }
+            });
+        },
+
+
+        // 获取表单数据
+        getProductFormData() {
+            this.productId = localStorage.getItem('productId');
+            localStorage.removeItem('productId');
+
+            if(!this.productId) return;
+
+            const that = this;
+            SupplierApi.GetShopBaikeProductForm({ productId: this.productId }, function(res){
+                if(res.code === 0){
+                    that.initFormData(res.data);
+                }else{
+                    CAIMEI.dialog('获取产品数据失败', false);
+                    setTimeout(function () {
+                        that.handleBack();
+                    }, 2000);
+                }
+            });
+        },
+        // 保存表单数据
+        saveFormData() {
+            const that = this;
+            const params = {
+                ...this.formData,
+                shopId: this.shopId,
+                commodityType: this.commodityType,
+                paramList: JSON.stringify(this.formData.paramList),
+                questionList: JSON.stringify(this.formData.questionList)
+            };
+
+            if(this.productId) params.productId = this.productId;
+
+            SupplierApi.ShopBaikeProductSave(params, function(res){
+                if(res.code === 0) {
+                    CAIMEI.dialog('保存成功', false);
+                    setTimeout(function () {
+                        that.handleBack();
+                    }, 2000);
+                }else{
+                    CAIMEI.Alert(res.msg, '确认', false)
+                }
             })
-        }
+        },
+
+        // 返回文章列表页面
+        handleBack: function handleBack() {
+            localStorage.removeItem('target-name');
+            window.open('/supplier/encyclopedia/product-list.html', 'supplier-product-list');
+            window.close();
+        },
+
+        // 保存事件
+        handleSave() {
+            console.log(this.formData);
+            const that = this;
+            // that.saveFormData();
+            this.validFormData(this.formData, this.rules).then(res=>{
+                that.saveFormData()
+            }).catch(()=>{
+                CAIMEI.dialog('必填项不能为空', false)
+            })
+        },
+
+        // 上传封面图片
+        handleUploadProductImage(files){
+            this.uploadImage(files[0]).then(res=>{
+                this.formData.image = res;
+                this.imageList.push({ url: res , name: '封面'})
+            }).catch(err=>{
+                console.log(err)
+            })
+        },
+
+        // 删除上传的封面图片
+        handleRemoveProductImage(){
+            this.formData.image = ''
+        },
+
+        // 上传授权图片
+        handleUploadAuthImage(files){
+            const that = this;
+            files.forEach(function (file) {
+                if(file.type){
+                    // resultFiles 是 input 中选中的文件列表
+                    // insertImgFn 是获取图片 url 后,插入到编辑器的方法
+                    that.uploadImage(file).then(function (res) {
+                        that.formData.authImageList.push(res);
+                        that.authImageList.push({ url: res, name: '图片' })
+                    });
+                }
+            });
+        },
+        // 删除上传的授权图片
+        handleRemoveAuthImage(index){
+             this.formData.authImageList.splice(index, 1);
+             this.authImageList.splice(index, 1);
+             console.log(this.formData.authImageList);
+             console.log(this.authImageList);
+        },
+
+        // 上传效果展示图片
+        handleUploadDisplayImageList(files){
+            const that = this;
+            files.forEach(function (file) {
+                if(file.type){
+                    // resultFiles 是 input 中选中的文件列表
+                    // insertImgFn 是获取图片 url 后,插入到编辑器的方法
+                    that.uploadImage(file).then(function (res) {
+                        that.formData.displayImageList.push(res);
+                        that.displayImageList.push({ url: res, name: '图片' })
+                    });
+                }
+            });
+        },
+        // 删除上传的效果展示图片
+        handleRemoveDisplayImageList(index){
+             this.formData.displayImageList.splice(index, 1);
+             this.displayImageList.splice(index, 1);
+        },
+
+
+
+        // 上传图片
+        uploadImage: function uploadImage(file) {
+            var 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();
+                });
+            });
+        },
+
+        // 初始化问题表单个数
+        resetParamsListLimit() {
+            for (let i = 0; i < this.paramsMinLimit; i++) {
+                this.formData.paramList.push({
+                    name: '',
+                    content: ''
+                });
+            }
+        },
+        // 移除参数
+        handleRemoveParams(params) {
+            console.log(params);
+            this.formData.paramList.splice(params.index, 1);
+        },
+        // 添加参数
+        handleAddParams() {
+            this.formData.paramList.push({
+                name: '',
+                content: ''
+            });
+            this.registerForm(this.formData, this.rules);
+        },
+
+
+        // 初始化问题表单个数
+        resetQuestionListLimit() {
+            for (let i = 0; i < this.questionMinLimit; i++) {
+                this.formData.questionList.push({
+                    question: '',
+                    answer: '',
+                });
+            }
+        },
+        // 移除问题
+        handleRemoveQuestion(question) {
+            this.formData.paramList.splice(question.index, 1);
+        },
+        // 添加问题
+        handleAddQuestion() {
+            this.formData.questionList.push({
+                question: '',
+                answer: '',
+            });
+            this.registerForm(this.formData, this.rules);
+        },
     }
 });

+ 29 - 29
src/main/resources/static/js/supplier-center/encyclopedia/product-list.js

@@ -5,16 +5,16 @@ console.log(123);
 var productList = new Vue({
     el: '#productList',
     data: {
-        name: 'supplier-article-list',
+        name: 'supplier-product-list',
         refreshType: '',
         hidden: '',
         visibilityChange: '',
         listRecord: 0,
         shopId: GLOBAL_SHOP_ID || 0,
         listQuery: {
-            articleId: '',
-            title: '',
-            publisher: '',
+            commodityType: 1,
+            productId: '',
+            name: '',
             auditStatus: '',
             typeId: '',
             pageNum: 1,
@@ -22,8 +22,8 @@ var productList = new Vue({
         },
         pageInput: 1,
         pageTotal: 0,
-        articleList: [],
-        articleTypeList: [],
+        productList: [],
+        productTypeList: [],
         categoryKeyMap: {
             name: 'typeName',
             value: 'typeId'
@@ -92,11 +92,11 @@ var productList = new Vue({
         getArticleList: function getArticleList() {
             var that = this;
             this.listQuery.shopId = this.shopId;
-            SupplierApi.GetArticleList(this.listQuery, function (res) {
-                // console.log(res);
+            SupplierApi.GetShopBaikeProductList(this.listQuery, function (res) {
+                console.log(res);
                 if (res.code === 0) {
                     that.listRecord = res.data.total;
-                    that.articleList = res.data.list;
+                    that.productList = res.data.list;
                     that.pageTotal = res.data.pages;
                 } else {
                     CAIMEI.Alert(res.msg, '确定', false);
@@ -104,36 +104,36 @@ var productList = new Vue({
             });
         },
         //表格操作按钮点击
-        clickOption: function clickOption(article, type) {
+        clickOption: function clickOption(product, type) {
             var handles = {
                 1: this.toEdit,
                 2: this.changeStatus,
                 3: this.toDetail,
                 4: this.handleDelete
             };
-            handles[type](article);
+            handles[type](product);
         },
         //跳转编辑页面
-        toEdit: function toEdit(article) {
-            localStorage.setItem('articleId', article.articleId);
+        toEdit: function toEdit(product) {
+            localStorage.setItem('productId', product.productId);
             window.open('/supplier/encyclopedia/product-edit.html');
         },
         //修改状态
-        changeStatus: function changeStatus(article) {
+        changeStatus: function changeStatus(product) {
             var newStatus = 1;
 
-            if (article.status === 1) {
+            if (product.status === 1) {
                 newStatus = 0;
             }
 
-            SupplierApi.ArticleStatusChange({
-                articleId: article.articleId,
+            SupplierApi.ShopBaikeProductStatusUpdate({
+                productId: product.productId,
                 shopId: this.shopId,
                 status: newStatus
             }, function (res) {
                 if (res.code === 0) {
                     // 不刷新数据更新
-                    article.status = newStatus;
+                    product.status = newStatus;
                     CAIMEI.dialog('修改状态成功!');
                 } else {
                     CAIMEI.dialog('修改状态失败!');
@@ -141,10 +141,10 @@ var productList = new Vue({
             });
         },
         //查看
-        toDetail: function toDetail(article) {
-            if (article.auditStatus !== 2) return CAIMEI.dialog('请等待审核通过后查看!');
-            if (!article.status) return CAIMEI.dialog('请未启后查看!');
-            window.open('/encyclopedia/product-' + article.articleId + '.html');
+        toDetail: function toDetail(product) {
+            if (product.auditStatus !== 2) return CAIMEI.dialog('请等待审核通过后查看!');
+            if (!product.status) return CAIMEI.dialog('请未启后查看!');
+            window.open('/encyclopedia/product-' + product.productId + '.html');
         },
         // 跳转添加文章页面
         handleAddArticle: function handleAddArticle() {
@@ -158,16 +158,16 @@ var productList = new Vue({
         // 获取文章列表
         fetchArticleCatagory: function fetchArticleCatagory() {
             var that = this;
-            SupplierApi.ArticleCategory({}, function (res) {
+            SupplierApi.ShopBaikeProductTypeList({ commodityType: 1 }, function (res) {
                 if (res.code === 0) {
-                    that.articleTypeList = res.data;
+                    that.productTypeList = res.data;
                 } else {
                     CAIMEI.Alert(res.msg, '确定', false);
                 }
             });
         },
         //删除确认
-        handleDelete: function handleDelete(article) {
+        handleDelete: function handleDelete(product) {
             var that = this;
             var params = {
                 content: '确认删除该商品信息?',
@@ -175,14 +175,14 @@ var productList = new Vue({
                 confitmBtnText: '删除'
             };
             CAIMEI.Popup(params, function () {
-                that.articleDelete(article);
+                that.productDelete(product);
             });
         },
         // 删除文章
-        articleDelete: function articleDelete(article) {
+        productDelete: function productDelete(product) {
             var that = this;
-            SupplierApi.ArticleRemove({
-                articleId: article.articleId
+            SupplierApi.ShopBaikeProductDelete({
+                productId: product.productId
             }, function (res) {
                 if (res.code === 0) {
                     that.getArticleList();

+ 186 - 0
src/main/resources/static/js/supplier-center/encyclopedia/validFormMixin.js

@@ -0,0 +1,186 @@
+const validFormMixin = {
+    data: {
+        validMessage: {}
+    },
+    methods: {
+        // 注册验证表单
+        registerForm: function registerForm(model, rules) {
+            var _this = this;
+
+            var _loop = function _loop(key) {
+                // 初始化验证信息
+                _this.$set(_this.validMessage, key, {
+                    valid: true,
+                    message: ''
+                });
+
+                rules[key].forEach(function (rule) {
+                    if (Array.isArray(rule.trigger)) {
+                        _this.registerTrigger(key, rule.trigger, model, rules);
+                    } else if (typeof rule.trigger === 'string') {
+                        _this.registerTrigger(key, [rule.trigger], model, rules);
+                    }
+                });
+            };
+
+            for (var key in rules) {
+                _loop(key);
+            }
+        },
+
+        // 验证所有表单信息
+        validFormData: function validFormData(model, rules) {
+            for (var key in model) {
+                this.validation(key, model, rules);
+            }
+            for (var _key in this.validMessage) {
+                if (!this.validMessage[_key].valid) {
+                    return Promise.reject(false);
+                }
+            }
+            return Promise.resolve(true);
+        },
+
+        // 绑定事件监听
+        registerTrigger: function registerTrigger(key, trigger, model, rules) {
+            var _this2 = this;
+            this.$nextTick(function () {
+                trigger.forEach(function (item) {
+                    // 如果是change 则使用vue中的watch进行数据变化的监听
+                    if (item === 'change') {
+                        _this2.$watch(function () {
+                            return model[key];
+                        }, function (nVal, oVal) {
+                            _this2.validation(key, model, rules);
+                        });
+                    } else {
+                        _this2.$nextTick(function(){
+                            var element = document.querySelector('[props="' + key + '"]');
+                            if (!element) return;
+                            var validControl = element.querySelectorAll('.valid-control');
+                            validControl.forEach(function (el, index) {
+                                el.addEventListener(item, function () {
+                                    _this2.validation(key, model, rules);
+                                });
+                            });
+                        })
+                    }
+                });
+            });
+        },
+
+        // 验证
+        validation: function validation(key, model, rules) {
+            var _this3 = this;
+            rules[key].forEach(function (rule) {
+                if (rule.type === 'string') {
+                    var validValue = model[key];
+                    _this3.validString(key, rule, validValue);
+                }
+                if (rule.type === 'number') {
+                    var validValue = parseFloat(model[key]);
+                    _this3.validNumber(key, rule, validValue);
+                }
+                if (rule.type === 'array'){
+                    _this3.validArray(key, rule ,model[key]);
+                }
+            });
+        },
+
+        // 验证数组
+        validArray: function validArray(key, rule ,validValue){
+            const validKeys = rule.valid || [];
+            let flag = false;
+            if(validKeys.length > 0){
+                flag = validValue.every(function (item) {
+                    let result = true;
+                    validKeys.forEach(function (key) {
+                        if (item[key] === '') {
+                            result = false
+                        }
+                    });
+                    return result
+                });
+            }else{
+                flag = validValue.length > 0
+            }
+
+            if(!flag) {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+            this.$set(this.validMessage, key, {
+                valid: true,
+                message: ''
+            });
+        },
+
+        // 验证字符串类型
+        validString: function validString(key, rule, validValue) {
+            if(!validValue) validValue = '';
+
+            if (rule.minLength && validValue.length < rule.minLength) {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+
+            if (rule.maxLength && validValue.length > rule.maxLength) {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+
+            if (rule.required && validValue.length <= 0) {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+
+            this.$set(this.validMessage, key, {
+                valid: true,
+                message: ''
+            });
+        },
+
+        // 验证数字类型
+        validNumber: function validNumber(key, rule, validValue) {
+            validValue = parseFloat(validValue);
+
+            if (rule.min && validValue < rule.min) {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+            if (rule.max && validValue > rule.max) {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+            if (rule.required && typeof validValue !== 'number') {
+                this.$set(this.validMessage, key, {
+                    valid: false,
+                    message: rule.message
+                });
+                return;
+            }
+            this.$set(this.validMessage, key, {
+                valid: true,
+                message: ''
+            });
+        }
+    },
+};

+ 7 - 7
src/main/resources/templates/supplier-center/encyclopedia/components/form-component.html

@@ -1,10 +1,10 @@
 <!-- 图片上传 -->
 <script type="text/html" id="imageUpload">
     <div class="cm image-upload">
-        <template v-if="fileCount > 0">
+        <template v-if="files.length > 0">
             <div class="image border" v-for="(file,index) in files" :key="files">
                 <img :src="file.url" :alt="file.name"/>
-                <span class="remove" @click="removeImage(index)">&times;</span>
+                <span class="remove" @click="removeImage(file,index)">&times;</span>
             </div>
         </template>
         <div class="choose-image border" @click="handleClick" v-if="canChooseImage">
@@ -38,9 +38,9 @@
     <div class="input-group">
         <span class="add-btn" @click.stop="handleAddOnce" v-if="addText">{{ addText }}</span>
         <div class="cm form-group" v-for="(item, index) in showList" :key="index">
-            <input type="text" class="cm input  border" v-model="item[keyMap.key]" :placeholder="getPlaceholder(index).label"/>
-            <input type="text" class="cm input  border" v-model="item[keyMap.value]" :placeholder="getPlaceholder(index).value"/>
-            <span class="remove" v-if="showList.length > minLimit" @click.stop="handleRemove(item)">&times;</span>
+            <input type="text" class="cm input  border valid-control" v-model="item[keyMap.key]" :placeholder="getPlaceholder(index).label"/>
+            <input type="text" class="cm input  border valid-control" v-model="item[keyMap.value]" :placeholder="getPlaceholder(index).value"/>
+            <span class="remove" v-if="showList.length > minLimit" @click.stop="handleRemove(item, index)">&times;</span>
         </div>
     </div>
 </script>
@@ -51,11 +51,11 @@
         <div class="cm form-group" v-for="(item, index) in showList" :key="index">
             <div class="question">
                 <div class="form-label"><em>*</em><span>问题{{ index +1 }}</span></div>
-                <input type="text" class="cm input max border" v-model="item[keyMap.key]" :placeholder="getPlaceholder(index).label"/>
+                <input type="text" class="cm input max border valid-control hello" v-model="item[keyMap.key]" :placeholder="getPlaceholder(index).label"/>
             </div>
             <div class="answer">
                 <div class="form-label"><em>*</em><span>答</span></div>
-                <textarea type="text" class="cm textarea border max no-resize " rows="3" v-model="item[keyMap.value]" :placeholder="getPlaceholder(index).value"></textarea>
+                <textarea type="text" class="cm textarea border max no-resize valid-control" rows="3" v-model="item[keyMap.value]" :placeholder="getPlaceholder(index).value"></textarea>
             </div>
             <span class="remove" v-if="showList.length > minLimit" @click.stop="handleRemove(item)">&times;</span>
         </div>

+ 107 - 83
src/main/resources/templates/supplier-center/encyclopedia/instrument-edit.html

@@ -25,7 +25,7 @@
             <span>&gt;</span>
             <span>百科文库</span>
             <span>&gt;</span>
-            <span>添加产品百科</span>
+            <span>添加仪器百科</span>
         </div>
         <div class="wrap clear">
             <!--左侧导航-->
@@ -37,141 +37,164 @@
                     <form class="valid-form">
                         <h2><em>*</em>产品简述</h2>
                         <!-- 产品名称 -->
-                        <div class="form-item" required>
-                            <div class="form-label"><em>*</em><span>产品名称</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入产品名称"/>
-                            <div class="valid-message">产品名称不能为空!</div>
+                        <div class="form-item" required props="name">
+                            <div class="form-label"><em>*</em><span>仪器名称</span></div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入仪器名称" v-model="formData.name"/>
+                            <div class="valid-message" v-if="!validMessage['name'].valid">{{ validMessage['name'].message }}</div>
                         </div>
                         <!-- 产品别名 -->
-                        <div class="form-item" required>
-                            <div class="form-label"><em>*</em><span>产品别名</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入英文名或其他名称"/>
-                            <div class="valid-message">产品别名不能为空!</div>
+                        <div class="form-item" required props="alias">
+                            <div class="form-label"><em>*</em><span>仪器别名</span></div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入英文名或其他名称" v-model="formData.alias"/>
+                            <div class="valid-message" v-if="!validMessage['alias'].valid">{{ validMessage['alias'].message }}</div>
                         </div>
                         <!-- 产品概述 -->
-                        <div class="form-item" required>
-                            <div class="form-label"><em>*</em><span>产品概述</span></div>
-                            <textarea class="cm textarea border max no-resize " rows="3"></textarea>
-                            <div class="valid-message">产品概述不能为空!</div>
+                        <div class="form-item" required props="discription">
+                            <div class="form-label"><em>*</em><span>仪器概述</span></div>
+                            <textarea class="cm textarea border max no-resize valid-control" rows="3" v-model="formData.discription"></textarea>
+                            <div class="valid-message" v-if="!validMessage['discription'].valid">{{ validMessage['discription'].message }}</div>
                         </div>
                         <!-- 产品图片 -->
-                        <div class="form-item" required>
-                            <div class="form-label"><em>*</em><span>产品图片</span></div>
-                            <cm-upload-image></cm-upload-image>
-                            <div class="valid-message">产品图片不能为空!</div>
+                        <div class="form-item" required props="image">
+                            <div class="form-label"><em>*</em><span>仪器图片</span></div>
+                            <cm-upload-image @change="handleUploadProductImage" @remove="handleRemoveProductImage" :img-list="imageList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['image'].valid">{{ validMessage['image'].message }}</div>
                         </div>
-                        <h2><em>*</em>产品参数</h2>
-                        <div class="form-item" required>
+                        <h2><em>*</em>正品识别</h2>
+                        <div class="form-item" required props="authLink">
+                            <div class="form-label"><em>*</em><span>认证链接</span></div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输认证链接" v-model="formData.authLink"/>
+                            <div class="valid-message" v-if="!validMessage['authLink'].valid">{{ validMessage['authLink'].message }}</div>
+                        </div>
+
+                        <div class="form-item" required props="authQrCode">
+                            <div class="form-label"><em>*</em><span>认证二维码</span></div>
+                            <cm-upload-image @change="handleUploadAuthQrCode" @remove="handleRemoveAuthQrCode" :img-list="authQrCodeList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['authQrCode'].valid">{{ validMessage['authQrCode'].message }}</div>
+                        </div>
+
+
+                        <h2><em>*</em>仪器参数</h2>
+                        <div class="form-item" required props="paramList">
                             <cm-input-group
-                                    :list="paramsList"
-                                    :placeholder-list="placeholderList"
-                                    :min-limit="minLimit"
+                                    :list="formData.paramList"
+                                    :placeholder-list="paramsPlaceholderList"
+                                    :min-limit="paramsMinLimit"
+                                    :key-map="paramskeyMap"
                                     add-text = '添加一条'
-                                    @remove="handleRemove"
-                                    @add="handleAdd"
+                                    @remove="handleRemoveParams"
+                                    @add="handleAddParams"
                             ></cm-input-group>
-                            <div class="valid-message">产品名称不能为空!</div>
+                            <div class="valid-message" v-if="!validMessage['paramList'].valid">{{ validMessage['paramList'].message }}</div>
                         </div>
-                        <h2><em>*</em>产品优点</h2>
-                        <div class="form-item" required>
-                            <cm-editor v-model="youdian"></cm-editor>
-                            <div class="valid-message">产品优点不能为空!</div>
+                        <h2><em>*</em>仪器优点</h2>
+                        <div class="form-item" required props="advantage">
+                            <cm-editor v-model="formData.advantage" :text="formData.advantage"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['advantage'].valid">{{ validMessage['advantage'].message }}</div>
                         </div>
-                        <h2><em>*</em>产品缺点</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">产品缺点不能为空!</div>
+                        <h2><em>*</em>仪器缺点</h2>
+                        <div class="form-item" required props="disadvantage">
+                            <cm-editor v-model="formData.disadvantage" :text="formData.disadvantage"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['disadvantage'].valid">{{ validMessage['disadvantage'].message }}</div>
                         </div>
-                        <h2><em>*</em>产品原理</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">产品原理不能为空!</div>
+                        <h2><em>*</em>仪器原理</h2>
+                        <div class="form-item" required props="principle">
+                            <cm-editor v-model="formData.principle" :text="formData.principle"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['principle'].valid">{{ validMessage['principle'].message }}</div>
                         </div>
-                        <h2><em>*</em>产品档案</h2>
+                        <h2><em>*</em>仪器档案</h2>
                         <!-- 品牌 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="brand">
                             <div class="form-label"><em>*</em><span>品牌</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入品牌"/>
-                            <div class="valid-message">品牌不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入品牌" v-model="formData.brand"/>
+                            <div class="valid-message" v-if="!validMessage['brand'].valid">{{ validMessage['brand'].message }}</div>
                         </div>
                         <!-- 产地 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="producePlace">
                             <div class="form-label"><em>*</em><span>产地</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入产地"/>
-                            <div class="valid-message">产地不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入产地" v-model="formData.producePlace"/>
+                            <div class="valid-message" v-if="!validMessage['producePlace'].valid">{{ validMessage['producePlace'].message }}</div>
                         </div>
                         <!-- 上市时间 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="marketTime">
                             <div class="form-label"><em>*</em><span>上市时间</span></div>
-                            <input type="date" class="cm input max border" placeholder="请选择上市时间"/>
-                            <div class="valid-message">上市时间不能为空!</div>
+                            <input type="date" class="cm input max border valid-control" placeholder="请选择上市时间" v-model="formData.marketTime"/>
+                            <div class="valid-message" v-if="!validMessage['marketTime'].valid">{{ validMessage['marketTime'].message }}</div>
                         </div>
                         <!-- 公司/厂商 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="company">
                             <div class="form-label"><em>*</em><span>公司/厂商</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入公司/厂商"/>
-                            <div class="valid-message">公司/厂商不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入公司/厂商" v-model="formData.company"/>
+                            <div class="valid-message" v-if="!validMessage['company'].valid">{{ validMessage['company'].message }}</div>
                         </div>
                         <!-- NMPA认证时间 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="nmpaTime">
                             <div class="form-label"><em>*</em><span>NMPA认证时间</span></div>
-                            <input type="date" class="cm input max border" placeholder="请选择NMPA认证时间"/>
-                            <div class="valid-message">请选择NMPA认证时间不能为空!</div>
+                            <input type="date" class="cm input max border valid-control" placeholder="请选择NMPA认证时间" v-model="formData.nmpaTime"/>
+                            <div class="valid-message" v-if="!validMessage['nmpaTime'].valid">{{ validMessage['nmpaTime'].message }}</div>
                         </div>
                         <!-- 产品认证 -->
-                        <div class="form-item" required>
-                            <div class="form-label"><em>*</em><span>产品认证</span></div>
-                            <cm-upload-image></cm-upload-image>
-                            <div class="valid-message">请上传产品认证信息!</div>
+                        <div class="form-item" required props="authImageList">
+                            <div class="form-label"><em>*</em><span>仪器认证</span></div>
+                            <cm-upload-image @change="handleUploadAuthImage" @remove="handleRemoveAuthImage" :multiple="true" :img-list="authImageList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['authImageList'].valid">{{ validMessage['authImageList'].message }}</div>
                         </div>
                         <h2><em>*</em>适应人群</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">适应人群不能为空!</div>
+                        <div class="form-item" required props="adaptiveMan">
+                            <cm-editor v-model="formData.adaptiveMan" :text="formData.adaptiveMan"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['adaptiveMan'].valid">{{ validMessage['adaptiveMan'].message }}</div>
                         </div>
                         <h2><em>*</em>不适应人群</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">不适应人群不能为空!</div>
+                        <div class="form-item" required props="unAdaptiveMan">
+                            <cm-editor v-model="formData.unAdaptiveMan" :text="formData.unAdaptiveMan"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['unAdaptiveMan'].valid">{{ validMessage['unAdaptiveMan'].message }}</div>
                         </div>
                         <h2><em>*</em>术前术后</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">产品原理不能为空!</div>
+                        <div class="form-item" required props="aroundOperation">
+                            <cm-editor v-model="formData.aroundOperation" :text="formData.aroundOperation"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['aroundOperation'].valid">{{ validMessage['aroundOperation'].message }}</div>
                         </div>
+                        <!-- 效果展示 -->
+                        <h2><em>*</em>效果展示</h2>
+                        <div class="form-item" required props="displayImageList">
+                            <cm-upload-image @change="handleUploadDisplayImageList" @remove="handleRemoveDisplayImageList" :multiple="true" :img-list="displayImageList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['displayImageList'].valid">{{ validMessage['displayImageList'].message }}</div>
+                        </div>
+
                         <h2><em>*</em>常见问题</h2>
-                        <div class="form-item" required>
+                        <div class="form-item" required props="questionList">
                             <cm-question-group
-                                    :list="paramsList"
-                                    :placeholder-list="placeholderList"
-                                    :min-limit="minLimit"
+                                    :list="formData.questionList"
+                                    :placeholder-list="questionPlaceHolderList"
+                                    :min-limit="questionMinLimit"
                                     add-text='添加一条'
-                                    @remove="handleRemove"
-                                    @add="handleAdd"
+                                    :key-map="questionkeyMap"
+                                    @remove="handleRemoveQuestion"
+                                    @add="handleAddQuestion"
                             ></cm-question-group>
-                            <div class="valid-message">请添加常见问题!</div>
+                            <div class="valid-message" v-if="!validMessage['questionList'].valid">{{ validMessage['questionList'].message }}</div>
                         </div>
                         <!-- 产品类别 -->
                         <div class="form-item" required>
-                            <div class="form-label"><em>*</em><span>产品类别</span></div>
-                            <cm-select v-model="selected" placeholder="请选择" class="cm-select">
-                                <cm-option v-for="(item, index) in options" :key="index" :label="item.label" :value="item.value"></cm-option>
+                            <div class="form-label"><em>*</em><span>仪器类别</span></div>
+                            <cm-select v-model="formData.typeId" placeholder="请选择" class="cm-select">
+                                <cm-option v-for="(item, index) in typeList" :key="index" :label="item.typeName" :value="item.typeId"></cm-option>
                             </cm-select>
-                            <div class="valid-message">请选择产品类别!</div>
+                            <div class="valid-message" v-if="!validMessage['typeId'].valid">{{ validMessage['typeId'].message }}</div>
                         </div>
                         <!-- 产品状态 -->
-                        <div class="form-item vertical" required>
-                            <div class="form-label"><em>*</em><span>产品状态</span></div>
+                        <div class="form-item vertical" required props="status">
+                            <div class="form-label"><em>*</em><span>状态</span></div>
                             <div class="form-group">
-                                <cm-radio class="cm-radio" :label="1" v-model="status">启用</cm-radio>
-                                <cm-radio class="cm-radio" :label="2" v-model="status">停用</cm-radio>
+                                <cm-radio class="cm-radio" :label="1" v-model="formData.status">启用</cm-radio>
+                                <cm-radio class="cm-radio" :label="0" v-model="formData.status">停用</cm-radio>
                             </div>
-                            <div class="valid-message">请选择产品状态!</div>
+                            <div class="valid-message" v-if="!validMessage['status'].valid">{{ validMessage['status'].message }}</div>
                         </div>
 
                         <div class="form-item vertical btns">
                             <button class="btn break">返回</button>
-                            <button class="btn submit">保存</button>
+                            <button class="btn submit" @click.prevent="handleSave">保存</button>
                         </div>
                     </form>
                 </div>
@@ -189,6 +212,7 @@
 <script charset="utf-8" type="text/javascript" th:src="@{/js/center.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/common/serviceapi/supplier.service.js(v=${version})}"></script>
 <script charset="UTF-8" type="text/javascript" th:src="@{/js/supplier-center/encyclopedia/form-component.js(v=${version})}"></script>
+<script charset="UTF-8" type="text/javascript" th:src="@{/js/supplier-center/encyclopedia/validFormMixin.js(v=${version})}"></script>
 <script charset="UTF-8" type="text/javascript" th:src="@{/js/supplier-center/encyclopedia/instrument-edit.js(v=${version})}"></script>
 </body>
 </html>

+ 28 - 28
src/main/resources/templates/supplier-center/encyclopedia/instrument-list.html

@@ -14,7 +14,7 @@
 <template th:replace="components/header"></template>
 
 <!-- 我的采美 -->
-<div id="instrumentList" class="article-list">
+<div id="productList" class="article-list">
     <div class="navLayout" v-cloak>
         <div v-if="isPC" class="top-row">
             <div class="crumbs">
@@ -34,25 +34,25 @@
                 <div class="row">
                     <div class="form-section">
                         <div class="form-item">
-                            <label for="articleId" class="form-label">文章ID:</label>
-                            <input id="articleId" class="form-control" v-model="listQuery.articleId" type="text" placeholder="请输入ID号"/>
+                            <label for="productId" class="form-label">仪器ID:</label>
+                            <input id="productId" class="form-control" v-model="listQuery.productId" type="text" placeholder="请输入仪器ID"/>
                         </div>
                         <div class="form-item">
-                            <label for="articleTitle" class="form-label">仪器名称:</label>
-                            <input id="articleTitle" class="form-control" v-model="listQuery.title" type="text" placeholder="请输入仪器名称"/>
+                            <label for="productTitle" class="form-label">仪器名称:</label>
+                            <input id="productTitle" class="form-control" v-model="listQuery.name" type="text" placeholder="请输入仪器名称"/>
                         </div>
                         <div class="form-item">
-                            <label for="articleCate" class="form-label">仪器分类:</label>
-                            <select id="articleCate" class="form-control form-select" v-model="listQuery.typeId" @change="getArticleList">
+                            <label for="productCate" class="form-label">仪器分类:</label>
+                            <select id="productCate" class="form-control form-select" v-model="listQuery.typeId" @change="getArticleList">
                                 <option value="">请选择</option>
-                                <template v-for="(typeInfo, index) in articleTypeList">
+                                <template v-for="(typeInfo, index) in productTypeList">
                                     <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" v-model="listQuery.auditStatus"  @change="handleSearchList">
+                            <label for="productStatus" class="form-label">审核状态:</label>
+                            <select id="productStatus" class="form-control form-select" v-model="listQuery.auditStatus"  @change="handleSearchList">
                                 <option value="">全部</option>
                                 <option value="1">待审核</option>
                                 <option value="2">审核通过</option>
@@ -71,8 +71,8 @@
                     <table class="table">
                         <tr>
                             <th>ID</th>
-                            <th>商品名称</th>
-                            <th>商品分类</th>
+                            <th>仪器名称</th>
+                            <th>仪器分类</th>
                             <th>阅读量</th>
                             <th>审核状态</th>
                             <th>发布时间</th>
@@ -80,36 +80,36 @@
                             <th>状态</th>
                             <th>操作</th>
                         </tr>
-                        <template v-for="(articleInfo, index) in articleList"  >
+                        <template v-for="(productInfo, index) in productList"  >
                             <tr :key="index" class="tr-row">
-                                <td v-text="articleInfo.articleId"></td>
+                                <td v-text="productInfo.productId"></td>
                                 <td class="title">
-                                    <div class="title" v-text="articleInfo.title" :title="articleInfo.title"></div>
+                                    <div class="title" v-text="productInfo.name" :title="productInfo.name"></div>
                                 </td>
-                                <td v-text="articleInfo.typeName"></td>
-                                <td v-text="articleInfo.pvNum"></td>
+                                <td v-text="productInfo.typeName"></td>
+                                <td v-text="productInfo.actualPv"></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 warning" v-if="productInfo.auditStatus === 1">待审核</span>
+                                    <span class="state success" v-else-if="productInfo.auditStatus === 2">审核通过</span>
                                     <span class="state danger" v-else>审核失败</span>
-                                    <span class="reason" v-if="articleInfo.auditStatus === 3" :title="'审核失败:' + articleInfo.failReason">?</span>
+                                    <span class="reason" v-if="productInfo.auditStatus === 3" :title="'审核失败:' + productInfo.failReason">?</span>
                                 </td>
                                 <td class="time">
-                                    <div class="time">{{ articleInfo.publishDate | formatDate }}</div>
+                                    <div class="time">{{ productInfo.publishTime | formatDate }}</div>
                                 </td>
-                                <td class="time" v-if="articleInfo.createDate">
-                                    <div class="time">{{ articleInfo.createDate | formatDate}}</div>
+                                <td class="time" v-if="productInfo.createDate">
+                                    <div class="time">{{ productInfo.addTime | formatDate}}</div>
                                 </td>
                                 <td>
-                                    <span class="state primary" v-if="articleInfo.status === 1">已启用</span>
+                                    <span class="state primary" v-if="productInfo.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>
+                                        <button class="form-button edit" @click="clickOption(productInfo, 1)">编辑</button>
+                                        <button class="form-button stop" @click="clickOption(productInfo, 2)">{{ productInfo.status === 1 ? '停用':'启用' }}</button>
+                                        <button class="form-button search" @click="clickOption(productInfo, 3)">查看</button>
+                                        <button class="form-button delete" @click="clickOption(productInfo, 4)">删除</button>
                                     </div>
                                 </td>
                             </tr>

+ 80 - 70
src/main/resources/templates/supplier-center/encyclopedia/product-edit.html

@@ -37,141 +37,150 @@
                     <form class="valid-form">
                         <h2><em>*</em>产品简述</h2>
                         <!-- 产品名称 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="name">
                             <div class="form-label"><em>*</em><span>产品名称</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入产品名称"/>
-                            <div class="valid-message">产品名称不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入产品名称" v-model="formData.name"/>
+                            <div class="valid-message" v-if="!validMessage['name'].valid">{{ validMessage['name'].message }}</div>
                         </div>
                         <!-- 产品别名 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="alias">
                             <div class="form-label"><em>*</em><span>产品别名</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入英文名或其他名称"/>
-                            <div class="valid-message">产品别名不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入英文名或其他名称" v-model="formData.alias"/>
+                            <div class="valid-message" v-if="!validMessage['alias'].valid">{{ validMessage['alias'].message }}</div>
                         </div>
                         <!-- 产品概述 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="discription">
                             <div class="form-label"><em>*</em><span>产品概述</span></div>
-                            <textarea class="cm textarea border max no-resize " rows="3"></textarea>
-                            <div class="valid-message">产品概述不能为空!</div>
+                            <textarea class="cm textarea border max no-resize valid-control" rows="3" v-model="formData.discription"></textarea>
+                            <div class="valid-message" v-if="!validMessage['discription'].valid">{{ validMessage['discription'].message }}</div>
                         </div>
                         <!-- 产品图片 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="image">
                             <div class="form-label"><em>*</em><span>产品图片</span></div>
-                            <cm-upload-image></cm-upload-image>
-                            <div class="valid-message">产品图片不能为空!</div>
+                            <cm-upload-image @change="handleUploadProductImage" @remove="handleRemoveProductImage" :img-list="imageList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['image'].valid">{{ validMessage['image'].message }}</div>
                         </div>
                         <h2><em>*</em>产品参数</h2>
-                        <div class="form-item" required>
+                        <div class="form-item" required props="paramList">
                             <cm-input-group
-                                    :list="paramsList"
-                                    :placeholder-list="placeholderList"
-                                    :min-limit="minLimit"
+                                    :list="formData.paramList"
+                                    :placeholder-list="paramsPlaceholderList"
+                                    :min-limit="paramsMinLimit"
+                                    :key-map="paramskeyMap"
                                     add-text = '添加一条'
-                                    @remove="handleRemove"
-                                    @add="handleAdd"
+                                    @remove="handleRemoveParams"
+                                    @add="handleAddParams"
                             ></cm-input-group>
-                            <div class="valid-message">产品名称不能为空!</div>
+                            <div class="valid-message" v-if="!validMessage['paramList'].valid">{{ validMessage['paramList'].message }}</div>
                         </div>
                         <h2><em>*</em>产品优点</h2>
-                        <div class="form-item" required>
-                            <cm-editor v-model="youdian"></cm-editor>
-                            <div class="valid-message">产品优点不能为空!</div>
+                        <div class="form-item" required props="advantage">
+                            <cm-editor v-model="formData.advantage" :text="formData.advantage"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['advantage'].valid">{{ validMessage['advantage'].message }}</div>
                         </div>
                         <h2><em>*</em>产品缺点</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">产品缺点不能为空!</div>
+                        <div class="form-item" required props="disadvantage">
+                            <cm-editor v-model="formData.disadvantage" :text="formData.disadvantage"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['disadvantage'].valid">{{ validMessage['disadvantage'].message }}</div>
                         </div>
                         <h2><em>*</em>产品原理</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">产品原理不能为空!</div>
+                        <div class="form-item" required props="principle">
+                            <cm-editor v-model="formData.principle" :text="formData.principle"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['principle'].valid">{{ validMessage['principle'].message }}</div>
                         </div>
                         <h2><em>*</em>产品档案</h2>
                         <!-- 品牌 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="brand">
                             <div class="form-label"><em>*</em><span>品牌</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入品牌"/>
-                            <div class="valid-message">品牌不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入品牌" v-model="formData.brand"/>
+                            <div class="valid-message" v-if="!validMessage['brand'].valid">{{ validMessage['brand'].message }}</div>
                         </div>
                         <!-- 产地 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="producePlace">
                             <div class="form-label"><em>*</em><span>产地</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入产地"/>
-                            <div class="valid-message">产地不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入产地" v-model="formData.producePlace"/>
+                            <div class="valid-message" v-if="!validMessage['producePlace'].valid">{{ validMessage['producePlace'].message }}</div>
                         </div>
                         <!-- 上市时间 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="marketTime">
                             <div class="form-label"><em>*</em><span>上市时间</span></div>
-                            <input type="date" class="cm input max border" placeholder="请选择上市时间"/>
-                            <div class="valid-message">上市时间不能为空!</div>
+                            <input type="date" class="cm input max border valid-control" placeholder="请选择上市时间" v-model="formData.marketTime"/>
+                            <div class="valid-message" v-if="!validMessage['marketTime'].valid">{{ validMessage['marketTime'].message }}</div>
                         </div>
                         <!-- 公司/厂商 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="company">
                             <div class="form-label"><em>*</em><span>公司/厂商</span></div>
-                            <input type="text" class="cm input max border" placeholder="请输入公司/厂商"/>
-                            <div class="valid-message">公司/厂商不能为空!</div>
+                            <input type="text" class="cm input max border valid-control" placeholder="请输入公司/厂商" v-model="formData.company"/>
+                            <div class="valid-message" v-if="!validMessage['company'].valid">{{ validMessage['company'].message }}</div>
                         </div>
                         <!-- NMPA认证时间 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="nmpaTime">
                             <div class="form-label"><em>*</em><span>NMPA认证时间</span></div>
-                            <input type="date" class="cm input max border" placeholder="请选择NMPA认证时间"/>
-                            <div class="valid-message">请选择NMPA认证时间不能为空!</div>
+                            <input type="date" class="cm input max border valid-control" placeholder="请选择NMPA认证时间" v-model="formData.nmpaTime"/>
+                            <div class="valid-message" v-if="!validMessage['nmpaTime'].valid">{{ validMessage['nmpaTime'].message }}</div>
                         </div>
                         <!-- 产品认证 -->
-                        <div class="form-item" required>
+                        <div class="form-item" required props="authImageList">
                             <div class="form-label"><em>*</em><span>产品认证</span></div>
-                            <cm-upload-image></cm-upload-image>
-                            <div class="valid-message">请上传产品认证信息!</div>
+                            <cm-upload-image @change="handleUploadAuthImage" @remove="handleRemoveAuthImage" :multiple="true" :img-list="authImageList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['authImageList'].valid">{{ validMessage['authImageList'].message }}</div>
                         </div>
                         <h2><em>*</em>适应人群</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">适应人群不能为空!</div>
+                        <div class="form-item" required props="adaptiveMan">
+                            <cm-editor v-model="formData.adaptiveMan" :text="formData.adaptiveMan"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['adaptiveMan'].valid">{{ validMessage['adaptiveMan'].message }}</div>
                         </div>
                         <h2><em>*</em>不适应人群</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">不适应人群不能为空!</div>
+                        <div class="form-item" required props="unAdaptiveMan">
+                            <cm-editor v-model="formData.unAdaptiveMan" :text="formData.unAdaptiveMan"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['unAdaptiveMan'].valid">{{ validMessage['unAdaptiveMan'].message }}</div>
                         </div>
                         <h2><em>*</em>术前术后</h2>
-                        <div class="form-item" required>
-                            <cm-editor></cm-editor>
-                            <div class="valid-message">产品原理不能为空!</div>
+                        <div class="form-item" required props="aroundOperation">
+                            <cm-editor v-model="formData.aroundOperation" :text="formData.aroundOperation"></cm-editor>
+                            <div class="valid-message" v-if="!validMessage['aroundOperation'].valid">{{ validMessage['aroundOperation'].message }}</div>
+                        </div>
+                        <!-- 效果展示 -->
+                        <h2><em>*</em>效果展示</h2>
+                        <div class="form-item" required props="displayImageList">
+                            <cm-upload-image @change="handleUploadDisplayImageList" @remove="handleRemoveDisplayImageList" :multiple="true" :img-list="displayImageList"></cm-upload-image>
+                            <div class="valid-message" v-if="!validMessage['displayImageList'].valid">{{ validMessage['displayImageList'].message }}</div>
                         </div>
+
                         <h2><em>*</em>常见问题</h2>
-                        <div class="form-item" required>
+                        <div class="form-item" required props="questionList">
                             <cm-question-group
-                                    :list="paramsList"
-                                    :placeholder-list="placeholderList"
-                                    :min-limit="minLimit"
+                                    :list="formData.questionList"
+                                    :placeholder-list="questionPlaceHolderList"
+                                    :min-limit="questionMinLimit"
                                     add-text='添加一条'
-                                    @remove="handleRemove"
-                                    @add="handleAdd"
+                                    :key-map="questionkeyMap"
+                                    @remove="handleRemoveQuestion"
+                                    @add="handleAddQuestion"
                             ></cm-question-group>
-                            <div class="valid-message">请添加常见问题!</div>
+                            <div class="valid-message" v-if="!validMessage['questionList'].valid">{{ validMessage['questionList'].message }}</div>
                         </div>
                         <!-- 产品类别 -->
                         <div class="form-item" required>
                             <div class="form-label"><em>*</em><span>产品类别</span></div>
-                            <cm-select v-model="selected" placeholder="请选择" class="cm-select">
-                                <cm-option v-for="(item, index) in options" :key="index" :label="item.label" :value="item.value"></cm-option>
+                            <cm-select v-model="formData.typeId" placeholder="请选择" class="cm-select">
+                                <cm-option v-for="(item, index) in typeList" :key="index" :label="item.typeName" :value="item.typeId"></cm-option>
                             </cm-select>
-                            <div class="valid-message">请选择产品类别!</div>
+                            <div class="valid-message" v-if="!validMessage['typeId'].valid">{{ validMessage['typeId'].message }}</div>
                         </div>
                         <!-- 产品状态 -->
-                        <div class="form-item vertical" required>
+                        <div class="form-item vertical" required props="status">
                             <div class="form-label"><em>*</em><span>产品状态</span></div>
                             <div class="form-group">
-                                <cm-radio class="cm-radio" :label="1" v-model="status">启用</cm-radio>
-                                <cm-radio class="cm-radio" :label="2" v-model="status">停用</cm-radio>
+                                <cm-radio class="cm-radio" :label="1" v-model="formData.status">启用</cm-radio>
+                                <cm-radio class="cm-radio" :label="0" v-model="formData.status">停用</cm-radio>
                             </div>
-                            <div class="valid-message">请选择产品状态!</div>
+                            <div class="valid-message" v-if="!validMessage['status'].valid">{{ validMessage['status'].message }}</div>
                         </div>
 
                         <div class="form-item vertical btns">
                             <button class="btn break">返回</button>
-                            <button class="btn submit">保存</button>
+                            <button class="btn submit" @click.prevent="handleSave">保存</button>
                         </div>
                     </form>
                 </div>
@@ -189,6 +198,7 @@
 <script charset="utf-8" type="text/javascript" th:src="@{/js/center.js(v=${version})}"></script>
 <script charset="utf-8" type="text/javascript" th:src="@{/js/common/serviceapi/supplier.service.js(v=${version})}"></script>
 <script charset="UTF-8" type="text/javascript" th:src="@{/js/supplier-center/encyclopedia/form-component.js(v=${version})}"></script>
+<script charset="UTF-8" type="text/javascript" th:src="@{/js/supplier-center/encyclopedia/validFormMixin.js(v=${version})}"></script>
 <script charset="UTF-8" type="text/javascript" th:src="@{/js/supplier-center/encyclopedia/product-edit.js(v=${version})}"></script>
 </body>
 </html>

+ 25 - 25
src/main/resources/templates/supplier-center/encyclopedia/product-list.html

@@ -34,25 +34,25 @@
                 <div class="row">
                     <div class="form-section">
                         <div class="form-item">
-                            <label for="articleId" class="form-label">文章ID:</label>
-                            <input id="articleId" class="form-control" v-model="listQuery.articleId" type="text" placeholder="请输入ID号"/>
+                            <label for="productId" class="form-label">商品ID:</label>
+                            <input id="productId" class="form-control" v-model="listQuery.productId" type="text" placeholder="请输入商品ID"/>
                         </div>
                         <div class="form-item">
-                            <label for="articleTitle" class="form-label">仪器名称:</label>
-                            <input id="articleTitle" class="form-control" v-model="listQuery.title" type="text" placeholder="请输入仪器名称"/>
+                            <label for="productTitle" class="form-label">商品名称:</label>
+                            <input id="productTitle" class="form-control" v-model="listQuery.name" type="text" placeholder="请输入商品名称"/>
                         </div>
                         <div class="form-item">
-                            <label for="articleCate" class="form-label">仪器分类:</label>
-                            <select id="articleCate" class="form-control form-select" v-model="listQuery.typeId" @change="getArticleList">
+                            <label for="productCate" class="form-label">商品分类:</label>
+                            <select id="productCate" class="form-control form-select" v-model="listQuery.typeId" @change="getArticleList">
                                 <option value="">请选择</option>
-                                <template v-for="(typeInfo, index) in articleTypeList">
+                                <template v-for="(typeInfo, index) in productTypeList">
                                     <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" v-model="listQuery.auditStatus"  @change="handleSearchList">
+                            <label for="productStatus" class="form-label">审核状态:</label>
+                            <select id="productStatus" class="form-control form-select" v-model="listQuery.auditStatus"  @change="handleSearchList">
                                 <option value="">全部</option>
                                 <option value="1">待审核</option>
                                 <option value="2">审核通过</option>
@@ -80,36 +80,36 @@
                             <th>状态</th>
                             <th>操作</th>
                         </tr>
-                        <template v-for="(articleInfo, index) in articleList"  >
+                        <template v-for="(productInfo, index) in productList"  >
                             <tr :key="index" class="tr-row">
-                                <td v-text="articleInfo.articleId"></td>
+                                <td v-text="productInfo.productId"></td>
                                 <td class="title">
-                                    <div class="title" v-text="articleInfo.title" :title="articleInfo.title"></div>
+                                    <div class="title" v-text="productInfo.name" :title="productInfo.name"></div>
                                 </td>
-                                <td v-text="articleInfo.typeName"></td>
-                                <td v-text="articleInfo.pvNum"></td>
+                                <td v-text="productInfo.typeName"></td>
+                                <td v-text="productInfo.actualPv"></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 warning" v-if="productInfo.auditStatus === 1">待审核</span>
+                                    <span class="state success" v-else-if="productInfo.auditStatus === 2">审核通过</span>
                                     <span class="state danger" v-else>审核失败</span>
-                                    <span class="reason" v-if="articleInfo.auditStatus === 3" :title="'审核失败:' + articleInfo.failReason">?</span>
+                                    <span class="reason" v-if="productInfo.auditStatus === 3" :title="'审核失败:' + productInfo.failReason">?</span>
                                 </td>
                                 <td class="time">
-                                    <div class="time">{{ articleInfo.publishDate | formatDate }}</div>
+                                    <div class="time">{{ productInfo.publishTime | formatDate }}</div>
                                 </td>
-                                <td class="time" v-if="articleInfo.createDate">
-                                    <div class="time">{{ articleInfo.createDate | formatDate}}</div>
+                                <td class="time" v-if="productInfo.createDate">
+                                    <div class="time">{{ productInfo.addTime | formatDate}}</div>
                                 </td>
                                 <td>
-                                    <span class="state primary" v-if="articleInfo.status === 1">已启用</span>
+                                    <span class="state primary" v-if="productInfo.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>
+                                        <button class="form-button edit" @click="clickOption(productInfo, 1)">编辑</button>
+                                        <button class="form-button stop" @click="clickOption(productInfo, 2)">{{ productInfo.status === 1 ? '停用':'启用' }}</button>
+                                        <button class="form-button search" @click="clickOption(productInfo, 3)">查看</button>
+                                        <button class="form-button delete" @click="clickOption(productInfo, 4)">删除</button>
                                     </div>
                                 </td>
                             </tr>