Browse Source

产品详情以及产品类别详情

zhuliu 1 year ago
parent
commit
3fdeaa3eed

+ 10 - 0
src/api/myApi/login.js

@@ -8,3 +8,13 @@ export function loginByAccount(params) {
     data:params
   })
 }
+
+//退出登录接口
+export function logout(params) {
+  return request({
+    url:'/xiaoshi-weixinback/account/logout',
+    method:'post',
+    data:params
+  })
+}
+

+ 1 - 1
src/api/myApi/product.js

@@ -30,7 +30,7 @@ export function addOrUpdateHotProduct(params){
 export function queryHotProductDetail(params){
   return request({
     url:'/xiaoshi-weixinback/product/queryHotProductDetail',
-    method:'post',
+    method:'get',
     params:params
   })
 }

+ 10 - 5
src/assets/css/theme.css

@@ -1,26 +1,31 @@
 html{
     --bg:#316192;
     --ph:#999;
-    --color:#fff; 
+    --color:#fff;
 }
 
 html[theme-type='#6768ab']{
     --bg:#6768ab;
     --ph:#999;
-    --color:#fff; 
+    --color:#fff;
 }
 html[theme-type='#316192']{
   --bg:#316192;
   --ph:#999;
-  --color:#fff; 
+  --color:#fff;
 }
 html[theme-type='#879cf3']{
   --bg:#879cf3;
   --ph:#999;
-  --color:#fff; 
+  --color:#fff;
 }
 body{
   --fm:思源黑体CN;
   --color1:#316192;
   --color2:#000000;
-}
+}
+.noWrap{
+  overflow: hidden;
+  white-space: nowrap;
+  text-overflow:ellipsis;
+}

+ 1 - 1
src/config/index.js

@@ -5,5 +5,5 @@ export default {
   host: window.location.host,
   imgURL: process.env.NODE_ENV !== 'production' ? 'https://xsip.cn' : 'http://192.168.1.19:8802',
   staticURL:process.env.NODE_ENV !== 'production' ? '139.224.24.90' : '192.168.1.24',
-  WebSocketPath: process.env.NODE_ENV === 'production' ? '139.224.24.90:8879' : '192.168.1.24:8877',
+  WebSocketPath: process.env.NODE_ENV === 'production' ? '139.224.24.90:8879' : '192.168.2.113:8902',
 }

+ 22 - 1
src/router/index.js

@@ -6,6 +6,8 @@ Vue.use(Router)
 /* Layout */
 import Layout from '../views/layout/Layout'
 
+import Store from '../store'
+
 /**
  * hidden: true                   if `hidden:true` will not show in the sidebar(default is false)
  * alwaysShow: true               if set true, will always show the root menu, whatever its child routes length
@@ -350,9 +352,28 @@ export const asyncRouterMap = [
   {path: '*', redirect: '/404', hidden: true}
 ]
 
-export default new Router({
+
+// export default new Router({
+//   // mode: 'history', //后端支持可开
+//   scrollBehavior: () => ({y: 0}),
+//   routes: constantRouterMap
+// })
+const route = new Router({
   // mode: 'history', //后端支持可开
   scrollBehavior: () => ({y: 0}),
   routes: constantRouterMap
 })
 
+// 在你的路由配置文件中
+route.afterEach((to, from) => {
+  console.log(to)
+  var obj = {
+    name:to.meta.title,
+    path:to.path
+  }
+  Store.commit('addHistory',obj);
+  Store.commit('addHistoryPath',to.path);
+});
+
+export default route
+

+ 2 - 1
src/store/getters.js

@@ -6,6 +6,7 @@ const getters = {
   name: state => state.user.name,
   roles: state => state.user.roles,
   addRouters: state => state.permission.addRouters,
-  routers: state => state.permission.routers
+  routers: state => state.permission.routers,
+  webSocket: state => state.user.webSocket,
 }
 export default getters

+ 5 - 1
src/store/index.js

@@ -5,13 +5,17 @@ import user from './modules/user'
 import permission from './modules/permission'
 import getters from './getters'
 
+import history from './modules/history'
+
+
 Vue.use(Vuex)
 
 const store = new Vuex.Store({
   modules: {
     app,
     user,
-    permission
+    permission,
+    history
   },
   getters
 })

+ 54 - 0
src/store/modules/history.js

@@ -0,0 +1,54 @@
+export default {
+  state: {
+    history:[],
+    historyPath:[],
+    currentPath:null
+  },
+
+  mutations: {
+    addHistoryPath(state,path){
+      let paths=state.historyPath.filter(item=>{
+          return item!==path;
+      })
+      paths.push(path);
+      state.historyPath=paths;
+      state.currentPath=path;
+    },
+    addHistory(state,history){
+      if(!history.name){
+        return
+      }
+        let index=-1;
+        state.history.forEach((item,i)=>{
+            if(item.path===history.path)
+                index=i;
+        })
+        if(index!==-1){
+            return;
+        }
+        state.history.push({
+            name:history.name,
+            path:history.path
+        })
+    },
+    removeHistory(state,path){
+        state.history=state.history.filter(item=>{
+            return item.path!==path;
+        })
+    },
+    removeHistoryPath(state,path){
+        state.historyPath=state.historyPath.filter(item=>{
+            return item!==path;
+        })
+        if(state.historyPath.length>0)
+            state.currentPath=state.historyPath[state.historyPath.length-1];
+        else
+            state.currentPath=null;
+    }
+
+  },
+
+  actions: {
+
+  }
+}

+ 10 - 4
src/store/modules/user.js

@@ -1,13 +1,14 @@
 // import { login, logout, getInfo } from '@/api/login'
-import { loginByAccount } from '@/api/myApi/login'
-import { getToken, setToken, removeToken } from '@/utils/auth'
+import { loginByAccount,logout } from '@/api/myApi/login'
+import { getToken, setToken, removeToken ,setCookie,removeCookie} from '@/utils/auth'
 
 const user = {
   state: {
     token: getToken(),
     name: '',
     avatar: '',
-    roles: []
+    roles: [],
+    webSocket: null,
   },
 
   mutations: {
@@ -22,7 +23,10 @@ const user = {
     },
     SET_ROLES: (state, roles) => {
       state.roles = roles
-    }
+    },
+    SET_WEB_SOCKET: (state, webSocket) => {
+      state.webSocket = webSocket
+    },
   },
 
   actions: {
@@ -40,6 +44,8 @@ const user = {
           const tokenStr = data.token
           commit('SET_NAME', data.name)
           commit('SET_AVATAR', data.fileGuid)
+          setCookie('SET_AVATAR', data.fileGuid)
+          setCookie('userId', data.uuid)
           setToken(tokenStr)
           commit('SET_TOKEN', tokenStr)
           resolve()

+ 1 - 1
src/styles/index.scss

@@ -96,7 +96,7 @@ a:hover {
   position: absolute;
   left: 0;
   right: 0;
-  width: 720px;
+  width:800px;
   padding: 35px 35px 15px 35px;
   margin: 20px auto;
 }

+ 10 - 0
src/utils/auth.js

@@ -16,3 +16,13 @@ export function removeToken() {
   return Cookies.remove(TokenKey)
   // return localStorage.removeItem(TokenKey)
 }
+
+export function setCookie(key,value) {
+  return Cookies.set(key,value)
+}
+export function getCookie(key) {
+  return Cookies.get(key)
+}
+export function removeCookie(key) {
+  return Cookies.remove(key)
+}

+ 7 - 4
src/utils/model/upload/index.vue

@@ -3,6 +3,7 @@
     <div class="myUpload1" v-if="show">
       <div class="myDemo">
         <el-upload
+          ref="uploadRef"
           class="upload-demo"
           action="#"
           :auto-upload="false"
@@ -43,7 +44,7 @@
                 }}</span>
               </div>
             </myTooltip>
-            <div class="type">{{ item.guid ? "已上传" : "待上传" }}</div>
+            <div class="type" v-if="autoUpload">{{ item.guid ? "已上传" : "待上传" }}</div>
             <div class="icon" @click="onRemove(item, fileList)">
               <i class="el-icon-close"></i>
             </div>
@@ -264,6 +265,8 @@ export default {
         }
       }
       this.$emit("on-change", file);
+
+      this.$refs.uploadRef.clearFiles()
       //是否立即上传
       if (this.autoUpload) {
         this.uploadFile(file)
@@ -437,7 +440,7 @@ export default {
   padding: 5px;
 }
 .myUpload1 {
-  width: calc(100% - 20px);
+  width: calc(100% - 10px);
   height: 100%;
   padding: 5px;
   display: flex;
@@ -448,7 +451,7 @@ export default {
   .myDemo {
     width: 100%;
     height: 100%;
-    flex: 1;
+    flex: 2;
   }
   .line {
     width: 1px;
@@ -459,7 +462,7 @@ export default {
     width: 100%;
     height: 100%;
     overflow-y: auto;
-    flex: 2;
+    flex: 3;
     ul {
       list-style-type: none;
       padding: 0 10px;

+ 9 - 4
src/views/layout/Layout.vue

@@ -3,13 +3,14 @@
     <sidebar class="sidebar-container"></sidebar>
     <div class="main-container">
       <navbar></navbar>
+      <history></history>
       <app-main></app-main>
     </div>
   </div>
 </template>
 
 <script>
-import { Navbar, Sidebar, AppMain } from './components'
+import { Navbar, Sidebar, AppMain,history } from './components'
 import ResizeMixin from './mixin/ResizeHandler'
 
 export default {
@@ -17,7 +18,8 @@ export default {
   components: {
     Navbar,
     Sidebar,
-    AppMain
+    AppMain,
+    history
   },
   mixins: [ResizeMixin],
   computed: {
@@ -33,8 +35,11 @@ export default {
         withoutAnimation: this.sidebar.withoutAnimation,
         mobile: this.device === 'mobile'
       }
-    }
-  }
+    },
+
+  },
+  created(){
+ },
 }
 </script>
 

+ 11 - 0
src/views/layout/components/AppMain.vue

@@ -8,12 +8,23 @@
 </template>
 
 <script>
+import { getCookie} from '@/utils/auth'
+import { webSocket } from "../mixin";
 export default {
   name: 'AppMain',
+  mixins: [webSocket],
   computed: {
     // key() {
     //   return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date()
     // }
+    userId(){
+      return getCookie('userId')
+    }
+  },
+  created(){
+    if(this.userId){
+      this.connectWebSocket(this.userId)
+    }
   }
 }
 </script>

+ 63 - 21
src/views/layout/components/Navbar.vue

@@ -1,23 +1,27 @@
 <template>
   <el-menu class="navbar" mode="horizontal">
-    <hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger>
-    <breadcrumb></breadcrumb>
-    <el-dropdown class="avatar-container" trigger="click">
-      <div class="avatar-wrapper">
-        <img class="user-avatar" :src="$commonJS.getFile(avatar)">
-        <i class="el-icon-caret-bottom"></i>
-      </div>
-      <el-dropdown-menu class="user-dropdown" slot="dropdown">
-        <router-link class="inlineBlock" to="/">
-          <el-dropdown-item>
-            首页
+      <hamburger class="hamburger-container" :toggleClick="toggleSideBar" :isActive="sidebar.opened"></hamburger>
+      <breadcrumb></breadcrumb>
+    <div class="screenfull" @click="toggleFullScreen" v-if="!isScreenFull">
+      全屏
+    </div>
+      <el-dropdown class="avatar-container" trigger="click">
+        <div class="avatar-wrapper">
+          <img class="user-avatar" :src="$commonJS.getFile(avatar)">
+          <i class="el-icon-caret-bottom"></i>
+        </div>
+        <el-dropdown-menu class="user-dropdown" slot="dropdown">
+          <router-link class="inlineBlock" to="/">
+            <el-dropdown-item>
+              首页
+            </el-dropdown-item>
+          </router-link>
+          <el-dropdown-item divided>
+            <span @click="logout" style="display:block;">退出</span>
           </el-dropdown-item>
-        </router-link>
-        <el-dropdown-item divided>
-          <span @click="logout" style="display:block;">退出</span>
-        </el-dropdown-item>
-      </el-dropdown-menu>
-    </el-dropdown>
+        </el-dropdown-menu>
+      </el-dropdown>
+
   </el-menu>
 </template>
 
@@ -25,6 +29,7 @@
 import { mapGetters } from 'vuex'
 import Breadcrumb from '@/components/Breadcrumb'
 import Hamburger from '@/components/Hamburger'
+import { getCookie } from '@/utils/auth'
 
 export default {
   components: {
@@ -34,10 +39,34 @@ export default {
   computed: {
     ...mapGetters([
       'sidebar',
-      'avatar'
-    ])
+      // 'avatar'
+    ]),
+    avatar(){
+      return getCookie('SET_AVATAR')
+    },
+
+  },
+  data() {
+    return {
+      isScreenFull:null
+    }
+  },
+  mounted(){
+    window.onresize = () => {
+        this.isScreenFull = this.getFullscreen()
+      }
   },
   methods: {
+    getFullscreen(){
+      return (
+        // 标准模式
+        document.fullscreenElement ||
+        // 兼容老旧浏览器的API
+        document.mozFullScreenElement ||
+        document.webkitFullscreenElement ||
+        document.msFullscreenElement
+      );
+    },
     toggleSideBar() {
       this.$store.dispatch('ToggleSideBar')
     },
@@ -45,6 +74,18 @@ export default {
       this.$store.dispatch('LogOut').then(() => {
         location.reload() // 为了重新实例化vue-router对象 避免bug
       })
+    },
+    toggleFullScreen() {
+      const elem = document.documentElement;
+      if (elem.requestFullscreen) {
+        elem.requestFullscreen();
+      } else if (elem.mozRequestFullScreen) {
+        elem.mozRequestFullScreen();
+      } else if (elem.webkitRequestFullscreen) {
+        elem.webkitRequestFullscreen();
+      } else if (elem.msRequestFullscreen) {
+        elem.msRequestFullscreen();
+      }
     }
   }
 }
@@ -69,8 +110,9 @@ export default {
   .screenfull {
     position: absolute;
     right: 90px;
-    top: 16px;
-    color: red;
+    top: 0px;
+    color: blue;
+    cursor: pointer;
   }
   .avatar-container {
     height: 50px;

+ 87 - 0
src/views/layout/components/history.vue

@@ -0,0 +1,87 @@
+<template>
+  <el-tabs type="card" v-if="history&&history.length>0"
+           :value="currentPath"
+           @tab-click="tabClick"
+           @tab-remove="tabRemove"
+           closable class="content">
+    <el-tab-pane v-for="item in history"
+                 :key="item.path"
+                 :label="item.name"
+                 :name="item.path">
+    </el-tab-pane>
+  </el-tabs>
+</template>
+
+<script>
+
+export default {
+  name: "Tab",
+  computed:{
+    history(){
+      return this.$store.state.history.history;
+    },
+    currentPath(){
+      return this.$store.state.history.currentPath;
+    }
+  },
+  mounted(){
+  },
+  methods:{
+    tabClick({name}){
+      this.$store.commit('addHistoryPath',name);
+      if(name!==this.$route.path){
+        this.$router.push(name);
+      }
+    },
+    tabRemove(path){
+      this.$store.commit('removeHistory',path);
+      this.$store.commit('removeHistoryPath',path);
+    }
+  }
+}
+</script>
+
+<style scoped>
+.content{
+  margin-top: 5px;
+  height: 35px;
+  user-select: none;
+}
+:deep(.el-tabs__nav-wrap){
+  height: 35px !important;
+  line-height: 35px !important;
+}
+:deep(.el-tabs__nav-next) , :deep(.el-tabs__nav-prev){
+  line-height: 35px !important;
+}
+:deep(.el-tabs__header){
+  height: 35px !important;
+  margin: 0;
+  border: none;
+}
+:deep(.el-tabs__item){
+  height: 30px;
+  margin-top: 2px;
+  margin-bottom: 2px;
+  border: 1px solid grey !important;
+  line-height: 30px;
+  padding: 0 10px 0 10px !important;
+  border-radius: 2px;
+}
+
+:deep(.el-tabs__item:not(:last-child)){
+  margin-right: 10px;
+}
+
+:deep(.is-active){
+  border-bottom:inherit;
+  background-color: lightcyan;
+}
+:deep(.el-tabs__nav){
+  border: none !important;
+  /*height: 35px;*/
+  /*1px solid #E4E7ED*/
+}
+
+</style>
+

+ 1 - 0
src/views/layout/components/index.js

@@ -1,3 +1,4 @@
 export { default as Navbar } from './Navbar'
 export { default as Sidebar } from './Sidebar'
 export { default as AppMain } from './AppMain'
+export { default as history } from './history'

+ 37 - 0
src/views/layout/mixin/index.js

@@ -0,0 +1,37 @@
+import Config from '@/config'
+import Store from '@/store'
+
+export const webSocket = {
+  methods: {
+    connectWebSocket(userId) {
+      let webSocket = new WebSocket(`ws://${Config.WebSocketPath}/xiaoshi-weixinback/ws/` + userId)
+      Store.commit('SET_WEB_SOCKET', webSocket)
+      webSocket.onopen = () => {
+        console.log('WebSocket连接成功')
+      }
+      webSocket.onmessage = async (e) => {
+        if (e.data.indexOf('{') == -1) {
+          return false
+        }
+        const { code, data, message } = JSON.parse(e.data)
+
+        if (code == 111) {
+          if (data.complete) {
+            this.$message.success(`导入完成`)
+          } else {
+          }
+        }
+
+      }
+      webSocket.onerror = () => {
+        console.log('WebSocket连接失败')
+      }
+      webSocket.onclose = () => {
+        console.log('WebSocket连接关闭')
+      }
+    }
+  }
+}
+
+
+

+ 9 - 10
src/views/oms/order/index.vue

@@ -21,10 +21,10 @@
       <div style="margin-top: 15px">
         <el-form :inline="true" :model="listQuery" size="small" label-width="140px">
           <el-form-item label="输入搜索:">
-            <el-input v-model="listQuery.orderSn" class="input-width" placeholder="工单编号"></el-input>
+            <el-input v-model="listQuery.num" class="input-width" placeholder="工单编号"></el-input>
           </el-form-item>
           <el-form-item label="工单联系人:">
-            <el-input v-model="listQuery.receiverKeyword" class="input-width" placeholder="联系人姓名"></el-input>
+            <el-input v-model="listQuery.contactPerson" class="input-width" placeholder="联系人姓名"></el-input>
           </el-form-item>
           <el-form-item label="提交时间:">
             <el-date-picker
@@ -36,7 +36,7 @@
             </el-date-picker>
           </el-form-item>
           <el-form-item label="工单状态:">
-            <el-select v-model="listQuery.status" class="input-width" placeholder="全部" clearable>
+            <el-select v-model="listQuery.process" class="input-width" placeholder="全部" clearable>
               <el-option v-for="item in ticketProgress"
                          :key="item.value"
                          :label="item.label"
@@ -45,7 +45,7 @@
             </el-select>
           </el-form-item>
           <el-form-item label="工单类型:">
-            <el-select v-model="listQuery.orderType" class="input-width" placeholder="全部" clearable>
+            <el-select v-model="listQuery.ticketType" class="input-width" placeholder="全部" clearable>
               <el-option v-for="item in ticketTypes"
                          :key="item.value"
                          :label="item.label"
@@ -202,11 +202,10 @@
   const defaultListQuery = {
     current: 1,
     size: 10,
-    orderSn: null,
-    receiverKeyword: null,
-    status: null,
-    orderType: null,
-    sourceType: null,
+    num: null,
+    contactPerson: null,
+    process: null,
+    ticketType: null,
     createTime: null,
   };
   export default {
@@ -261,7 +260,7 @@
         //工单类型
         ticketTypes:[
           {
-            label:'我要查风险',
+            label:'专利解读',
             value:'1'
           },
           {

+ 15 - 12
src/views/oms/order/orderDetail.vue

@@ -68,9 +68,9 @@
             <div class="content_item">
               是否海外申请:{{order[ticketTypeFiled[order.ticketType]].appAbroad?'是':'否'}}
             </div>
-            <div class="content_item">
+            <!-- <div class="content_item">
               一同申请海牙认证:{{order[ticketTypeFiled[order.ticketType]].appApostille?'是':'否'}}
-            </div>
+            </div> -->
             <div class="content_item">
               <!-- 附图:{{item[ticketTypeFiled[item.ticketType]].appType}} -->
             </div>
@@ -115,10 +115,16 @@
               侵权分类:{{order[ticketTypeFiled[order.ticketType]].tortClassify}}
             </div>
             <div class="content_item">
-              是否拥有专利号:{{order[ticketTypeFiled[order.ticketType]].ifHavePatent?'是':'否'}}
+              是否拥有权利:{{order[ticketTypeFiled[order.ticketType]].ifHaveRightProof?'是':'否'}}
             </div>
             <div class="content_item" v-if="order[ticketTypeFiled[order.ticketType]].patentNo">
-              专利号:{{order[ticketTypeFiled[order.ticketType]].patentNo}}
+              权利证明(号码):{{order[ticketTypeFiled[order.ticketType]].patentNo}}
+            </div>
+            <div class="content_item" v-if="order[ticketTypeFiled[order.ticketType]].proofGuids && order[ticketTypeFiled[order.ticketType]].proofGuids.length>0">
+              权利证明(图):
+              <div>
+                <el-image v-for="img in order[ticketTypeFiled[order.ticketType]].proofGuids" :key="img" class="img_item" :src="$commonJS.getFile(img)"  :preview-src-list="order[ticketTypeFiled[order.ticketType]].proofGuids.map(item=>$commonJS.getFile(item))"></el-image>
+              </div>
             </div>
             <div class="content_item">
               描述:{{order[ticketTypeFiled[order.ticketType]].problemDescription}}
@@ -148,13 +154,6 @@
             创建时间:{{order.createTime}}
           </div> -->
           <div v-if="order.systemFiles && order.systemFiles.length>0" class="file content_item">
-            <!-- <el-form v-if="order.systemFiles" label-width="100px">
-              <el-form-item v-if="order.systemFiles && order.systemFiles.length>0" label="附件:">
-                <div v-for="item in order.systemFiles" :key="item.guid">
-                  <div>{{item.originalName}}</div>
-                </div>
-              </el-form-item>
-            </el-form> -->
             <div>附件:</div>
             <div>
               <div v-for="item in order.systemFiles" :key="item.guid">
@@ -349,7 +348,7 @@
         //工单类型
         ticketTypes:[
           {
-            label:'我要查风险',
+            label:'专利解读',
             value:'1'
           },
           {
@@ -611,6 +610,10 @@
   margin: 5px 0;
   width: 100%;
 }
+.img_item{
+  width: 100px;
+  height: 100px;
+}
 .file{
   width: 100%;
   display: flex;

+ 182 - 4
src/views/pms/product/components/ProductDetail.vue

@@ -1,14 +1,72 @@
 <template>
   <el-card class="form-container" shadow="never">
 
-    <product-info-detail
+    <!-- <product-info-detail
       v-model="productParam"
       :is-edit="isEdit"
       @finishCommit="finishCommit"
       @resetForm="resetForm"
       :btnLoading="btnLoading"
     >
-    </product-info-detail>
+    </product-info-detail> -->
+    <div style="" >
+      <el-form :model="productParam" :rules="rules" ref="productInfoForm" label-width="120px" class="form-inner-container" size="small">
+        <el-form-item label="产品分类:" prop="productCategoryId">
+          <el-cascader
+            v-if="show"
+            style="width:100%"
+            :props="categoryProp()"
+            v-model="selectProductCateValue"
+            :options="productCateOptions">
+          </el-cascader>
+        </el-form-item>
+        <el-form-item label="产品名称:" prop="name">
+          <el-input v-model="productParam.name" placeholder="请输入产品名称"></el-input>
+        </el-form-item>
+        <el-form-item label="是否上架:">
+          <el-switch
+            :active-value="true"
+            :inactive-value="false"
+            v-model="productParam.ifShow">
+          </el-switch>
+        </el-form-item>
+        <el-form-item label="产品图:" >
+          <myUpload :file-list="files" @on-change="onChange" @on-remove="onRemove" :autoUpload="true"></myUpload>
+        </el-form-item>
+        <el-form-item label="检索条件:">
+          <el-input type="textarea" v-model="productParam.searchCondition" placeholder="请输入检索条件"></el-input>
+        </el-form-item>
+        <el-form-item label="来源:">
+          <el-input v-model="productParam.sourceFrom" placeholder="请输入来源"></el-input>
+        </el-form-item>
+        <el-form-item label="售卖平台:">
+          <el-input v-model="productParam.sellPlatform" placeholder="请输入售卖平台"></el-input>
+        </el-form-item>
+        <el-form-item label="售卖平台链接:">
+          <el-input v-model="productParam.platformLink" placeholder="请输入售卖平台链接"></el-input>
+        </el-form-item>
+        <el-form-item label="销冠品牌:">
+          <el-input v-model="productParam.bestSellingBrand" placeholder="请输入销冠品牌"></el-input>
+        </el-form-item>
+        <el-form-item label="产品介绍:">
+          <el-input
+            :autoSize="true"
+            v-model="productParam.description"
+            type="textarea"
+            placeholder="请输入内容"></el-input>
+        </el-form-item>
+        <el-form-item label="产品价格:">
+          <el-input v-model="productParam.price" placeholder="请输入产品价格"></el-input>
+        </el-form-item>
+        <!-- <el-form-item label="排序">
+          <el-input v-model="productParam.sort" placeholder="请输入排序"></el-input>
+        </el-form-item> -->
+        <el-form-item style="text-align: center">
+          <el-button type="primary" size="medium" @click="submit('productInfoForm')" :loading="btnLoading">确认</el-button>
+          <el-button v-if="!isEdit" @click="resetForm('productCateFrom')">重置</el-button>
+        </el-form-item>
+      </el-form>
+    </div>
 
   </el-card>
 </template>
@@ -21,6 +79,7 @@
     description:'',//描述
     searchCondition:'',//检索条件
     sourceFrom:'',//来源
+    sellPlatform:'',//售卖平台
     platformLink:'',//平台链接
     price:'',//价格
     bestSellingBrand:'',//品牌
@@ -41,6 +100,17 @@
       return {
         btnLoading:false,
         productParam: Object.assign({}, defaultProductParam),
+        files:[],
+        selectProductCateValue: null,
+        productCateOptions: [],
+        rules: {
+          name: [
+            {required: true, message: '请输入产品名称', trigger: 'blur'},
+            {min: 2, max: 140, message: '长度在 2 到 140 个字符', trigger: 'blur'}
+          ],
+          productCategoryId: [{required: true, message: '请选择产品分类', trigger: 'blur'}],
+        },
+        show:true
       }
     },
     computed:{
@@ -56,20 +126,128 @@
       }
     },
     methods: {
+      //产品类别下拉框
+      categoryProp(){
+        var that = this
+        return {
+          checkStrictly: true,
+          label:'name',
+          value:'id',
+          lazy: true,
+          lazyLoad(node,resolve){
+            if(node.level == 0){
+              that.getProductCateList(0,resolve)
+            }else{
+              that.getProductCateList(node.data.id,resolve)
+            }
+          }
+        }
+
+      },
+        //查询产品类别
+      getProductCateList(parentId,fn) {
+        var params = {
+          parentId:parentId
+        }
+        this.$api.queryCategory(params).then(response => {
+          let list = response.data.data;
+          // this.productCateOptions = list
+          if(list.length>0){
+              fn(list)
+            }else{
+              fn(null)
+            }
+        });
+      },
       //获取产品信息
       getProductDetails(){
         var params = {
           id:this.productId
         }
         this.$api.queryHotProductDetail(params).then(response=>{
-          this.productParam=response.data.data;
+          var productParam=response.data.data;
+          this.files = response.data.data.systemFileList||[]
+          if(productParam.productCategoryId){
+            var data = []
+            if(productParam.path){
+              var arr = productParam.path.split('/')
+              if(arr[arr.length-1] == ''){
+                arr.pop()
+              }
+              // var arr = arr.map(item=>parseInt(item))
+              arr.forEach(item => {
+                data.push(parseInt(item));
+              });
 
+            }
+            data.push(productParam.productCategoryId);
+            this.$set(this,'selectProductCateValue',data)
+            this.show = false
+            this.$nextTick(()=>{
+              this.show = true
+            })
+          }
+          this.productParam = productParam
         });
       },
       //重置表单
-      resetForm(){
+      resetForm(formName) {
+        this.$refs[formName].resetFields();
+        this.selectProductCateValue=[],
+        this.files=[]
         this.productParam = Object.assign({}, defaultProductParam);
       },
+       //获取文件
+       onChange(file, fileList){
+        if(!this.files){
+          this.$set(this,'files',[])
+        }
+        if (file.guid) {
+          let index = this.files.findIndex(item => {
+            return item.uid == file.uid
+          })
+          if (index != -1) {
+            this.files.splice(index, 1, file)
+          }
+        } else {
+          this.files.push(file.raw)
+        }
+      },
+      // 删除上传的文件
+      onRemove(file, fileList) {
+        let index = this.files.findIndex(item => {
+          return item.uid == file.uid
+        })
+        if (index != -1) {
+          this.files.splice(index, 1)
+        }
+      },
+      submit(formName){
+        var guids = this.$commonJS.checkUploadFile(this.files)
+        if(!guids){
+          return false
+        }
+        this.productParam.fileGuids = guids
+        if(this.selectProductCateValue && this.selectProductCateValue.length>0){
+          this.productParam.productCategoryId = this.selectProductCateValue[this.selectProductCateValue.length-1]
+        }else{
+          this.productParam.productCategoryId = null
+        }
+        console.log(this.selectProductCateValue)
+        this.$refs[formName].validate((valid) => {
+          if (valid) {
+            // this.$emit('finishCommit');
+            this.finishCommit(this.isEdit)
+          } else {
+            this.$message({
+              message: '验证失败',
+              type: 'error',
+              duration:1000
+            });
+            return false;
+          }
+        });
+      },
       //提交信息
       finishCommit(isEdit) {
         this.$confirm('是否要提交该产品', '提示', {

+ 12 - 11
src/views/pms/product/components/ProductInfoDetail.vue

@@ -5,7 +5,7 @@
         <el-cascader
           style="width:100%"
           :props="categoryProp()"
-          v-model="selectProductCateValue "
+          v-model="selectProductCateValue"
           :options="productCateOptions">
         </el-cascader>
       </el-form-item>
@@ -56,7 +56,6 @@
 </template>
 
 <script>
-
   export default {
     name: "ProductInfoDetail",
     props: {
@@ -83,19 +82,13 @@
             {min: 2, max: 140, message: '长度在 2 到 140 个字符', trigger: 'blur'}
           ],
           productCategoryId: [{required: true, message: '请选择产品分类', trigger: 'blur'}],
-        }
+        },
       };
     },
     created() {
     },
     computed:{
-      //重置表单
-      resetForm(formName) {
-        this.$refs[formName].resetFields();
-        this.selectProductCateValue=null,
-        this.files=[]
-        this.$emit('resetForm')
-      },
+
       //产品的编号
       productId(){
         return this.value.id;
@@ -106,7 +99,7 @@
         if(!this.isEdit)return;
         if(this.hasEditCreated)return;
         if(newValue===undefined||newValue==null||newValue===0)return;
-        this.handleEditCreated();
+        // this.handleEditCreated();
       },
       // selectProductCateValue: function (newValue) {
       //   if (newValue != null && newValue.length === 2) {
@@ -119,12 +112,20 @@
       // },
       value(){
         this.files = this.value.systemFileList || []
+        this.handleEditCreated();
       }
     },
     mounted(){
       this.files = this.value.systemFileList
     },
     methods: {
+       //重置表单
+       resetForm(formName) {
+        this.$refs[formName].resetFields();
+        this.selectProductCateValue=null,
+        this.files=[]
+        this.$emit('resetForm')
+      },
       //获取文件
       onChange(file, fileList){
         if(!this.files){

+ 50 - 7
src/views/pms/product/index.vue

@@ -62,6 +62,9 @@
         添加
       </el-button>
     </el-card>
+    <div v-if="showProgress">
+        <el-progress :percentage="percentage"></el-progress>
+    </div>
     <div class="table-container">
       <el-table ref="productTable"
                 :data="list"
@@ -177,6 +180,7 @@
 </template>
 <script>
   import importDialog from '../components/importDialog.vue';
+  import { mapGetters } from 'vuex'
   const defaultListQuery = {
     name: null,
     current: 1,
@@ -225,9 +229,13 @@
           value: false,
           label: '下架'
         }],
-
+        showProgress:false,
+        percentage:0,
       }
     },
+    computed:{
+      ...mapGetters(['webSocket']),
+    },
     created() {
       this.getList();
       // this.getProductCateList();
@@ -245,7 +253,28 @@
     filters: {
 
     },
+    mounted(){
+      this.initTask()
+    },
     methods: {
+      initTask() {
+        this.webSocket.onmessage = (e) => {
+          if(e.data.indexOf('{') == -1){
+            return false
+          }
+          const { code, data, message } = JSON.parse(e.data)
+          if (code === 111 && data.taskType == 2) {
+            if (data.complete) {
+              this.showProgress=false
+              this.percentage=0
+              this.getList()
+            }else{
+              this.showProgress = true
+              this.percentage = data.percentage
+            }
+          }
+        }
+      },
       //产品类别下拉框
       categoryProp(){
         var that = this
@@ -377,10 +406,10 @@
       handlePublishStatusChange(index, row) {
         let ids = [];
         ids.push(row.id);
-        this.updatePublishStatus(!row.ifShow, ids);
+        this.updatePublishStatus(row.ifShow, ids,index);
       },
       //修改产品状态
-      updatePublishStatus(publishStatus, ids) {
+      updatePublishStatus(publishStatus, ids,index=null) {
         var params = {
           ids:ids,
           ifShow:publishStatus
@@ -391,8 +420,21 @@
             type: 'success',
             duration: 1000
           });
-          this.getList()
-        });
+          if(index != null){
+            this.list[index].ifShow = publishStatus
+          }else{
+            this.getList()
+          }
+        }).catch(error=>{
+          this.$message({
+            message: '修改失败',
+            type: 'error',
+            duration: 1000
+          });
+          if(index != null){
+            this.list[index].ifShow = !publishStatus
+          }
+        })
       },
 
       //重置查询条件
@@ -413,7 +455,7 @@
         });
       },
       //删除产品
-      updateDeleteStatus( ids) {
+      updateDeleteStatus(ids) {
         var params = {
           ids:ids
         }
@@ -423,8 +465,9 @@
             type: 'success',
             duration: 1000
           });
+          this.getList()
         });
-        this.getList();
+
       },
 
 

+ 2 - 2
src/views/pms/productCate/components/ProductCateDetail.vue

@@ -33,9 +33,9 @@
       </el-form-item>
 
 
-      <el-form-item label="关键词:">
+      <!-- <el-form-item label="关键词:">
         <el-input v-model="productCate.searchCondition" placeholder="请输入关键词"></el-input>
-      </el-form-item>
+      </el-form-item> -->
       <el-form-item label="类别描述:">
         <el-input type="textarea" :autosize="true" v-model="productCate.description" placeholder="请输入类别的描述"></el-input>
       </el-form-item>

+ 29 - 2
src/views/pms/productCate/index.vue

@@ -43,9 +43,9 @@
         <el-table-column label="路径" align="center">
           <template slot-scope="scope">{{scope.row.echoPath}}</template>
         </el-table-column>
-        <el-table-column label="关键词" align="center">
+        <!-- <el-table-column label="检索条件" align="center">
           <template slot-scope="scope">{{scope.row.searchCondition}}</template>
-        </el-table-column>
+        </el-table-column> -->
         <el-table-column label="描述" align="center">
           <template slot-scope="scope">{{scope.row.description}}</template>
         </el-table-column>
@@ -105,6 +105,7 @@
 
 <script>
 import importDialog from '../components/importDialog.vue';
+import { mapGetters } from 'vuex'
   export default {
     components:{
       importDialog
@@ -134,7 +135,33 @@ import importDialog from '../components/importDialog.vue';
         this.getList();
       }
     },
+    computed:{
+      ...mapGetters(['webSocket']),
+    },
+    mounted(){
+      this.initTask()
+    },
     methods: {
+      initTask() {
+        this.webSocket.onmessage = (e) => {
+          if(e.data.indexOf('{') == -1){
+              return false
+          }
+          const { code, data, message } = JSON.parse(e.data)
+          if (code === 111 && data.taskType == 1) {
+            if (data.complete) {
+              this.showProgress=false
+              this.percentage=0
+              this.getList()
+            }else{
+              this.showProgress = true
+              this.percentage = data.percentage
+            }
+          }
+        }
+      },
+
+
       resetParentId(){
         this.listQuery.current = 1;
         if (this.$route.query.parentId != null) {