From f6c05b70e6f74b413d8bce3d63f844c6cdb194f2 Mon Sep 17 00:00:00 2001
From: xiangpei <xiangpei@timesnew.cn>
Date: 星期三, 25 六月 2025 21:20:48 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/dev' into dev

---
 manager/src/api/customer.js                                 |    6 
 manager/src/views/goods/goods-info/goodsApply.vue           |    6 
 manager/src/views/tag/tag/index.vue                         |  403 ++++++++
 seller/src/views/goods/goods-seller/goodsOperationFirst.vue |   48 
 seller/src/views/goods/goods-seller/goods.vue               |    3 
 manager/src/views/customer/index.vue                        |  173 +++
 seller/src/views/goods/goods-seller/goodsOperationSec.vue   |  633 ++++++++++---
 manager/src/views/activity/index.vue                        |  139 +++
 manager/src/api/order.js                                    |    4 
 manager/src/api/tag.js                                      |   47 +
 seller/src/views/goods/goods-seller/goodsOperation.vue      |    6 
 manager/src/views/goods/goods-info/goods.vue                |   18 
 manager/src/views/goods/goods-info/goodsDetail.vue          |   21 
 manager/src/views/kitchen/kitchenVideo.vue                  |    5 
 seller/src/api/file.js                                      |   31 
 seller/src/views/lili-components/editor/index.vue           |    5 
 seller/src/libs/axios.js                                    |    3 
 manager/src/api/tag-type.js                                 |   48 +
 manager/src/views/news/index.vue                            |  543 +++++++++++
 manager/src/api/news.js                                     |   39 
 seller/src/utils/file.js                                    |   40 
 manager/src/views/tag/tag-type/index.vue                    |  311 ++++++
 seller/package.json                                         |    1 
 manager/src/views/health/HealthVideoList.vue                |    5 
 manager/src/views/order/order/orderDetail.vue               |  175 +++
 25 files changed, 2,513 insertions(+), 200 deletions(-)

diff --git a/manager/src/api/customer.js b/manager/src/api/customer.js
index 9128455..9972185 100644
--- a/manager/src/api/customer.js
+++ b/manager/src/api/customer.js
@@ -78,3 +78,9 @@
   })
 }
 
+export const getCustomerInfo= (params) =>{
+  return service({
+    url: '/customerManager/'+ params,
+    method: 'GET'
+  })
+}
diff --git a/manager/src/api/news.js b/manager/src/api/news.js
new file mode 100644
index 0000000..19aca4e
--- /dev/null
+++ b/manager/src/api/news.js
@@ -0,0 +1,39 @@
+import service from "../libs/axios";
+
+export  const getNews = (params) =>{
+  return service({
+    url: "/news/page",
+    method: "GET",
+    params: params
+  })
+}
+
+export  const addNews = (params) =>{
+  return service({
+    url: "/news",
+    method: "POST",
+    data: params
+  })
+}
+
+export  const editNews = (params) =>{
+  return service({
+    url: "/news",
+    method: "PUT",
+    data: params
+  })
+}
+
+export const publish = (param) =>{
+  return service({
+    url: "/news/publish/"+ param,
+    method: "PUT",
+  })
+}
+
+export const delById = (param) =>{
+  return service({
+    url: "/news/"+ param,
+    method: "DELETE",
+  })
+}
diff --git a/manager/src/api/order.js b/manager/src/api/order.js
index 4981a96..b46c866 100644
--- a/manager/src/api/order.js
+++ b/manager/src/api/order.js
@@ -130,6 +130,10 @@
 export const getLogisticsChecked = () => {
   return getRequest(`/other/logistics/getChecked`)
 }
+//鏌ヨ鍖呰9鍒楄〃
+export const getPackage = (orderSn) => {
+  return getRequest(`/order/order/getPackage/${orderSn}`);
+}
 
 //鏌ヨ鐗╂祦
 export const getTraces = (sn, params) => {
diff --git a/manager/src/api/tag-type.js b/manager/src/api/tag-type.js
new file mode 100644
index 0000000..7776630
--- /dev/null
+++ b/manager/src/api/tag-type.js
@@ -0,0 +1,48 @@
+import service from "@/libs/axios";
+
+// 鑾峰彇鏍囩鍒嗙被鍒楄〃
+export const getTagTypeList = (params) => {
+    return service({
+        url: "/lmk/tag-type/list",
+        method: "GET",
+        params: params
+    })
+}
+
+export const getTagKeyTypeList = () => {
+    return service({
+        url: "/lmk/tag-type/key/list",
+        method: "GET"
+    })
+}
+
+
+
+// 閫氳繃id鍒犻櫎鏍囩鍒嗙被
+export const deleteTagTypeById = (params) => {
+    return service({
+        url: "/lmk/tag-type/" + params,
+        method: "DELETE"
+    })
+}
+
+
+// 淇敼鏍囩鍒嗙被
+export const updateTagType = (params) => {
+    return service({
+        url: "/lmk/tag-type/",
+        method: "PUT",
+        data: params
+    })
+}
+
+// 娣诲姞鏍囩鍒嗙被
+export const saveTagType = (params) => {
+    return service({
+        url: "/lmk/tag-type/",
+        method: "POST",
+        data: params
+    })
+}
+
+
diff --git a/manager/src/api/tag.js b/manager/src/api/tag.js
new file mode 100644
index 0000000..a97d17a
--- /dev/null
+++ b/manager/src/api/tag.js
@@ -0,0 +1,47 @@
+import service from "@/libs/axios";
+
+// 鑾峰彇鏍囩鍒嗛〉
+export const getTags = (data) => {
+    return service({
+        url: "/lmk/tag/page",
+        method: "GET",
+        params: data
+    })
+}
+
+// 鑾峰彇鏍囩鍒楄〃
+export const getTagList = () => {
+    return service({
+        url: "/lmk/tag/list",
+        method: "GET"
+    })
+}
+
+
+// 閫氳繃id鍒犻櫎鏍囩
+export const deleteTagById = (params) => {
+    return service({
+        url: "/lmk/tag/" + params,
+        method: "DELETE"
+    })
+}
+
+
+// 淇敼鏍囩
+export const editTag = (params) => {
+    return service({
+        url: "/lmk/tag/",
+        method: "PUT",
+        data: params
+    })
+}
+
+// 娣诲姞鏍囩
+export const addTag = (params) => {
+    return service({
+        url: "/lmk/tag/",
+        method: "POST",
+        data: params
+    })
+}
+
diff --git a/manager/src/views/activity/index.vue b/manager/src/views/activity/index.vue
index b1f49f2..26a2c42 100644
--- a/manager/src/views/activity/index.vue
+++ b/manager/src/views/activity/index.vue
@@ -136,6 +136,11 @@
             <Button
               type="info"
               size="small"
+              @click="detail(row)"
+            >璇︽儏</Button>
+            <Button
+              type="info"
+              size="small"
               @click="openEdit(row)"
             >缂栬緫</Button>
             <Button
@@ -336,6 +341,82 @@
         </Row>
       </Modal>
 
+      <Modal
+        v-model="infoModelShow"
+        :title="modelTitle"
+        @on-cancel="infoModelClose"
+        width="800"
+        :mask-closable="false"
+      >
+        <div class="detail-container">
+          <Row :gutter="16">
+            <Col span="12">
+              <div class="detail-item">
+                <label>娲诲姩鍚嶇О锛�</label>
+                <span>{{ activityInfo.activityName || '-' }}</span>
+              </div>
+            </Col>
+            <Col span="12">
+              <div class="detail-item">
+                <label>娲诲姩绫诲瀷锛�</label>
+                <span>{{activityInfo.activityType === 'online' ? '绾夸笂':'绾夸笅'}}</span>
+              </div>
+            </Col>
+            <Col span="12">
+              <div class="detail-item">
+                <label>鎶ュ悕鏃堕棿娈碉細</label>
+                <span>{{ activityInfo.reportStartTime }} - {{ activityInfo.reportEndTime }}</span>
+              </div>
+            </Col>
+            <Col span="12">
+              <div class="detail-item">
+                <label>娲诲姩鏃堕棿娈碉細</label>
+                <span>{{ activityInfo.startTime }} - {{ activityInfo.endTime }}</span>
+              </div>
+            </Col>
+
+            <Col span="24" v-if="coverType === '杈撳叆鏂囧瓧灏侀潰'">
+              <div class="detail-item">
+                <label>灏侀潰鏂囧瓧锛�</label>
+                <span>{{ activityInfo.cover || '-' }}</span>
+              </div>
+            </Col>
+            <Col span="24" v-if="coverType === '閫夋嫨鏂囦欢灏侀潰'">
+              <div class="detail-item">
+                <label>涓婁紶灏侀潰锛�</label>
+                <span>{{ activityInfo.cover }}</span>
+              </div>
+            </Col>
+            <Col span="12">
+              <div class="detail-item">
+                <label>浜烘暟闄愬埗锛�</label>
+                <span>{{ activityInfo.limitUserNum || '鏃犻檺鍒�' }}</span>
+              </div>
+            </Col>
+            <Col span="12">
+              <div class="detail-item">
+                <label>娲诲姩鍦扮偣锛�</label>
+                <span>{{ activityInfo.activityLocation || '-' }}</span>
+              </div>
+            </Col>
+            <Col span="24">
+              <div class="detail-item">
+                <label>娲诲姩鍐呭锛�</label>
+                <div
+                  class="activity-content"
+                  v-html="activityInfo.activityContent || '鏃犲唴瀹�'"
+                ></div>
+              </div>
+            </Col>
+          </Row>
+        </div>
+
+        <div slot="footer">
+          <Button @click="infoModelClose">鍏抽棴</Button>
+        </div>
+      </Modal>
+
+
       <!-- 鍥剧墖棰勮妯℃�佹 -->
       <Modal v-model="previewVisible" title="鍥剧墖棰勮" footer-hide>
         <img :src="previewImageUrl" style="width: 100%">
@@ -361,6 +442,8 @@
   components: {Editor},
   data() {
     return {
+      infoModelShow:false,
+
       loading: false,
       membersLoading: false,
       submitLoading: false,
@@ -397,6 +480,24 @@
 
       // 娲诲姩琛ㄥ崟
       activityFrom: {
+        id: '',
+        activityName: '',
+        activityType: '',
+        reportTime: [],
+        time: [],
+        activityContent: '',
+        cover: '',
+        coverType: '',
+        status: '',
+        reportStartTime: '',
+        reportEndTime: '',
+        startTime: '',
+        endTime: '',
+        recommend: false,
+        limitUserNum: 0,
+        activityLocation: '',
+      },
+      activityInfo: {
         id: '',
         activityName: '',
         activityType: '',
@@ -645,6 +746,11 @@
     this.init()
   },
   methods: {
+    detail(row){
+      this.modelTitle = '娲诲姩璇︽儏'
+      this.infoModelShow = true
+      this.activityInfo = row
+    },
     // 鑾峰彇瀵屾枃鏈紪杈戝櫒鐨勫唴瀹�
     getReason(content) {
       this.activityFrom.activityContent = content
@@ -757,7 +863,9 @@
         this.coverType = row.coverType === 'text' ? '杈撳叆鏂囧瓧灏侀潰' : '閫夋嫨鏂囦欢灏侀潰'
       })
     },
-
+    infoModelClose(){
+      this.infoModelShow = false
+    },
     // 鍏抽棴妯℃�佹
     modelClose() {
       this.modelShow = false
@@ -1183,4 +1291,33 @@
     margin-top: 4px;
   }
 }
+.detail-container {
+  padding: 16px;
+}
+
+.detail-item {
+  margin-bottom: 18px;
+  line-height: 1.5;
+
+  label {
+    display: inline-block;
+    width: 100px;
+    color: #666;
+    font-weight: bold;
+    vertical-align: top;
+  }
+
+  span {
+    display: inline-block;
+    width: calc(100% - 110px);
+  }
+}
+
+.activity-content {
+  border: 1px solid #dcdee2;
+  border-radius: 4px;
+  padding: 12px;
+  min-height: 100px;
+  margin-top: 8px;
+}
 </style>
diff --git a/manager/src/views/customer/index.vue b/manager/src/views/customer/index.vue
index 40112e7..6208375 100644
--- a/manager/src/views/customer/index.vue
+++ b/manager/src/views/customer/index.vue
@@ -68,6 +68,7 @@
         @on-selection-change="showSelect"
       >
         <template slot-scope="{ row, index }" slot="action">
+          <Button type="info" size="small" style="margin-right: 5px" @click="openInfo(row)">鏌ョ湅璇︽儏</Button>
           <Button type="info" size="small" style="margin-right: 5px" @click="openEdit(row)">缂栬緫鏍囩</Button>
           <Button type="error" size="small" style="margin-right: 5px" @click="joinBlack(row)">鍔犲叆榛戝悕鍗�</Button>
         </template>
@@ -87,6 +88,82 @@
         ></Page>
       </Row>
 
+      <Modal
+        v-model="showCustomerInfo"
+        :title="modelTitle"
+        width="700"
+        :mask-closable="false"
+      >
+        <div class="customer-detail">
+          <div class="avatar-section">
+            <Avatar :src="customerInfo.face" size="large" />
+            <div class="basic-info">
+              <h3>{{ customerInfo.nickName || '寰俊鐢ㄦ埛' }}</h3>
+              <p>ID: {{ customerInfo.id }}</p>
+              <p>鐢ㄦ埛鍚�: {{ customerInfo.username }}</p>
+            </div>
+          </div>
+
+          <Divider />
+
+          <div class="detail-grid">
+            <div class="detail-row">
+              <span class="detail-label">鎬у埆锛�</span>
+              <span class="detail-value">{{ customerInfo.sex === 0 ? "濂�" : "鐢�"}}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">鍦板尯锛�</span>
+              <span class="detail-value">{{ customerInfo.region || '鏈缃�' }}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">鎵嬫満鍙凤細</span>
+              <span class="detail-value">{{ customerInfo.mobile || '鏈粦瀹�' }}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">褰撳墠绉垎锛�</span>
+              <span class="detail-value">{{ customerInfo.point }}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">鎬荤Н鍒嗭細</span>
+              <span class="detail-value">{{ customerInfo.totalPoint }}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">璐﹀彿鐘舵�侊細</span>
+              <span class="detail-value">
+          <Tag :color="customerInfo.disabled ? 'error' : 'success'">
+            {{ customerInfo.disabled ? '宸茬鐢�' : '姝e父' }}
+          </Tag>
+        </span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">鏄惁鍏宠仈搴楅摵锛�</span>
+              <span class="detail-value">{{ customerInfo.haveStore ? '鏄�' : '鍚�' }}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">娉ㄥ唽鏃堕棿锛�</span>
+              <span class="detail-value">{{ customerInfo.createTime }}</span>
+            </div>
+            <div class="detail-row">
+              <span class="detail-label">鏈�鍚庣櫥褰曟椂闂达細</span>
+              <span class="detail-value">{{ customerInfo.lastLoginDate }}</span>
+            </div>
+          </div>
+
+          <div v-if="customerInfo.customerTagList && customerInfo.customerTagList.length > 0" class="tags-section">
+            <h4>鐢ㄦ埛鏍囩</h4>
+            <div>
+              <Tag v-for="tag in customerInfo.customerTagList" :key="tag" color="default" style="margin-right: 8px;">
+                {{ tag }}
+              </Tag>
+            </div>
+          </div>
+        </div>
+
+        <div slot="footer">
+          <Button type="primary" @click="showCustomerInfo = false">鍏抽棴</Button>
+        </div>
+      </Modal>
+<!--      鏍囩寮圭獥-->
       <Modal
         v-model="showCustomerTag"
         :title="modelTitle"
@@ -125,7 +202,7 @@
 
 <script>
 import JsonExcel from "vue-json-excel";
-import {getCustomerList,addCustomerTag,saveCustomerTagById,getTagList,getStoreSelectOptions} from "@/api/customer";
+import {getCustomerList,addCustomerTag,saveCustomerTagById,getTagList,getStoreSelectOptions,getCustomerInfo} from "@/api/customer";
 import {addCustomerBlackByPC} from "@/api/customer-black.js"
 
 export default {
@@ -135,6 +212,30 @@
   },
   data(){
     return{
+      customerInfo: {
+        birthday: null,
+        blackId: null,
+        clientEnum: null,
+        createTime: "",
+        customerTagList: [],
+        disabled: true,
+        experience: null,
+        face: "",
+        gradeId: null,
+        haveStore: false,
+        id: "",
+        lastLoginDate: "",
+        mobile: null,
+        nickName: "",
+        openId: null,
+        point: 10,
+        region: "",
+        regionId: "",
+        sex: 0,
+        storeId: null,
+        totalPoint: 0,
+        username: ""
+      },
       loading: false, // 琛ㄥ崟鍔犺浇鐘舵��
       //鏌ヨ瀹㈡埛鍒楄〃璇锋眰鍙傛暟
       searchForm:{
@@ -225,8 +326,9 @@
       selectCount: 0, // 宸查�夋暟閲�
       selectList: [], // 宸查�夋暟鎹垪琛�
 
+      //瀹㈡埛璇︽儏瀵硅瘽妗�---
+      showCustomerInfo:false,
       //瀹㈡埛鏍囩瀵硅瘽妗�---
-
       showCustomerTag:false,
       submitLoading:false,
       selectLoading:false,
@@ -301,6 +403,39 @@
       this.selectList = e.map(d => d.id);
       this.selectCount = e.length;
     },
+    //鏌ョ湅璇︽儏
+    openInfo(row){
+      this.showCustomerInfo = true;
+      this.modelTitle = "鐢ㄦ埛璇︽儏"
+      getCustomerInfo(row.id).then(res =>{
+        if(res.code === 200){
+          this.customerInfo = {
+            birthday: res.data.birthday || null,
+            blackId: res.data.blackId || null,
+            clientEnum: res.data.clientEnum || null,
+            createTime: res.data.createTime || '',
+            customerTagList: res.data.customerTagList || [],
+            disabled: res.data.disabled || false,
+            experience: res.data.experience || null,
+            face: res.data.face || '榛樿澶村儚URL',
+            gradeId: res.data.gradeId || null,
+            haveStore: res.data.haveStore || false,
+            id: res.data.id || '',
+            lastLoginDate: res.data.lastLoginDate || '',
+            mobile: res.data.mobile || null,
+            nickName: res.data.nickName || '寰俊鐢ㄦ埛',
+            openId: res.data.openId || null,
+            point: res.data.point || 0,
+            region: res.data.region || '',
+            regionId: res.data.regionId || '',
+            sex: res.data.sex || 0,
+            storeId: res.data.storeId || null,
+            totalPoint: res.data.totalPoint || 0,
+            username: res.data.username || ''
+          };
+        }
+      })
+    },
     // 缂栬緫鏍囩
     openEdit(row){
       this.showCustomerTag = true
@@ -360,6 +495,40 @@
 
 </script>
 <style lang="scss" scoped>
+.customer-detail {
+  padding: 16px;
+}
+
+.avatar-section {
+  display: flex;
+  align-items: center;
+  margin-bottom: 16px;
+}
+
+.basic-info {
+  margin-left: 16px;
+}
+
+.basic-info h3 {
+  margin: 0 0 8px 0;
+  font-size: 18px;
+}
+
+.basic-info p {
+  margin: 6px 0;
+  color: #808695;
+  font-size: 14px;
+}
+
+.tags-section {
+  margin-top: 16px;
+  padding-top: 16px;
+}
+
+.tags-section h4 {
+  margin-bottom: 12px;
+  color: #17233d;
+}
 .export {
   margin: 10px 20px 10px 0;
 }
diff --git a/manager/src/views/goods/goods-info/goods.vue b/manager/src/views/goods/goods-info/goods.vue
index 7a5f7d3..7d1d4e4 100644
--- a/manager/src/views/goods/goods-info/goods.vue
+++ b/manager/src/views/goods/goods-info/goods.vue
@@ -89,9 +89,12 @@
         <template slot="goodsSlot" slot-scope="{ row }">
           <div style="margin: 5px 0px; height: 80px; display: flex">
             <div style="">
-              <img
+              <img v-if="row.original"
                 :src="row.original"
                 style="height: 60px; margin-top: 1px; width: 60px"
+              />
+              <video v-else
+                     :src="row.goodsVideo" style="height: 60px; margin-top: 1px; width: 60px"
               />
             </div>
 
@@ -159,6 +162,7 @@
 
 <script>
 import { getGoodsListData, upGoods, lowGoods } from "@/api/goods";
+import {getSts} from '@/api/file'
 import vueQr from "vue-qr";
 export default {
   components: {
@@ -376,6 +380,18 @@
         this.loading = false;
         if (res.success) {
           this.data = res.result.records;
+          getSts().then(res => {
+         const endpoint = res.data.endpoint
+            this.data.forEach(item => {
+              if (item.goodsVideo != null && item.goodsVideo.indexOf('http')===-1) {
+                item.goodsVideo = endpoint + '/' + item.goodsVideo;
+              }
+              if (item.original !=null && item.original.indexOf('http') ===-1) {
+                item.original = endpoint + '/' + item.original;
+              }
+            })
+          })
+
           this.total = res.result.total;
         }
       });
diff --git a/manager/src/views/goods/goods-info/goodsApply.vue b/manager/src/views/goods/goods-info/goodsApply.vue
index 30deb6a..8b8aa08 100644
--- a/manager/src/views/goods/goods-info/goodsApply.vue
+++ b/manager/src/views/goods/goods-info/goodsApply.vue
@@ -42,11 +42,13 @@
         <!-- 鍟嗗搧鏍忕洰鏍煎紡鍖� -->
         <template slot="goodsSlot" slot-scope="scope">
           <div style="margin-top: 5px; height: 80px; display: flex">
-            <div style="">
-              <img
+            <div style="" >
+              <img v-if="scope.row.original"
                 :src="scope.row.original"
                 style="height: 60px; margin-top: 3px; width: 60px"
               />
+              <video v-else :src="scope.row.goodsVideo"      style="height: 60px; margin-top: 3px; width: 60px"
+              />
             </div>
 
             <div style="margin-left: 13px">
diff --git a/manager/src/views/goods/goods-info/goodsDetail.vue b/manager/src/views/goods/goods-info/goodsDetail.vue
index 60d4c41..af66491 100644
--- a/manager/src/views/goods/goods-info/goodsDetail.vue
+++ b/manager/src/views/goods/goods-info/goodsDetail.vue
@@ -143,6 +143,7 @@
 </template>
 <script>
 import { getGoodsDetail } from "@/api/goods";
+import {getSts} from '@/api/file'
 export default {
   name: "goodsDetail",
   data() {
@@ -193,6 +194,26 @@
     initGoods(id) {
       getGoodsDetail(id).then((res) => {
         this.goods = res.result;
+        if (this.goods.goodsVideo != null && this.goods.goodsVideo !== '') {
+          getSts().then(res => {
+            console.log('--------------->',this.goods.goodsVideo.indexOf('http')!== -1)
+            if (this.goods.goodsVideo !== null && this.goods.goodsVideo.indexOf('http')=== -1) {
+              this.goods.goodsVideo = res.data.endpoint+'/'+this.goods.goodsVideo;
+            }
+          })
+        }
+        if (this.goods.goodsGalleryList != null && this.goods.goodsGalleryList.length > 0) {
+          getSts().then(res => {
+            this.goods.goodsGalleryList =  this.goods.goodsGalleryList.map((item) => {
+              if (item !== null&&item.indexOf('http')===-1) {
+                return  res.data.endpoint+'/'+item;
+              }else {
+                return item;
+              }
+            })
+          })
+        }
+
         let that = this;
         res.result.skuList.forEach(function (sku, index, array) {
           that.skuData.push({
diff --git a/manager/src/views/health/HealthVideoList.vue b/manager/src/views/health/HealthVideoList.vue
index 9c87653..43ef70c 100644
--- a/manager/src/views/health/HealthVideoList.vue
+++ b/manager/src/views/health/HealthVideoList.vue
@@ -112,6 +112,7 @@
               <FormItem label="瑙嗛">
                 <video style="width: 150px;height: 150px"
                        controls
+                       @loadedmetadata="getVideoDuration"
                        :poster="uploadVideoForm.showCoverUrl"
                        :autoplay="false"
                        id="remoteVideo" :src="uploadVideoForm.showVideoUrl"
@@ -671,6 +672,10 @@
         this.auditingLoading = false
       })
     },
+    getVideoDuration(e){
+      const duration = this.$refs.healthVideoInfo.duration;
+      this.uploadVideoForm.videoDuration = Math.floor(duration);
+    },
     // 鎵撳紑缂栬緫寮圭獥
     deleteHealthVideo(row) {
       console.log('鍒犻櫎娴嬭瘯', row)
diff --git a/manager/src/views/kitchen/kitchenVideo.vue b/manager/src/views/kitchen/kitchenVideo.vue
index d3e945a..40e7079 100644
--- a/manager/src/views/kitchen/kitchenVideo.vue
+++ b/manager/src/views/kitchen/kitchenVideo.vue
@@ -112,6 +112,7 @@
               <FormItem label="瑙嗛">
                 <video style="width: 150px;height: 150px"
                        controls
+                       @loadedmetadata="getVideoDuration"
                        :poster="uploadVideoForm.showCoverUrl"
                        :autoplay="false"
                        id="remoteVideo" :src="uploadVideoForm.showVideoUrl"
@@ -588,6 +589,10 @@
       this.$set(this.uploadVideoForm, 'temp', new Date().getTime());
       console.log(this.uploadVideoForm)
     },
+    getVideoDuration(e){
+      const duration = this.$refs.healthVideoInfo.duration;
+      this.uploadVideoForm.videoDuration = Math.floor(duration);
+    },
     // 瑙嗛涓婃灦
     videoUp(row) {
       this.$Modal.confirm({
diff --git a/manager/src/views/news/index.vue b/manager/src/views/news/index.vue
new file mode 100644
index 0000000..e9d2d95
--- /dev/null
+++ b/manager/src/views/news/index.vue
@@ -0,0 +1,543 @@
+<template>
+  <div class="news-management">
+    <Card>
+      <!-- 鎼滅储琛ㄥ崟 -->
+      <Form
+        ref="searchForm"
+        @keydown.enter.native="handleSearch"
+        :model="searchForm"
+        inline
+        :label-width="80"
+        class="search-form"
+      >
+        <FormItem label="鏍囬" prop="title">
+          <Input
+            type="text"
+            v-model="searchForm.title"
+            placeholder="璇疯緭鍏ユ爣棰樺悕绉�"
+            clearable
+            @on-clear="handleSearch"
+            style="width: 180px"
+          />
+        </FormItem>
+        <FormItem label="鏄惁鍙戝竷" prop="publish">
+          <Select
+            v-model="searchForm.publish"
+            placeholder="璇烽�夋嫨"
+            style="width: 180px"
+            clearable
+            @on-clear="handleSearch"
+            @on-change="handleSearch"
+          >
+            <Option
+              v-for="item in typeSelect"
+              :value="item.value"
+              :key="item.id"
+            >
+              {{ item.label }}
+            </Option>
+          </Select>
+        </FormItem>
+        <Button
+          @click="handleSearch"
+          type="primary"
+          icon="ios-search"
+          class="search-btn"
+        >鎼滅储</Button>
+        <Button
+          @click="resetSearch"
+          icon="md-refresh"
+          style="margin-left: 8px"
+        >閲嶇疆</Button>
+      </Form>
+
+      <!-- 鎿嶄綔鎸夐挳 -->
+      <Row class="operation">
+        <Button @click="openAdd" type="primary" icon="md-add">鏂板娲诲姩</Button>
+        <Button @click="delBatch" type="error" icon="md-trash" :disabled="selectCount === 0">鎵归噺鍒犻櫎</Button>
+      </Row>
+
+      <!-- 娲诲姩琛ㄦ牸 -->
+      <Table
+        :loading="loading"
+        border
+        :columns="columns"
+        :data="newsList"
+        ref="table"
+        @on-selection-change="showSelect"
+        class="news-table"
+      >
+        <!-- 灏侀潰灞曠ず鎻掓Ы -->
+        <!-- 鎿嶄綔鎸夐挳鎻掓Ы -->
+        <template slot-scope="{ row }" slot="action">
+          <div class="action-btns">
+            <Button
+              type="primary"
+              size="small"
+              @click="changeStatus(row, row.publish ? '涓嬫灦' : '鍙戝竷')"
+              :loading="row.statusLoading"
+            >
+              {{ row.publish  ? '涓嬫灦' : '鍙戝竷' }}
+            </Button>
+            <Button
+              type="info"
+              size="small"
+              @click="detail(row)"
+            >璇︽儏</Button>
+            <Button
+              type="info"
+              size="small"
+              @click="openEdit(row)"
+            >缂栬緫</Button>
+            <Button
+              type="error"
+              size="small"
+              @click="delById(row)"
+            >鍒犻櫎</Button>
+          </div>
+        </template>
+      </Table>
+
+      <!-- 鍒嗛〉 -->
+      <Row type="flex" justify="end" class="page-footer">
+        <Page
+          :current="searchForm.pageNumber"
+          :total="total"
+          :page-size="searchForm.pageSize"
+          @on-change="changePage"
+          @on-page-size-change="changePageSize"
+          :page-size-opts="[10, 20, 50]"
+          size="small"
+          show-total
+          show-elevator
+          show-sizer
+        ></Page>
+      </Row>
+
+      <!-- 鏂伴椈缂栬緫/鏂板妯℃�佹 -->
+      <Modal
+        v-model="modelShow"
+        :title="modelTitle"
+        @on-cancel="modelClose"
+        width="800"
+        :mask-closable="false"
+      >
+        <Form ref="form" :model="newsForm" :label-width="100" :rules="rules">
+          <Row :gutter="16">
+            <Col span="12">
+              <FormItem label="鏍囬" prop="title">
+                <Input
+                  v-model="newsForm.title"
+                  placeholder="璇疯緭鍏ユ爣棰樺悕绉�"
+                  clearable
+                />
+              </FormItem>
+            </Col>
+            <Col span="24">
+              <FormItem label="鏂伴椈鍐呭锛�" prop="content">
+                <editor ref="editor" @input="getReason" />
+              </FormItem>
+            </Col>
+          </Row>
+        </Form>
+
+        <div slot="footer">
+          <Button @click="modelClose">鍙栨秷</Button>
+          <Button type="primary" :loading="submitLoading" @click="saveOrUpdate">鎻愪氦</Button>
+        </div>
+      </Modal>
+
+
+      <Modal
+        v-model="infoModelShow"
+        :title="modelTitle"
+        @on-cancel="infoModelClose"
+        width="800"
+        :mask-closable="false"
+      >
+        <div class="detail-container">
+          <Row :gutter="16">
+            <Col span="12">
+              <div class="detail-item">
+                <label>鏍囬锛�</label>
+                <span>{{ newsInfo.title || '-' }}</span>
+              </div>
+            </Col>
+            <Col span="12">
+              <div class="detail-item">
+                <label>鏄惁鍙戝竷锛�</label>
+                <span>{{newsInfo.publish  ? '宸插彂甯�':'鏈彂甯�'}}</span>
+              </div>
+            </Col>
+
+            <Col span="12">
+              <div class="detail-item" v-if="newsInfo.publish">
+                <label>鍙戝竷鏃堕棿锛�</label>
+                <span>{{ newsInfo.publishDate}}</span>
+              </div>
+            </Col>
+            <Col span="24">
+              <div class="detail-item">
+                <label>鏂伴椈鍐呭锛�</label>
+                <div
+                  class="news-content"
+                  v-html="newsInfo.content || '鏃犲唴瀹�'"
+                ></div>
+              </div>
+            </Col>
+          </Row>
+        </div>
+
+        <div slot="footer">
+          <Button @click="infoModelClose">鍏抽棴</Button>
+        </div>
+      </Modal>
+
+
+      <!-- 鍥剧墖棰勮妯℃�佹 -->
+      <Modal v-model="previewVisible" title="鍥剧墖棰勮" footer-hide>
+        <img :src="previewImageUrl" style="width: 100%">
+      </Modal>
+    </Card>
+  </div>
+</template>
+<script>
+import Editor from '@/components/editor/index.vue'
+import { getNews,editNews,addNews,publish,delById } from '@/api/news.js'
+export default {
+  name: "newsManagement",
+  components: {Editor},
+  data(){
+    return{
+      // 鍥剧墖棰勮
+      previewVisible: false,
+      previewImageUrl: '',
+
+      modelShow:false,
+      modelTitle:'',
+      submitLoading:false,
+      infoModelShow:false,
+      //琛ㄥご
+      columns: [
+        {
+          type: 'selection',
+          width: 60,
+          align: 'center'
+        },
+        {
+          title: '鏍囬',
+          key: 'title',
+          minWidth: 120,
+          tooltip: true
+        },
+        {
+          title: '鍙戝竷',
+          key: 'publish',
+          width: 100,
+          align: 'center',
+          render: (h, params) => {
+            return h('Tag', {
+              props: {
+                color: params.row.publish ? 'green' : 'default'
+              }
+            }, params.row.publish ? '宸插彂甯�' : '鏈彂甯�')
+          }
+        },
+        {
+          title: '鍙戝竷鏃堕棿',
+          key: 'publishDate',
+          width: 300,
+          align: 'center',
+          render: (h, { row }) => {
+            // 濡傛灉 publishDate 涓� null 鎴� undefined锛屾樉绀� "鏈彂甯�"
+            if (row.publishDate == null) {
+              return h('span', { style: { color: '#999' } }, '鏆傛棤');
+            }
+            // 鍚﹀垯姝e父鏄剧ず鏃ユ湡
+            return h('span', row.publishDate);
+          },
+        },
+        {
+          title: '鎿嶄綔',
+          slot: 'action',
+          width: 280,
+          align: 'center',
+          fixed: 'right'
+        }
+      ],
+
+      newsList:[],
+      total:0,
+      newsForm:{
+        id:'',
+        title:'',
+        content:'',
+        publish:0,
+      },
+      newsInfo:{
+        title:'',
+        publish:false,
+        publishDate:'',
+        content:''
+      },
+      rules: {
+        title: [
+          { required: true, message: '璇疯緭鍏ユ爣棰�', trigger: 'blur' },
+          { max: 50, message: '闀垮害涓嶈兘瓒呰繃50涓瓧绗�', trigger: 'blur' }
+        ],
+        publish: [
+          { required: true, message: '璇烽�夋嫨鏄惁鍙戝竷', trigger: 'blur' },
+        ],
+        content: [
+          { required: true, message: '璇疯緭鍏ユ柊闂诲唴瀹�', trigger: 'blur' }
+        ]
+      },
+
+      selectList:[],
+      selectCount:0,
+
+      loading:false,
+
+      searchForm: {
+        title: '',
+        publish: 0,
+        pageNumber: 1,
+        pageSize: 10
+      },
+      typeSelect:[
+        {
+          id:1,
+          label:'鏈彂甯�',
+          value:0
+        },
+        {
+          id:2,
+          label:'宸插彂甯�',
+          value:1
+        }
+
+      ]
+    }
+  },
+  mounted() {
+    this.getNewsList();
+  },
+  methods:{
+    getNewsList(){
+      this.loading = true
+      getNews(this.searchForm).then(res =>{
+        this.loading = false
+        if (res.code === 200) {
+          // 涓烘瘡涓�琛屾坊鍔爈oading鐘舵��
+          this.newsList = res.data.map(item => ({
+            ...item,
+          }))
+          this.total = res.total
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    getReason(content) {
+      this.newsForm.content = content
+    },
+    saveOrUpdate(){
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          this.submitLoading = true
+          const submitData = {
+            ...this.newsForm,
+            publish: this.newsForm.publish !== 0,  // true 鈫� 1, false 鈫� 0
+          };
+          if (this.newsForm.id){
+            editNews(submitData).then(res => {
+              this.submitLoading = false
+              if (res.code === 200) {
+                this.$Message.success(res.msg)
+                this.modelClose()
+                this.getNewsList()
+              }
+            }).catch(() => {
+              this.submitLoading = false
+            })
+          }else {
+            addNews(submitData).then(res => {
+              this.submitLoading = false
+              if (res.code === 200) {
+                this.$Message.success(res.msg)
+                this.modelClose()
+                this.getNewsList()
+              }
+            }).catch(() => {
+              this.submitLoading = false
+            })
+          }
+
+        }
+      })
+    },
+    infoModelClose(){
+      this.infoModelShow = false;
+    },
+    modelClose(){
+      this.modelShow = false;
+    },
+    changePage(page) {
+      this.searchForm.pageNumber = page
+      this.getNewsList()
+    },
+    // 鏀瑰彉姣忛〉鏉℃暟
+    changePageSize(pageSize) {
+      this.searchForm.pageNumber = 1
+      this.searchForm.pageSize = pageSize
+      this.getNewsList()
+    },
+
+    delById(row){
+      delById(row.id).then(res =>{
+        if (res.code === 200){
+          this.$Message.success(res.msg);
+          this.getNewsList();
+        }
+
+      })
+    },
+    openEdit(row){
+      this.modelTitle = '淇敼鏂伴椈';
+      this.modelShow = true;
+      this.$refs.form.resetFields();
+      this.newsForm.title = row.title;
+      this.newsForm.content = row.content;
+      this.newsForm.id = row.id;
+      this.$refs.editor.setContent(this.newsForm.content)
+    },
+    openAdd(){
+      this.modelTitle = '鏂板鏂伴椈';
+      this.modelShow = true;
+      this.$refs.form.resetFields()
+      this.newsForm.id = '';
+
+    },
+    detail(row){
+      this.modelTitle = '娲诲姩璇︽儏'
+      this.infoModelShow = true
+      this.newsInfo = row
+    },
+    changeStatus(row,action){
+      row.statusLoading = true;
+
+      publish(row.id).then(res =>{
+        row.statusLoading = false
+        if (res.code === 200){
+          this.$Message.success(res.msg);
+          this.getNewsList();
+        }
+      }).catch(() => {
+        row.statusLoading = false
+      })
+    },
+    // 琛ㄦ牸閫夋嫨鍙樺寲
+    showSelect(selection) {
+      this.selectList = selection.map(item => item.id)
+      this.selectCount = selection.length
+    },
+
+    delBatch(){
+
+    },
+    handleSearch(type, value){
+      this.searchForm.pageNumber = 1
+      this.getNewsList()
+    },
+    resetSearch(){
+      this.$refs.searchForm.resetFields()
+      this.searchForm.pageNumber = 1
+      this.getNewsList()
+    },
+
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.activity-management {
+  .search-form {
+    padding: 16px;
+    background: #f8f8f9;
+    border-radius: 4px;
+    margin-bottom: 16px;
+
+    .ivu-form-item {
+      margin-bottom: 16px;
+      margin-right: 16px;
+    }
+
+    .search-btn {
+      margin-left: 8px;
+    }
+  }
+}
+.detail-container {
+  padding: 16px;
+}
+
+.detail-item {
+  margin-bottom: 18px;
+  line-height: 1.5;
+
+  label {
+    display: inline-block;
+    width: 100px;
+    color: #666;
+    font-weight: bold;
+    vertical-align: top;
+  }
+
+  span {
+    display: inline-block;
+    width: calc(100% - 110px);
+  }
+}
+
+.news-content {
+  border: 1px solid #dcdee2;
+  border-radius: 4px;
+  padding: 12px;
+  min-height: 100px;
+  margin-top: 8px;
+}
+.news-table {
+  .media-container {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+    height: 100px;
+
+    .thumbnail {
+      max-width: 100%;
+      max-height: 100%;
+      object-fit: contain;
+      cursor: pointer;
+      transition: all 0.3s;
+
+      &:hover {
+        transform: scale(1.05);
+        box-shadow: 0 0 8px rgba(0, 0, 0, 0.2);
+      }
+    }
+  }
+
+  .action-btns {
+    display: flex;
+    flex-wrap: wrap;
+    justify-content: center;
+
+    .ivu-btn {
+      margin: 4px;
+      font-size: 12px;
+      padding: 2px 6px;
+      min-width: 60px;
+    }
+  }
+}
+</style>
diff --git a/manager/src/views/order/order/orderDetail.vue b/manager/src/views/order/order/orderDetail.vue
index dbf46b1..0007005 100644
--- a/manager/src/views/order/order/orderDetail.vue
+++ b/manager/src/views/order/order/orderDetail.vue
@@ -7,6 +7,7 @@
           <Button v-if="allowOperation.editConsignee" @click="editAddress" type="primary" ghost>淇敼鏀惰揣鍦板潃</Button>
           <Button v-if="allowOperation.cancel" @click="orderCancel" type="warning" ghost>璁㈠崟鍙栨秷</Button>
           <Button v-if="orderInfo.order.orderStatus === 'UNPAID'" @click="confirmPrice" type="primary">鏀舵</Button>
+          <Button v-if="allowOperation.showLogistics || orderPackage.length > 0" @click="checkLogistics" type="primary">鏌ョ湅鐗╂祦</Button>
           <Button @click="orderLog" type="info" ghost>璁㈠崟鏃ュ織</Button>
           <Button @click="printOrder" type="primary" ghost style="float:right;"
             v-if="$route.query.orderType != 'VIRTUAL'">鎵撳嵃鍙戣揣鍗�</Button>
@@ -310,6 +311,74 @@
         <Button type="primary" @click="modifyPriceSubmit">璋冩暣</Button>
       </div>
     </Modal>
+    <!-- 鏌ヨ鐗╂祦 -->
+    <Modal v-model="logisticsModal" width="40">
+      <p slot="header">
+        <span>鏌ヨ鐗╂祦</span>
+      </p>
+      <div class="layui-layer-wrap">
+        <dl>
+          <dt>璁㈠崟鍙凤細</dt>
+          <dd>
+            <div class="text-box">{{ sn }}</div>
+          </dd>
+        </dl>
+      </div>
+      <div v-if="packageTraceList.length > 0" v-for="(packageItem, packageIndex) in packageTraceList" :key="packageIndex">
+        <div class="layui-layer-wrap">
+          <dl>
+            <dt>鐗╂祦鍏徃锛�</dt>
+            <dd><div class="text-box">{{ packageItem.logisticsName }}</div></dd>
+          </dl>
+          <dl>
+            <dt>蹇�掑崟鍙凤細</dt>
+            <dd><div nctype="ordersSn" class="text-box">{{ packageItem.logisticsNo }}</div></dd>
+          </dl>
+          <div class="div-express-log">
+            <ul class="express-log express-log-name">
+              <li v-for="(item, index) in packageItem.orderPackageItemList" :key="index">
+                <span class="time" style="width: 50%;"><span>鍟嗗搧鍚嶇О锛�</span><span>{{ item.goodsName }}</span></span>
+                <span class="time" style="width: 30%;"><span>鍙戣揣鏃堕棿锛�</span><span>{{ item.logisticsTime }}</span></span>
+                <span class="time" style="width: 20%;"><span>鍙戣揣鏁伴噺锛�</span><span>{{ item.deliverNumber }}</span></span>
+              </li>
+            </ul>
+          </div>
+          <div class="div-express-log">
+            <ul class="express-log" v-if="packageItem.traces && packageItem.traces.traces">
+              <li v-for="(item, index) in packageItem.traces.traces" :key="index">
+                <span class="time">{{ item.AcceptTime || item.acceptTime }}</span>
+                <span class="detail">{{ item.AcceptStation || item.remark }}</span>
+              </li>
+            </ul>
+            <ul class="express-log" v-else><li>鏆傛棤鐗╂祦淇℃伅</li></ul>
+          </div>
+        </div>
+      </div>
+      <div v-if = "packageTraceList.length == 0 && logisticsInfo">
+        <div class="layui-layer-wrap">
+          <dl>
+            <dt>鐗╂祦鍏徃锛�</dt>
+            <dd><div class="text-box">{{ logisticsInfo.shipper }}</div></dd>
+          </dl>
+          <dl>
+            <dt>蹇�掑崟鍙凤細</dt>
+            <dd><div nctype="ordersSn" class="text-box">{{ logisticsInfo.logisticCode }}</div></dd>
+          </dl>
+          <div class="div-express-log">
+            <ul class="express-log" v-if="logisticsInfo && logisticsInfo.traces">
+              <li v-for="(item, index) in logisticsInfo.traces" :key="index">
+                <span class="time">{{ item.AcceptTime }}</span>
+                <span class="detail">{{ item.AcceptStation }}</span>
+              </li>
+            </ul>
+            <ul class="express-log" v-else><li>鏆傛棤鐗╂祦淇℃伅</li></ul>
+          </div>
+        </div>
+      </div>
+      <div slot="footer" style="text-align: right">
+        <Button @click="logisticsModal = false">鍙栨秷</Button>
+      </div>
+    </Modal>
     <!-- 璁㈠崟鍙栨秷妯℃�佹 -->
     <Modal v-model="orderCancelModal" width="530">
       <p slot="header">
@@ -468,6 +537,12 @@
       orderLogModal: false, //寮瑰嚭璋冩暣浠锋牸妗�
       checkedLogistics: [], //閫変腑鐨勭墿娴佸叕鍙搁泦鍚�
       allowOperation: {}, //璁㈠崟鍙墠鍋氶�夐」
+      logisticsModal: false, //寮瑰嚭鏌ヨ鐗╂祦妗�
+      packageTraceList: [],
+      orderPackage: [],
+      logisticsInfo: {
+        shipper: "",
+      }, //鐗╂祦淇℃伅
       sn: "", //璁㈠崟缂栧彿
       orderInfo: {
         order: {
@@ -645,7 +720,39 @@
     gotoHomes () {
       return false
     },
-
+    getOrderPackage() {
+      API_Order.getPackage(this.sn).then(res => {
+        if (res.success) {
+          this.orderPackage = res.result;
+          console.log('this.orderPackage',this.orderPackage);
+        }
+      })
+    },
+    //鏌ヨ鐗╂祦
+    checkLogistics () {
+      this.logisticsModal = true;
+      if (this.orderPackage.length > 0) {
+        this.logisticsList();
+      } else {
+        this.logistics();
+      }
+    },
+    logisticsList () {
+      this.logisticsModal = true;
+      API_Order.getPackage(this.sn).then((res) => {
+        if (res.success && res.result != null) {
+          this.packageTraceList = res.result;
+        }
+      });
+    },
+    logistics () {
+      this.logisticsModal = true;
+      API_Order.getTraces(this.sn).then((res) => {
+        if (res.success && res.result != null) {
+          this.logisticsInfo = res.result;
+        }
+      });
+    },
     //纭鏀舵
     confirmPrice () {
       this.$Modal.confirm({
@@ -805,6 +912,7 @@
   mounted () {
     this.sn = this.$route.query.sn;
     this.getDataList();
+    this.getOrderPackage();
   },
 };
 </script>
@@ -910,7 +1018,72 @@
     }
   }
 }
+.div-express-log {
+  max-height: 300px;
+  border: solid 1px #e7e7e7;
+  background: #fafafa;
+  overflow-y: auto;
+  overflow-x: auto;
+}
+.layui-layer-wrap {
+  dl {
+    border-top: solid 1px #f5f5f5;
+    margin-top: -1px;
+    overflow: hidden;
 
+    dt {
+      font-size: 14px;
+      line-height: 28px;
+      display: inline-block;
+      padding: 8px 1% 8px 0;
+      color: #999;
+    }
+
+    dd {
+      font-size: 14px;
+      line-height: 28px;
+      display: inline-block;
+      padding: 8px 0 8px 8px;
+      border-left: solid 1px #f5f5f5;
+
+      .text-box {
+        line-height: 40px;
+        color: #333;
+        word-break: break-all;
+      }
+    }
+  }
+}
+.express-log {
+  /*margin: 5px -10px 5px 5px;*/
+  padding: 10px;
+  list-style-type: none;
+
+  .time {
+    width: 30%;
+    display: inline-block;
+    float: left;
+  }
+
+  .detail {
+    width: 60%;
+    margin-left: 30px;
+    display: inline-block;
+  }
+
+  li {
+    line-height: 30px;
+  }
+}
+
+.express-log-name {
+  li {
+    display: flex;
+    span  {
+      display: flex;
+    }
+  }
+}
 .f14 {
   font-size: 14px;
   color: #333;
diff --git a/manager/src/views/tag/tag-type/index.vue b/manager/src/views/tag/tag-type/index.vue
new file mode 100644
index 0000000..a97eba3
--- /dev/null
+++ b/manager/src/views/tag/tag-type/index.vue
@@ -0,0 +1,311 @@
+<template>
+    <div>
+        <Card>
+            <div class="operation mb_10">
+                <Button @click="addParent" type="primary" icon="md-add">娣诲姞涓�绾у垎绫�</Button>
+            </div>
+            <tree-table ref="treeTable" size="default" :loading="loading" :data="tableData" :columns="columns"
+                :border="true" :show-index="false" :is-fold="true" :expand-type="false" primary-key="id">
+                <template slot="action" slot-scope="scope">
+                    <Button type="info" @click="edit(scope.row)" size="small" style="margin-right: 5px">缂栬緫
+                    </Button>
+
+                    <Button type="error" @click="remove(scope.row)" size="small" style="margin-right: 5px">鍒犻櫎
+                    </Button>
+                    <Button v-show="scope.row.level != 1" type="success" @click="addChildren(scope.row)" size="small"
+                        style="margin-right: 5px">娣诲姞瀛愬垎绫�
+                    </Button>
+                </template>
+            </tree-table>
+        </Card>
+        <Modal :title="modalTitle" v-model="modalVisible" :mask-closable="false" :width="500">
+            <Form ref="formAdd" :model="formAdd" :label-width="100" :rules="formValidate">
+                <div v-if="showParent">
+                    <FormItem label="涓婄骇鍒嗙被" prop="parentId">
+                        {{ parentTitle }}
+                        <Input v-model="formAdd.parentId" clearable style="width: 100%; display: none" />
+                    </FormItem>
+                </div>
+                <FormItem label="鍒嗙被鍚嶇О" prop="tagTypeName">
+                    <Input v-model="formAdd.tagTypeName" clearable style="width: 100%" />
+                </FormItem>
+                <FormItem label="鍒嗙被鏍囪瘑" prop="typeKey">
+
+                    <Select v-model="formAdd.typeKey" :disabled="formAdd.parentId!==0" placeholder="璇烽�夋嫨鍒嗙被鏍囪瘑" filterable :popper-append-to-body="false"
+                        popper-class="spec-values-popper" style="width: 100%; text-align: left; margin-right: 10px">
+                        <Option v-for="item in typeKeyList" :value="item.value" :label="item.value" :key="item.value">
+                        </Option>
+                    </Select>
+                </FormItem>
+                <FormItem label="鎺掑簭鍊�" prop="sortNum">
+                    <InputNumber v-model="formAdd.sortNum"></InputNumber>
+                </FormItem>
+            </Form>
+            <div slot="footer">
+                <Button type="text" @click="modalVisible = false">鍙栨秷</Button>
+                <Button type="primary" :loading="submitLoading" @click="Submit">鎻愪氦</Button>
+            </div>
+        </Modal>
+    </div>
+</template>
+<script>
+import {
+    saveTagType,
+    getTagTypeList ,
+    deleteTagTypeById,
+    updateTagType,getTagKeyTypeList
+} from "@/api/tag-type";
+import TreeTable from "@/components/tree-table/Table/Table";
+import uploadPicInput from "@/components/lili/upload-pic-input";
+import { regular } from "@/utils";
+export default {
+    name: "lili-components",
+    components: {
+        TreeTable,
+        uploadPicInput,
+    },
+    data() {
+        return {
+            submitLoading: false,
+            loading: false, // 鍔犺浇鐘舵��
+            expandLevel: 1, // 灞曞紑鐨勫眰绾�
+            modalType: 0, // 娣诲姞鎴栫紪杈戞爣璇�
+            modalVisible: false, // 娣诲姞鎴栫紪杈戞樉绀�
+            modalTitle: "", // 娣诲姞鎴栫紪杈戞爣棰�
+            showParent: false, // 鏄惁灞曠ず涓婄骇鑿滃崟
+            parentTitle: "", // 鐖剁骇鑿滃崟鍚嶇О
+            formAdd: {
+                // 娣诲姞鎴栫紪杈戣〃鍗曞璞″垵濮嬪寲鏁版嵁
+                parentId: "",
+                sortNum: 1,
+                level: 0,
+                tagTypeName: "",
+                typeKey:''
+            },
+            // 琛ㄥ崟楠岃瘉瑙勫垯
+            formValidate: {
+                tagTypeName: [regular.REQUIRED],
+                typeKey: [regular.REQUIRED],
+                sortNum: [regular.REQUIRED, regular.INTEGER],
+            },
+            columns: [
+                {
+                    title: "鍒嗙被鍚嶇О",
+                    key: "tagTypeName",
+                    witt: "100px",
+                },
+                {
+                    title: "鍒嗙被鏍囪瘑",
+                    key: "typeKey",
+                    witt: "100px",
+                },
+                {
+                    title: "鎺掑簭",
+                    key: "sortNum",
+                    width: "100px",
+                },
+                {
+                    title: "鎿嶄綔",
+                    key: "action",
+                    align: "center",
+                    headerAlign: "center",
+                    width: "400px",
+                    type: "template",
+                    template: "action",
+                },
+            ],
+            typeKeyList: [],
+            tableData: [], // 琛ㄦ牸鏁版嵁
+        };
+    },
+    methods: {
+        // 鍒濆鍖栨暟鎹�
+        init() {
+            this.getAllList();
+            this.getKeyTypeList();
+        },
+        getKeyTypeList() { 
+            getTagKeyTypeList().then((res) => { 
+                this.typeKeyList = res.data
+            })
+        },
+        // 娣诲姞瀛愬垎绫�
+        addChildren(v) {
+            this.modalType = 0;
+            this.modalTitle = "娣诲姞瀛愬垎绫�";
+            this.formAdd.tagTypeName = "";
+            this.parentTitle = v.tagTypeName;
+            this.formAdd.typeKey = v.typeKey;
+            this.typeKeyEdit = false
+            this.formAdd.level = eval(v.level + "+1");
+            this.showParent = true;
+            delete this.formAdd.id;
+            this.formAdd.parentId = v.id;
+            this.modalVisible = true;
+        },
+        // 缂栬緫鍒嗙被
+        edit(v) {
+            this.modalType = 1;
+            this.modalTitle = "缂栬緫";
+            this.formAdd.id = v.id;
+            this.formAdd.tagTypeName = v.tagTypeName;
+            this.formAdd.level = v.level;
+            this.formAdd.parentId = v.parentId;
+            this.formAdd.sortNum = v.sortNum;
+            this.showParent = false;
+            this.modalVisible = true;
+        },
+        // 娣诲姞涓�绾у垎绫�
+        addParent() {
+            this.modalType = 0;
+            this.modalTitle = "娣诲姞涓�绾у垎绫�";
+            this.parentTitle = "椤剁骇鍒嗙被";
+            this.showParent = true;
+            this.$refs.formAdd.resetFields();
+            delete this.formAdd.id;
+            this.formAdd.parentId = 0;
+            this.modalVisible = true;
+        },
+        // 鎻愪氦
+        Submit() {
+            this.$refs.formAdd.validate((valid) => {
+                if (valid) {
+                    this.submitLoading = true;
+                    if (this.modalType === 0) {
+                        // 娣诲姞 閬垮厤缂栬緫鍚庝紶鍏d绛夋暟鎹� 璁板緱鍒犻櫎
+                        delete this.formAdd.id;
+                        saveTagType(this.formAdd).then((res) => {
+                            this.submitLoading = false;
+                            if (res.success) {
+                                this.$Message.success("娣诲姞鎴愬姛");
+
+                                this.formAdd = {
+                                    // 娣诲姞鎴栫紪杈戣〃鍗曞璞″垵濮嬪寲鏁版嵁
+                                    parentId: "",
+                                    sortNum: 1,
+                                    level: 0,
+                                    tagTypeName: "",
+                                };
+                            } else {
+                                // this.$Message.error(res.message);
+                            }
+                            this.getAllList();
+                            this.modalVisible = false;
+                        });
+                    } else {
+                        // 缂栬緫
+                        updateTagType(this.formAdd, this.formAdd.id).then((res) => {
+                            this.submitLoading = false;
+                            if (res.success) {
+                                this.$Message.success("淇敼鎴愬姛");
+                            } else {
+                                // this.$Message.error(res.message);
+                            }
+                            this.getAllList();
+                            this.modalVisible = false;
+                            this.$refs.formAdd.resetFields();
+                        });
+                    }
+                }
+            });
+        },
+        // 鍒犻櫎鍒嗙被
+        remove(v) {
+            this.$Modal.confirm({
+                title: "纭鍒犻櫎",
+                content: "鎮ㄧ‘璁よ鍒犻櫎 " + v.tagTypeName + " ?",
+                loading: true,
+                onOk: () => {
+                    // 鍒犻櫎
+                    deleteTagTypeById(v.id).then((res) => {
+                        this.$Modal.remove();
+                        if (res.code===200) {
+                            this.$Message.success("鎿嶄綔鎴愬姛");
+                            this.getAllList();
+                        }
+                    });
+                },
+            });
+        },
+        // 鑾峰彇鍒嗙被鏁版嵁
+        getAllList(newval) {
+            this.loading = true;
+            getTagTypeList().then((res) => {
+                this.loading = false;
+                if (res.code===200) {
+                    // 浠呭睍寮�鎸囧畾绾ф暟 榛樿鍚庡彴宸插睍寮�鎵�鏈�
+                    let expandLevel = this.expandLevel;
+                    res.data.forEach(function (e) {
+                        if (expandLevel == 1) {
+                            if (e.level == 0) {
+                                e.expand = false;
+                            }
+                            if (e.children && e.children.length > 0) {
+                                e.children.forEach(function (c) {
+                                    if (c.level == 1) {
+                                        c.expand = false;
+                                    }
+                                    if (c.children && c.children.length > 0) {
+                                        c.children.forEach(function (b) {
+                                            if (b.level == 2) {
+                                                b.expand = false;
+                                            }
+                                        });
+                                    }
+                                });
+                            }
+                        } else if (expandLevel == 2) {
+                            if (e.level == 0) {
+                                e.expand = true;
+                            }
+                            if (e.children && e.children.length > 0) {
+                                e.children.forEach(function (c) {
+                                    if (c.level == 1) {
+                                        c.expand = false;
+                                    }
+                                    if (c.children && c.children.length > 0) {
+                                        c.children.forEach(function (b) {
+                                            if (b.level == 2) {
+                                                b.expand = false;
+                                            }
+                                        });
+                                    }
+                                });
+                            }
+                        } else if (expandLevel == 3) {
+                            if (e.level == 0) {
+                                e.expand = true;
+                            }
+                            if (e.children && e.children.length > 0) {
+                                e.children.forEach(function (c) {
+                                    if (c.level == 1) {
+                                        c.expand = true;
+                                    }
+                                    if (c.children && c.children.length > 0) {
+                                        c.children.forEach(function (b) {
+                                            if (b.level == 2) {
+                                                b.expand = false;
+                                            }
+                                        });
+                                    }
+                                });
+                            }
+                        }
+                    });
+                    this.tableData = res.data;
+                }
+            });
+        },
+    },
+    mounted() {
+        this.init();
+    },
+};
+</script>
+<style lang="scss" scoped>
+.article {
+    font-size: 16px;
+    font-weight: 400;
+    margin: 12px 0;
+}
+</style>
diff --git a/manager/src/views/tag/tag/index.vue b/manager/src/views/tag/tag/index.vue
new file mode 100644
index 0000000..51c9c9d
--- /dev/null
+++ b/manager/src/views/tag/tag/index.vue
@@ -0,0 +1,403 @@
+<template>
+  <div class="wrapper">
+    <Row>
+      <Col span="4">
+      <Card style="height: 100%;" class="article-category mr_10">
+        <Tree :data="treeData" @on-select-change="handleCateChange"></Tree>
+      </Card>
+      </Col>
+      <Col span="20">
+      <Card class="article-detail">
+        <Row @keydown.enter.native="handleSearch">
+          <Form ref="searchForm" :model="searchForm" inline :label-width="70" style="width: 100%" class="search-form">
+            <Form-item label="鏍囩鍚嶇О" prop="tagName">
+              <Input type="text" v-model="searchForm.tagName" placeholder="璇疯緭鍏ユ爣绛惧悕绉�" clearable style="width: 200px" />
+            </Form-item>
+            <Button @click="handleSearch" type="primary" icon="ios-search" class="search-btn">鎼滅储</Button>
+          </Form>
+        </Row>
+        <Row class="operation padding-row">
+          <Button @click="add" v-if="!selected" type="primary">娣诲姞</Button>
+        </Row>
+        <Table :loading="loading" border :columns="columns" :data="data" style="height: calc(100vh - 328px);"
+          ref="table">
+          <!-- 椤甸潰灞曠ず -->
+          <template slot="openStatusSlot" slot-scope="scope">
+            <div></div>
+            <i-switch size="large" v-model="scope.row.openStatus" @on-change="changeSwitch(scope.row)">
+              <span slot="open">灞曠ず</span>
+              <span slot="close">闅愯棌</span>
+            </i-switch>
+          </template>
+        </Table>
+        <Row type="flex" justify="end" class="mt_10">
+          <Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage"
+            @on-page-size-change="changePageSize" :page-size-opts="[10, 20, 50]" size="small" show-total show-elevator>
+          </Page>
+        </Row>
+      </Card>
+      </Col>
+    </Row>
+    <template v-if="!selected">
+      <Modal :tagName="modalTitle" v-model="modalVisible" :mask-closable="false" :width="1100">
+        <Form ref="form" :model="form" :label-width="100">
+          <FormItem label="鏍囩鍚嶇О" prop="tagName">
+            <Input v-model="form.tagName" clearable style="width: 40%" />
+          </FormItem>
+          <FormItem label="鏍囩鍒嗙被" prop="tagTypeId">
+            <Select v-model="treeValue" placeholder="璇烽�夋嫨" clearable style="width: 180px">
+              <Option v-if="treeValue" :value="treeValue" style="display: none">{{ treeValue }}
+              </Option>
+              <Tree :data="treeDataDefault" @on-select-change="handleCheckChange"></Tree>
+            </Select>
+          </FormItem>
+          <FormItem label="鎺掑簭" prop="sortNum">
+            <Input type="number" v-model="form.sortNum" clearable style="width: 10%" />
+          </FormItem>
+        </Form>
+        <div slot="footer">
+          <Button type="text" @click="modalVisible = false">鍙栨秷</Button>
+          <Button type="primary" :loading="submitLoading" @click="handleSubmit">鎻愪氦</Button>
+        </div>
+      </Modal>
+    </template>
+  </div>
+</template>
+
+<script>
+import { getTagTypeList } from "@/api/tag-type";
+import { getTags, deleteTagById, editTag, addTag } from "@/api/tag";
+import tinymec from "@/components/editor/index.vue";
+export default {
+  components: {
+    tinymec: tinymec,
+  },
+  props: {
+    selected: {
+      type: Boolean,
+      default: false,
+    },
+  },
+  data() {
+    return {
+      selectedIndex: 99999, // 宸查�変笅鏍�
+      loading: true, // 琛ㄥ崟鍔犺浇鐘舵��
+      modalType: 0, // 娣诲姞鎴栫紪杈戞爣璇�
+      modalVisible: false, // 娣诲姞鎴栫紪杈戞樉绀�
+      modalTitle: "", // 娣诲姞鎴栫紪杈戞爣棰�
+      treeDataDefault: [],
+      searchForm: {
+        // 鎼滅储妗嗗垵濮嬪寲瀵硅薄
+        pageNumber: 1, // 褰撳墠椤垫暟
+        pageSize: 10, // 椤甸潰澶у皬
+        sortNum: "createTime", // 榛樿鎺掑簭瀛楁
+        order: "desc", // 榛樿鎺掑簭鏂瑰紡
+        tagTypeId: "",
+      },
+      searchTreeValue: "", // 鍒囨崲
+      form: {
+        // 娣诲姞鎴栫紪杈戣〃鍗曞璞″垵濮嬪寲鏁版嵁
+        tagName: "",
+        tagTypeId: "",
+        sortNum: 1,
+        id: "",
+      },
+      list: [], // 鍒楄〃
+      treeValue: "", // 閫夋嫨鐨勫垎绫�
+      //鏍戠粨鏋�
+      treeData: [],
+      submitLoading: false, // 娣诲姞鎴栫紪杈戞彁浜ょ姸鎬�
+      columns: [
+        // 琛ㄥご
+        {
+          title: "鍒嗙被鍚嶇О",
+          key: "tagTypeName",
+          width: 150,
+        },
+        {
+          title: "鏍囩鍚嶇О",
+          key: "tagName",
+          minWidth: 200,
+          tooltip: true,
+        },
+        {
+          title: "鎺掑簭",
+          key: "sortNum",
+          width: 100,
+        },
+        {
+          title: "鎿嶄綔",
+          key: "action",
+          align: "center",
+
+          width: 230,
+          render: (h, params) => {
+            return h("div", [
+              h(
+                "Button",
+                {
+                  props: {
+                    size: "small",
+                    type:
+                      this.selectedIndex == params.index
+                        ? "primary"
+                        : "default",
+                  },
+                  style: {
+                    marginRight: "5px",
+                    display: this.selected ? "" : "none",
+                  },
+                  on: {
+                    click: () => {
+                      this.selectedIndex = params.index;
+                      this.$emit("callbacked", params.row);
+                    },
+                  },
+                },
+                this.selectedIndex == params.index ? "宸查��" : "閫夋嫨"
+              ),
+              h(
+                "Button",
+                {
+                  props: {
+                    size: "small",
+                    type: "info",
+                  },
+                  style: {
+                    marginRight: "5px",
+                  },
+                  on: {
+                    click: () => {
+                      this.edit(params.row);
+                    },
+                  },
+                },
+                "缂栬緫"
+              ),
+              h(
+                "Button",
+                {
+                  props: {
+                    type: "error",
+                    size: "small",
+                  },
+                  on: {
+                    click: () => {
+                      this.remove(params.row);
+                    },
+                  },
+                },
+                "鍒犻櫎"
+              ),
+            ]);
+          },
+        },
+      ],
+      data: [], // 琛ㄥ崟鏁版嵁
+      total: 0, // 琛ㄥ崟鏁版嵁鎬绘暟
+    };
+  },
+  watch: {
+    "searchForm.tagTypeId": {
+      handler() {
+        this.handleSearch();
+      },
+      deep: true,
+    },
+    "searchForm.tagName": {
+      handler() {
+        this.handleSearch();
+      },
+      deep: true,
+    },
+  },
+  methods: {
+    // 鍒濆鍖栨暟鎹�
+    init() {
+      this.getDataList();
+      this.getAllList(0);
+    },
+    // 閫夋嫨鍒嗙被鍥炶皟
+    handleCateChange(data) {
+      let { value, title } = data[0];
+      this.list.push({
+        value,
+        title,
+      });
+      this.searchForm.tagTypeId = value;
+      this.searchTreeValue = title;
+      this.getDataList()
+    },
+    // 鏍囩鍒嗙被鐨勯�夋嫨浜嬩欢
+    handleCheckChange(data) {
+      let value = "";
+      let title = "";
+      this.list = [];
+      data.forEach((item, index) => {
+        value += `${item.value},`;
+        title += `${item.title},`;
+      });
+      value = value.substring(0, value.length - 1);
+      title = title.substring(0, title.length - 1);
+      this.list.push({
+        value,
+        title,
+      });
+      this.form.tagTypeId = value;
+      this.treeValue = title;
+    },
+    // 鏀瑰彉椤垫暟
+    changePage(v) {
+      this.searchForm.pageNumber = v;
+      this.getDataList();
+    },
+    // 鏀瑰彉椤电爜
+    changePageSize(v) {
+      this.selected.pageNumber = 1;
+      this.searchForm.pageSize = v;
+      this.getDataList();
+    },
+    // 鎼滅储鍒楄〃
+    handleSearch() {
+      this.searchForm.pageNumber = 1;
+      this.searchForm.pageSize = 10;
+      this.getDataList();
+    },
+    // 鑾峰彇鍏ㄩ儴鏍囩鍒嗙被
+    getAllList(parent_id) {
+      this.loading = true;
+      getTagTypeList(parent_id).then((res) => {
+        this.loading = false;
+        if (res.code == 200) {
+          this.treeData = this.getTree(res.data);
+          this.treeDataDefault = this.getTree(res.data);
+          this.treeData.unshift({
+            title: "鍏ㄩ儴",
+            level: 0,
+            children: [],
+            id: "0",
+            tagTypeId: 0,
+          });
+        }
+      });
+    },
+    // 鏍囩鍒嗙被鏍煎紡鍖栨柟娉�
+    getTree(tree = []) {
+      let arr = [];
+      if (!!tree && tree.length !== 0) {
+        tree.forEach((item) => {
+          let obj = {};
+          obj.title = item.tagTypeName;
+          obj.value = item.id;
+          obj.attr = item.tagTypeName; // 鍏朵粬浣犳兂瑕佹坊鍔犵殑灞炴��
+          obj.expand = false;
+          obj.selected = false;
+          obj.children = this.getTree(item.children); // 閫掑綊璋冪敤
+          arr.push(obj);
+        });
+      }
+      return arr;
+    },
+    // 鑾峰彇鏍囩鍒楄〃
+    getDataList(val) {
+      if (val) this.form = {};
+      this.loading = true;
+      getTags(this.searchForm).then((res) => {
+        this.loading = false;
+        if (res.code === 200) {
+          this.total = res.total;
+          //涓轰簡鍦ㄦ槸鍚﹀睍绀轰竴鍒楀睍绀哄紑鍏� 闇�瑕佹敼涓�涓嬫暟鎹被鍨嬶紝鏈�缁堟彁浜ゅ啀娆℃洿鏀�
+          this.data = [];
+          if (res.data.length > 0) {
+            this.data = res.data;
+          }
+        }
+      });
+      this.total = this.data?.length;
+      this.loading = false;
+    },
+    // 娣诲姞鏍囩
+    handleSubmit() {
+      this.$refs.form.validate((valid) => {
+        if (valid) {
+          this.submitLoading = true;
+          if (this.modalType === 0) {
+            // 娣诲姞 閬垮厤缂栬緫鍚庝紶鍏d绛夋暟鎹� 璁板緱鍒犻櫎
+            delete this.form.id;
+            addTag(this.form).then((res) => {
+              this.submitLoading = false;
+              if (res.code === 200) {
+                this.$Message.success("鎿嶄綔鎴愬姛");
+                this.getDataList();
+                this.modalVisible = false;
+              }
+            });
+          } else {
+            // 缂栬緫
+            editTag(this.form).then((res) => {
+              this.submitLoading = false;
+              if (res.code === 200) {
+                this.$Message.success("鎿嶄綔鎴愬姛");
+                this.getDataList();
+                this.modalVisible = false;
+              }
+            });
+          }
+        }
+      });
+    },
+    // 娣诲姞鏍囩modal
+    add() {
+      this.modalType = 0;
+      this.modalTitle = "娣诲姞鏍囩";
+      this.treeValue = "";
+
+      this.form = {
+        sortNum: 1,
+        tagName: "",
+      };
+      this.$refs.form.resetFields();
+      delete this.form.id;
+      this.modalVisible = true;
+    },
+    // 缂栬緫鏍囩modal
+    edit(data) {
+      this.modalType = 1;
+      this.modalTitle = "缂栬緫鏍囩";
+      this.treeValue = "";
+      this.form = {
+        tagName: "",
+      };
+      this.$refs.form.resetFields();
+
+      this.modalVisible = true;
+      this.form.tagTypeId = data.tagTypeId;
+      this.treeValue = data.tagTypeName;
+      this.form.id = data.id;
+      this.form.tagName = data.tagName;
+      this.form.sortNum = data.sortNum;
+    },
+    // 鍒犻櫎鏍囩
+    remove(v) {
+      this.$Modal.confirm({
+        tagName: "纭鍒犻櫎",
+        content: "鎮ㄧ‘璁よ鍒犻櫎涔�?",
+        loading: true,
+        onOk: () => {
+          // 鍒犻櫎
+          deleteTagById(v.id).then((res) => {
+            this.$Modal.remove();
+            if (res.code === 200) {
+              this.$Message.success("鎿嶄綔鎴愬姛");
+              this.getDataList();
+            }
+          });
+        },
+      });
+    },
+  },
+  mounted() {
+    this.init();
+  },
+};
+</script>
diff --git a/seller/package.json b/seller/package.json
index 23f4baf..fe2ac56 100644
--- a/seller/package.json
+++ b/seller/package.json
@@ -13,6 +13,7 @@
     "@amap/amap-jsapi-loader": "0.0.7",
     "@antv/g2": "^4.1.14",
     "axios": "^0.21.1",
+    "cos-js-sdk-v5": "^1.10.1",
     "dplayer": "^1.27.1",
     "js-cookie": "^2.2.1",
     "node-sass": "^4.14.1",
diff --git a/seller/src/api/file.js b/seller/src/api/file.js
new file mode 100644
index 0000000..8c1bee0
--- /dev/null
+++ b/seller/src/api/file.js
@@ -0,0 +1,31 @@
+import service, {
+  getRequest,
+  postRequest,
+  putRequest,
+  deleteRequest,
+  importRequest,
+  getRequestWithNoToken,
+  commonUrl,
+  postRequestWithNoForm
+} from "@/libs/axios";
+
+
+// 鑾峰彇鏂囦欢涓存椂璁块棶url
+export const getFilePreview = (fileKey) => {
+    return service({
+        baseURL: commonUrl,
+        url: "/common/lmk/file/preview",
+        method: "POST",
+        data: {"fileKey": fileKey}
+    })
+}
+
+// 鑾峰彇STS璁块棶浠ょ墝
+export const getSts = () => {
+    return service({
+        baseURL: commonUrl,
+        url: "/common/lmk/file/sts",
+        method: "GET"
+    })
+}
+
diff --git a/seller/src/libs/axios.js b/seller/src/libs/axios.js
index a61bcf6..768708e 100644
--- a/seller/src/libs/axios.js
+++ b/seller/src/libs/axios.js
@@ -353,7 +353,8 @@
     }
   });
 };
-
+// 鍘熷鐨刟xios鏆撮湶鍑哄幓鐢ㄥ嵆鍙�
+export default service
 export const uploadFileRequest = (url, params) => {
   let accessToken = getStore("accessToken");
   return service({
diff --git a/seller/src/utils/file.js b/seller/src/utils/file.js
new file mode 100644
index 0000000..74cfa34
--- /dev/null
+++ b/seller/src/utils/file.js
@@ -0,0 +1,40 @@
+
+/**
+ * 鐢熸垚fileKey
+ *
+ * @param fileName 鏂囦欢鍚�
+ * @returns {*}
+ */
+export function getFileKey (fileName) {
+    const extension = fileName.split('.').pop().toLowerCase();
+        
+	const fileTypes = {
+		image: { name: '鍥剧墖', exts: ["jpg", "png", "jpeg", "gif", "bmp", "webp", "tiff", "svg", "ico", "psd", "raw"] },
+		video: { name: '瑙嗛', exts: ["mp4", "avi", "rmvb", "mov", "wmv", "flv", "mkv", "mpeg", "mpg", "m4v", "3gp", "webm", "vob", "swf"] },
+		radio: { name: '闊抽', exts: ["mp3", "wma", "wav", "mpeg-4", "cd", "m4a", "aac", "flac", "ogg", "aiff", "ape", "midi", "amr", "ra"] },
+		text: { name: '鏂囨湰', exts: ["txt", "xls", "xlsx", "doc", "docx", "pdf", "ppt", "pptx", "csv", "rtf", "odt", "ods", "odp", "epub", "mobi", "pages", "numbers", "key"] },
+		zip: { name: '鍘嬬缉鏂囦欢', exts: ["zip", "rar", "7z", "tar", "gz", "bz2", "xz", "iso", "dmg", "pkg", "cab", "z", "lz", "lzma", "lzo"] }
+	};
+  
+	// 鑾峰彇褰撳墠鏃堕棿骞舵牸寮忓寲涓� yyyyMMddHHmmss
+	const now = new Date();
+	const yyyyMMddHHmmss = [
+		now.getFullYear(),
+		String(now.getMonth() + 1).padStart(2, '0'),
+		String(now.getDate()).padStart(2, '0'),
+		String(now.getHours()).padStart(2, '0'),
+		String(now.getMinutes()).padStart(2, '0'),
+		String(now.getSeconds()).padStart(2, '0')
+	].join('');
+	
+	// 鐢熸垚5浣嶉殢鏈烘暟瀛�
+	const random5Digits = Math.floor(10000 + Math.random() * 90000);
+	
+	// 鏌ユ壘鍖归厤鐨勬枃浠剁被鍨�
+	for (const [type, data] of Object.entries(fileTypes)) {
+		if (data.exts.includes(extension)) {
+			return `${type}/${yyyyMMddHHmmss}${random5Digits}` + '.' + extension;
+		}
+	}
+    return '';
+}
diff --git a/seller/src/views/goods/goods-seller/goods.vue b/seller/src/views/goods/goods-seller/goods.vue
index ed68fda..e4efb96 100644
--- a/seller/src/views/goods/goods-seller/goods.vue
+++ b/seller/src/views/goods/goods-seller/goods.vue
@@ -95,10 +95,11 @@
         <template slot="goodsSlot" slot-scope="{ row }">
           <div style="margin-top: 5px; height: 90px; display: flex">
             <div style="">
-              <img
+              <img v-if="row.original"
                 :src="row.original"
                 style="height: 80px; margin-top: 3px; width: 70px"
               />
+              <video :src="row.goodsVideo" v-else style="height: 80px; margin-top: 3px; width: 70px"></video>
             </div>
 
             <div style="margin-left: 13px">
diff --git a/seller/src/views/goods/goods-seller/goodsOperation.vue b/seller/src/views/goods/goods-seller/goodsOperation.vue
index 77c41ec..d689a13 100644
--- a/seller/src/views/goods/goods-seller/goodsOperation.vue
+++ b/seller/src/views/goods/goods-seller/goodsOperation.vue
@@ -13,8 +13,8 @@
     <second-step ref='second' :firstData="firstData" v-if="activestep === 1"></second-step>
     <!-- 绗笁姝� 鍙戝竷瀹屾垚 -->
     <third-step ref='third' v-if="activestep === 2"></third-step>
-    
-    
+
+
   </div>
 </template>
 <script>
@@ -51,7 +51,7 @@
       this.activestep = 0
       this.$refs.first.selectGoodsType = true;
     }
-    
+
   }
 };
 </script>
diff --git a/seller/src/views/goods/goods-seller/goodsOperationFirst.vue b/seller/src/views/goods/goods-seller/goodsOperationFirst.vue
index 47af408..db69887 100644
--- a/seller/src/views/goods/goods-seller/goodsOperationFirst.vue
+++ b/seller/src/views/goods/goods-seller/goodsOperationFirst.vue
@@ -109,19 +109,19 @@
           type: "PHYSICAL_GOODS",
           check: false,
         },
-        {
-          title: "铏氭嫙鍟嗗搧",
-          img: require("@/assets/goodsType2.png"),
-          desc: "铏氭嫙鏍搁獙锛屾棤闇�鐗╂祦",
-          type: "VIRTUAL_GOODS",
-          check: false,
-        },
-        {
-          title: "鍟嗗搧妯℃澘瀵煎叆",
-          img: require("@/assets/goodsTypeTpl.png"),
-          desc: "鍟嗗搧妯℃澘锛屼竴閿鍏�",
-          check: false,
-        },
+        // {
+        //   title: "铏氭嫙鍟嗗搧",
+        //   img: require("@/assets/goodsType2.png"),
+        //   desc: "铏氭嫙鏍搁獙锛屾棤闇�鐗╂祦",
+        //   type: "VIRTUAL_GOODS",
+        //   check: false,
+        // },
+        // {
+        //   title: "鍟嗗搧妯℃澘瀵煎叆",
+        //   img: require("@/assets/goodsTypeTpl.png"),
+        //   desc: "鍟嗗搧妯℃澘锛屼竴閿鍏�",
+        //   check: false,
+        // },
       ],
       // 鍟嗗搧鍒嗙被閫夋嫨鏁扮粍
       category: [
@@ -130,7 +130,8 @@
         { name: "", id: "" },
       ],
       // 鍟嗗搧绫诲瀷
-      goodsType: "",
+      // goodsType: "",
+      goodsType: "PHYSICAL_GOODS",
       /** 1绾у垎绫诲垪琛�*/
       categoryListLevel1: [],
       /** 2绾у垎绫诲垪琛�*/
@@ -230,10 +231,13 @@
       if (!this.category[0].name) {
         this.$Message.error("璇烽�夋嫨鍟嗗搧鍒嗙被");
         return;
-      } else if (!this.category[2].name) {
-        this.$Message.error("蹇呴』閫夋嫨鍒颁笁绾у垎绫�");
-        return;
-      } else if (this.category[2].name) {
+      }
+      //鍏抽棴蹇呴』閫夋嫨3涓祦绋嬬殑閫夐」
+      // else if (!this.category[2].name) {
+      //   this.$Message.error("蹇呴』閫夋嫨鍒颁笁绾у垎绫�");
+      //   return;
+      // }
+      else if (this.category[2].name) {
         let params = {
           category: this.category,
           goodsType: this.goodsType,
@@ -245,6 +249,14 @@
           this.$emit("change", params);
         }
       }
+      //娴佺▼璋冩暣
+      else {
+        let params = {
+          category: this.category,
+          goodsType: this.goodsType,
+        };
+        this.$emit("change", params);
+      }
     },
   },
   mounted() {
diff --git a/seller/src/views/goods/goods-seller/goodsOperationSec.vue b/seller/src/views/goods/goods-seller/goodsOperationSec.vue
index 0965954..dbbdb51 100644
--- a/seller/src/views/goods/goods-seller/goodsOperationSec.vue
+++ b/seller/src/views/goods/goods-seller/goodsOperationSec.vue
@@ -26,13 +26,13 @@
             <FormItem label="鍟嗗搧鍗栫偣" prop="sellingPoint">
               <Input v-model="baseInfoForm.sellingPoint" :rows="4" style="width: 260px" type="textarea"/>
             </FormItem>
-            <FormItem label="鍟嗗搧鍝佺墝" prop="brandId">
-              <Select v-model="baseInfoForm.brandId" filterable style="width: 200px">
-                <Option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"></Option>
-              </Select>
-              <Button class="refresh-icon" icon="md-refresh" shape="circle" type="text"
-                      @click="refresh('brand')"></Button>
-            </FormItem>
+<!--            <FormItem label="鍟嗗搧鍝佺墝" prop="brandId">-->
+<!--              <Select v-model="baseInfoForm.brandId" filterable style="width: 200px">-->
+<!--                <Option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"></Option>-->
+<!--              </Select>-->
+<!--              <Button class="refresh-icon" icon="md-refresh" shape="circle" type="text"-->
+<!--                      @click="refresh('brand')"></Button>-->
+<!--            </FormItem>-->
           </div>
           <h4>鍟嗗搧浜ゆ槗淇℃伅</h4>
           <div class="form-item-view">
@@ -101,10 +101,10 @@
           </div>
           <h4>鍟嗗搧瑙勬牸鍙婂浘鐗�</h4>
           <div class="form-item-view">
-            <FormItem class="form-item-view-el required" label="涓诲浘" prop="goodsGalleryFiles">
+            <FormItem class="form-item-view-el required" label="涓诲浘" prop="goodsGalleryFiles"  >
               <div style="display: flex; flex-wrap: wrap;">
-                <vuedraggable :animation="200" :list="baseInfoForm.goodsGalleryFiles">
-                  <div v-for="(item, __index) in baseInfoForm.goodsGalleryFiles" :key="__index"
+                <vuedraggable :animation="200" :list="showListImages">
+                  <div v-for="(item, __index) in showListImages" :key="__index"
                        class="demo-upload-list">
                     <template>
                       <img :src="item"/>
@@ -118,17 +118,17 @@
                   </div>
                 </vuedraggable>
                 <!--<Upload ref="upload"-->
-                        <!--:action="uploadFileUrl" :before-upload="handleBeforeUploadGoodsPicture"-->
-                        <!--:format="['jpg', 'jpeg', 'png', 'webp']"-->
-                        <!--:headers="{ ...accessToken }"-->
-                        <!--:max-size="2048" :on-error="() => { $Spin.hide(); }" :on-exceeded-size="handleMaxSize"-->
-                        <!--:on-format-error="handleFormatError" :on-progress="() => { $Spin.show(); }"-->
-                        <!--:on-success="handleSuccessGoodsPicture" :show-upload-list="false" multiple-->
-                        <!--style="margin-left: 10px"-->
-                        <!--type="drag">-->
-                  <!--<div style="width: 148px; height: 148px; line-height: 148px">-->
-                    <!--<Icon size="20" type="md-add"></Icon>-->
-                  <!--</div>-->
+                <!--:action="uploadFileUrl" :before-upload="handleBeforeUploadGoodsPicture"-->
+                <!--:format="['jpg', 'jpeg', 'png', 'webp']"-->
+                <!--:headers="{ ...accessToken }"-->
+                <!--:max-size="2048" :on-error="() => { $Spin.hide(); }" :on-exceeded-size="handleMaxSize"-->
+                <!--:on-format-error="handleFormatError" :on-progress="() => { $Spin.show(); }"-->
+                <!--:on-success="handleSuccessGoodsPicture" :show-upload-list="false" multiple-->
+                <!--style="margin-left: 10px"-->
+                <!--type="drag">-->
+                <!--<div style="width: 148px; height: 148px; line-height: 148px">-->
+                <!--<Icon size="20" type="md-add"></Icon>-->
+                <!--</div>-->
                 <!--</Upload>-->
               </div>
               <div style="width: 100%;display: flex;justify-content: start;margin-top: 10px;">
@@ -139,22 +139,33 @@
               </Modal>
             </FormItem>
             <FormItem>
-              <div style="color: grey">涓诲浘浠呮敮鎸乸ng锛宩pg锛宩peg鏍煎紡锛屽楂樿嚦灏�600*600px锛屽ぇ灏�2M鍐咃紝鍙嫋鎷借皟鏁翠富鍥鹃『搴�</div>
+
+<!--              <div class="demo-upload-list" v-for="(item,index) in showListImages">-->
+<!--                <template style="display: flex">-->
+<!--                  <img :src="item">-->
+<!--                  <div class="demo-upload-list-cover">-->
+<!--                    <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>-->
+<!--                    <Icon type="ios-trash-outline" @click.native="handleRemove(index)"></Icon>-->
+<!--                  </div>-->
+<!--                </template>-->
+<!--              </div>-->
+              <div style="color: grey"  v-if="!baseInfoForm.goodsVideo">涓诲浘浠呮敮鎸乸ng锛宩pg锛宩peg鏍煎紡锛屽楂樿嚦灏�600*600px锛屽ぇ灏�2M鍐�</div>
             </FormItem>
-            <FormItem class="form-item-view-el" label="涓诲浘瑙嗛" prop="goodsVideo">
+            <FormItem class="form-item-view-el" label="瑙嗛" prop="goodsVideo" >
               <div class="goods-video">
                 <div v-if="baseInfoForm.goodsVideo">
                   <div>
-                    <video :src="baseInfoForm.goodsVideo" class="video" controls style="max-width: 300px;"/>
+                    <video :src="baseInfoForm.showGoodsVideo" class="video" controls style="max-width: 300px;"/>
                   </div>
                 </div>
-                <Upload ref="upload" :action="uploadFileUrl" :format="['avi', 'wmv', 'mpeg', 'mp4', 'mov']"
+                <Upload ref="upload" action="-" :format="['avi', 'wmv', 'mpeg', 'mp4', 'mov']"
                         :headers="{ ...accessToken }"
                         :max-size="10240" :on-error="() => { loadingVideo = false }"
                         :on-exceeded-size="handleVideoMaxSize"
                         :on-format-error="handleFormatError" :on-progress="() => { loadingVideo = true }"
                         :on-success="handleSuccessGoodsVideo" :show-upload-list="false"
-                        multiple
+                        :before-upload="upLoadVideo"
+                        accept="video/*"
                         style="margin-left: 10px" type="drag">
                   <Button :loading="loadingVideo" icon="ios-cloud-upload-outline" type="text">
                     <span v-if="!loadingVideo">
@@ -165,6 +176,9 @@
                     </span>
                   </Button>
                 </Upload>
+                <Button :loading="loadingVideo" v-if="baseInfoForm.goodsVideo"  icon="delete" @click="removeVideo" type="text">
+                  <span>鍒犻櫎瑙嗛</span>
+                </Button>
               </div>
             </FormItem>
             <div class="layout" style="width: 100%">
@@ -176,7 +190,7 @@
                       <div v-for="(item, $index) in skuInfo" :key="$index" class="sku-item-content">
                         <Card :bordered="true" class="ivu-card-body">
                           <a slot="extra" style="margin-left: 6px">
-                            <Icon size="20" type="md-trash"  @click="handleCloseSkuItem($index, item)"></Icon>
+                            <Icon size="20" type="md-trash" @click="handleCloseSkuItem($index, item)"></Icon>
                           </a>
                           <div>
                             <div style="display: flex;margin-bottom: 10px;font-weight: bold">瑙勬牸椤�</div>
@@ -185,10 +199,13 @@
                               <div>
                                 <AutoComplete v-model="item.name" :filter-method="filterMethod"
                                               :maxlength="30" placeholder="璇疯緭鍏ヨ鏍奸」鍚嶇О" style="width: 150px"
-                                              @on-focus="changeSkuItem(item.name)" @on-change="editSkuItem(item.name, $index, item)">
+                                              @on-focus="changeSkuItem(item.name)"
+                                              @on-change="editSkuItem(item.name, $index, item)">
                                 </AutoComplete>
 
-                                <iSwitch v-if="$index === 0" style="margin-left: 10px" size="small" @on-change="changeSkuOpenImage" v-model="openImage" /><span v-if="$index === 0" style="margin-left: 5px">娣诲姞瑙勬牸鍥剧墖</span>
+<!--                                <iSwitch v-if="$index === 0" style="margin-left: 10px" size="small"-->
+<!--                                         @on-change="changeSkuOpenImage" v-model="openImage"/>-->
+<!--                                <span v-if="$index === 0" style="margin-left: 5px">娣诲姞瑙勬牸鍥剧墖</span>-->
                               </div>
                             </FormItem>
 
@@ -210,7 +227,8 @@
                                                 @on-change="skuValueChange(val, index, item)">
                                   </AutoComplete>
                                   <a style="margin-left: 6px" v-if="val.value && val.value !== ''">
-                                    <Icon size="15" type="md-trash" @click="handleCloseSkuValue(val, index, item)"></Icon>
+                                    <Icon size="15" type="md-trash"
+                                          @click="handleCloseSkuValue(val, index, item)"></Icon>
                                   </a>
                                 </div>
                                 <div v-if="$index === 0 && openImage" style="margin-top: 10px">
@@ -225,19 +243,20 @@
                                           style="width: 180px;height: 140px"
                                         />
                                         <div class="sku-upload-list-cover">
-                                          <div style="margin-top: 50px" >
+                                          <div style="margin-top: 50px">
                                             <Icon size="25" type="md-search" @click="handleView(img)"></Icon>
-                                            <Icon size="25" type="md-trash" @click="handleRemove(val.images, __index)"></Icon>
+                                            <Icon size="25" type="md-trash"
+                                                  @click="handleRemove(val.images, __index)"></Icon>
                                           </div>
                                         </div>
                                       </template>
                                     </div>
                                   </vuedraggable>
-                                  <Upload ref="uploadSku" :action="uploadFileUrl"
+<!--                                  todo 3-->
+                                  <Upload ref="uploadSku" action="-"
                                           v-if="val.images < 1"
                                           :before-upload="handleBeforeUpload"
                                           :format="['jpg', 'jpeg', 'png', 'webp']"
-                                          :headers="{ ...accessToken }"
                                           :max-size="2048"
                                           :on-error="() => { $Spin.hide(); }"
                                           :on-exceeded-size="handleMaxSize"
@@ -255,7 +274,9 @@
                                 </div>
                               </FormItem>
 
-                              <FormItem v-if="item.spec_values.length < 10 && item.spec_values.length >= 1 && item.spec_values[0].value !== ''" class="sku-item-content-val flex" label="" style="line-height: 32px;">
+                              <FormItem
+                                v-if="item.spec_values.length < 10 && item.spec_values.length >= 1 && item.spec_values[0].value !== ''"
+                                class="sku-item-content-val flex" label="" style="line-height: 32px;">
                                 <AutoComplete ref="input" v-model="newSkuValues[$index]"
                                               :filter-method="filterMethod"
                                               :maxlength="30" placeholder="鑷畾涔夎鏍煎��" style="width: 180px"
@@ -362,6 +383,7 @@
             </div>
             <FormItem class="form-item-view-el" label="PC鍟嗗搧鎻忚堪" prop="intro" style="width: 100%">
               <editor
+                :show-upload="false"
                 ref="editor"
                 v-model="baseInfoForm.intro"
                 height="800px"
@@ -375,6 +397,7 @@
 
             <FormItem class="form-item-view-el" label="绉诲姩绔弿杩�" prop="skuList" style="width: 100%">
               <editor
+                :show-upload="false"
                 ref="introEditor"
                 v-model="baseInfoForm.mobileIntro"
                 height="800px"
@@ -473,8 +496,32 @@
     <!--<Modal width="1200px" v-model="picModelFlag">-->
     <!--<ossManage @callback="callbackSelected" ref="ossManage" />-->
     <!--</Modal>-->
-    <Modal v-model="picModelFlag" width="1200px" @on-ok="confirmUrls">
-      <ossManage ref="ossManage" :isComponent="true" :initialize="picModelFlag" @callback="callbackSelected" @selected="(list)=>{ selectedImage = list}"/>
+    <!--    todo web-->
+    <Modal v-model="picModelFlag" width="1200px">
+      <!--      <ossManage ref="ossManRage" :isComponent="true" :initialize="picModelFlag" @callback="callbackSelected" @selected="(list)=>{ selectedImage = list}"/>-->
+      <div class="demo-upload-list" v-for="(item,index) in showListImages">
+        <template>
+          <img :src="item">
+          <div class="demo-upload-list-cover">
+            <Icon type="ios-eye-outline" @click.native="handleView(item)"></Icon>
+            <Icon type="ios-trash-outline" @click.native="handleRemove(null,index)"></Icon>
+          </div>
+        </template>
+      </div>
+      <div class="demo-upload-list">
+        <Upload
+          :before-upload="upLoadImg"
+          accept="image/*"
+          action="-"
+          type="drag"
+          style=" display: inline-block;width: 58px"
+        >
+          <div style="width: 58px;height:58px;line-height: 58px;">
+            <Icon type="ios-camera" size="20"></Icon>
+          </div>
+        </Upload>
+      </div>
+
     </Modal>
 
   </div>
@@ -491,6 +538,9 @@
 import DPlayer from 'dplayer';
 // import ossManage from "@/views/sys/oss-manage/ossManage";
 import ossManage from "@/views/shop/ossManages";
+import COS from 'cos-js-sdk-v5';
+import {getFileKey} from "@/utils/file.js";
+import {getFilePreview, getSts} from "@/api/file";
 
 
 export default {
@@ -523,6 +573,7 @@
       }, 1000);
     };
     return {
+      showListImages: [],
       regular,
       openImage: false,
       needToloadSku: false,
@@ -625,6 +676,7 @@
         /** 鍟嗗搧鍒嗙被涓枃鍚� */
         categoryName: [],
         goodsVideo: "",
+        showGoodsVideo: "",
       },
       /** 琛ㄦ牸澶� */
       skuTableColumn: [],
@@ -698,12 +750,19 @@
       if (val) {
         this.initVideo();
       }
+    },
+    showListImages(newValue){
+      this.baseInfoForm.goodsGalleryFiles = newValue.map(item => {
+        return   item.split('/').slice(-2).join('/')
+      })
     }
   },
   methods: {
     // 閫夋嫨鍥剧墖modal
     handleCLickImg(val, index) {
-      this.$refs.ossManage.selectImage = true;
+      console.log('娴嬭瘯杈撳叆鐨勫��----------------銆�', val)
+      // 搴熷純鍘熸湁鐨勫浘鐗囦笂浼�
+      // this.$refs.ossManage.selectImage = true;
       this.picModelFlag = true;
       this.selectedFormBtnName = val;
       // this.picIndex = index;
@@ -724,10 +783,10 @@
     },
     // ship澶у皬涓嶆纭�
     handleVideoMaxSize(file) {
-      this.$Notice.warning({
-        title: "瓒呰繃鏂囦欢澶у皬闄愬埗",
-        desc: "瑙嗛澶у皬涓嶈兘瓒呰繃10MB",
-      });
+      // this.$Notice.warning({
+      //   title: "瓒呰繃鏂囦欢澶у皬闄愬埗",
+      //   desc: "瑙嗛澶у皬涓嶈兘瓒呰繃10MB",
+      // });
     },
     onAddSku(index) {
       if (!this.newSkuValues[index]) {
@@ -865,7 +924,15 @@
     },
     // 绉婚櫎宸查�夊浘鐗�
     handleRemove(item, index) {
-      item.splice(index, 1)
+      if (!item) {
+        this.listImages.splice(index, 1);
+        this.showListImages.splice(index, 1);
+        this.baseInfoForm.goodsGalleryFiles.splice(index, 1);
+        this.baseInfoForm.goodsGalleryList.splice(index, 1);
+      } else {
+        console.log('绉婚櫎娴嬭瘯',item, index);
+        item.splice(index, 1)
+      }
       this.previewPicture = "";
     },
     // 鏌ョ湅鍟嗗搧澶у浘
@@ -999,14 +1066,57 @@
       }
     },
     // sku鍥剧墖涓婁紶鍓嶉挬瀛�
-    handleBeforeUpload(file) {
+  async handleBeforeUpload(file) {
       const check =
         this.selectedSku.images !== undefined &&
         this.selectedSku.images.length > 5;
       if (check) {
         this.$Notice.warning({title: "鍥剧墖鏁伴噺涓嶈兘澶т簬浜斿紶"});
-        return false;
       }
+      try {
+        // this.upLoadVideoLoading = true;
+        // 鑾峰彇鏂囦欢涓婁紶涓存椂瀵嗛挜
+        const sts = await getSts();
+        const cos = new COS({
+          getAuthorization: async function (options, callback) {
+            callback({
+              TmpSecretId: sts.data.tmpSecretId,
+              TmpSecretKey: sts.data.tmpSecretKey,
+              SecurityToken: sts.data.sessionToken,
+              // 寤鸿杩斿洖鏈嶅姟鍣ㄦ椂闂翠綔涓虹鍚嶇殑寮�濮嬫椂闂达紝閬垮厤瀹㈡埛绔湰鍦版椂闂村亸宸繃澶у鑷寸鍚嶉敊璇�
+              StartTime: sts.data.stsStartTime, // 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+              ExpiredTime: sts.data.stsEndTime,// 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+              ScopeLimit: true, // 缁嗙矑搴︽帶鍒舵潈闄愰渶瑕佽涓� true锛屼細闄愬埗瀵嗛挜鍙湪鐩稿悓璇锋眰鏃堕噸澶嶄娇鐢�
+            });
+          }
+        })
+        const fileKey = getFileKey(file.name)
+        const upData = await cos.uploadFile({
+          Bucket: sts.data.bucket,
+          Region: sts.data.region,
+          Key: fileKey,
+          Body: file, // 瑕佷笂浼犵殑鏂囦欢瀵硅薄銆�
+          SliceSize: 1024 * 1024 * 5,
+          onProgress: function (progressData) {
+            console.log('涓婁紶杩涘害锛�', progressData);
+          },
+        });
+        console.log("涓婁紶鎴愬姛", upData)
+        this.$nextTick(() => {
+          this.listImages.push(fileKey);
+          this.showListImages.push(sts.data.endpoint + "/" + fileKey);
+          this.baseInfoForm.goodsGalleryFiles.push(fileKey);
+        })
+
+      } catch (e) {
+        console.log("涓婁紶澶辫触", upData)
+        return false;
+      } finally {
+        // this.upLoadVideoLoading = false;
+
+      }
+      return false;
+
     },
 
     /** 鏌ヨ鍟嗗搧鍝佺墝鍒楄〃 */
@@ -1086,8 +1196,34 @@
         this.baseInfoForm.goodsGalleryFiles =
           response.result.goodsGalleryList.map((i) => {
             return i;
-          });
+          })
+        try {
+          const stsInfo = await getSts();
+          const endpoint = stsInfo.data.endpoint;
+          this.showListImages = response.result.goodsGalleryList.map((i) => {
+            if (i!=null&&i.indexOf('http')===-1)
+            return endpoint+'/'+i;
+            else return i;
+          })
+          if (response.result.goodsVideo){
+
+          }
+        } catch (e) {
+          console.log('缁勮璺緞鍑洪棶棰�',e);
+        }
+
       }
+     if (response.result.goodsVideo){
+       try {
+         const stsInfo = await getSts();
+         const endpoint = stsInfo.data.endpoint;
+         this.baseInfoForm.goodsVideo = response.result.goodsVideo;
+         this.baseInfoForm.showGoodsVideo = endpoint + '/' + response.result.goodsVideo;
+         console.log('鏄剧ず鍟嗗搧瑙嗛------------------->', this.baseInfoForm.showGoodsVideo);
+       } catch (e) {
+         console.log('缁勮瑙嗛鍦板潃鍑洪敊浜�')
+       }
+     }
 
       if (
         response.result.wholesaleList &&
@@ -1105,7 +1241,8 @@
       this.renderGoodsDetailSku(response.result.skuList);
 
       /** 鏌ヨ鍝佺墝鍒楄〃 */
-      this.getGoodsBrandList();
+      //todo 绉婚櫎鍝佺墝姒傚康
+      // this.getGoodsBrandList();
 
       /** 鏌ヨ搴楅摵鍟嗗搧鍒嗙被 */
       this.GET_ShopGoodsLabel();
@@ -1125,7 +1262,7 @@
       this.firstData.goodsType &&
       (this.baseInfoForm.goodsType = this.firstData.goodsType);
       /** 鏌ヨ鍟嗗搧鍙傛暟 */
-      this.GET_GoodsParams();
+      // this.GET_GoodsParams();
     },
     // 娓叉煋sku鏁版嵁
     renderGoodsDetailSku(skuList) {
@@ -1780,124 +1917,134 @@
     },
     /**  娣诲姞鍟嗗搧 **/
     save() {
-      this.submitLoading = true;
-      this.$refs["baseInfoForm"].validate((valid) => {
-        if (valid) {
-          if (this.baseInfoForm.salesModel === "WHOLESALE") {
-            for (let i = 0; i < this.wholesaleData.length; i++) {
-              this.checkWholesaleNum(i);
-              this.checkWholesalePrice(i);
-              this.wholesaleData[i].goodsId = this.goodsId;
-            }
-            this.baseInfoForm.wholesaleList = this.wholesaleData;
-          }
-          this.baseInfoForm.goodsId = this.goodsId;
-          let submit = JSON.parse(JSON.stringify(this.baseInfoForm));
-          if (
-            submit.goodsGalleryFiles &&
-            submit.goodsGalleryFiles.length <= 0
-          ) {
-            this.submitLoading = false;
-            this.$Message.error("璇蜂笂浼犲晢鍝佸浘鐗�");
-            return;
-          }
-          if (submit.templateId === "") submit.templateId = 0;
-          let flag = false;
-          let paramValue = "";
-
-          if (flag) {
-            this.$Message.error(paramValue + " 鍙傛暟鍊间笉鑳戒负绌�");
-            this.submitLoading = false;
-            return;
-          }
-
-          if (this.goodsUnitList && !this.goodsUnitList.find(i => i === this.baseInfoForm.goodsUnit)) {
-            submit.goodsUnit = ""
-            this.$Message.error("鍟嗗搧鍗曚綅涓嶅瓨鍦�");
-            this.submitLoading = false;
-            return;
-          }
-          let skuInfoNames = this.skuInfo.map((n) => n.name);
-          submit.skuList = [];
-          let containEmptyImage = false;
-          this.skuTableData.map((sku) => {
-            let skuCopy = {
-              cost: 1,
-              price: sku.price,
-              quantity: sku.quantity,
-              // alertQuantity: sku.alertQuantity,
-              sn: sku.sn,
-              images: [],
-            };
-            if (this.openImage) {
-              this.skuInfo[0].spec_values.forEach(item => {
-                if (!item.images || item.images.length === 0) {
-                  containEmptyImage = true;
-                  return;
-                }
-                if (item.value === sku[this.skuInfo[0].name]) {
-                  skuCopy.images = item.images
-                }
-              })
-
-            }
-            if (sku.weight) {
-              skuCopy.weight = sku.weight;
-            }
-            if (this.baseInfoForm.weight) {
-              skuCopy.weight = this.baseInfoForm.weight;
-            }
-            if (sku.id) {
-              skuCopy.id = sku.id;
-            }
-            for (let skuInfoName of skuInfoNames) {
-              skuCopy[skuInfoName] = sku[skuInfoName];
-            }
-            submit.skuList.push(skuCopy);
-          });
-          if (containEmptyImage) {
-            this.$Message.error("寮�鍚鏍煎浘鐗囷紝鎵�鏈夎鏍煎浘鐗囦笉鑳戒负绌猴紒");
-            this.submitLoading = false;
-            return;
-          }
-          if (submit.goodsGalleryFiles.length > 0) {
-            submit.goodsGalleryList = submit.goodsGalleryFiles.map(
-              (i) => i
-            );
-          }
-          /** 鍙傛暟鏍¢獙 **/
-          /* Object.keys(submit.goodsParamsList).forEach((item) => {
-          });*/
-          submit.release ? (submit.release = true) : (submit.release = false);
-          submit.recommend
-            ? (submit.recommend = true)
-            : (submit.recommend = false);
-          if (this.goodsId) {
-            API_GOODS.editGoods(this.goodsId, submit).then((res) => {
-              if (res.success) {
-                this.submitLoading = false;
-                this.$router.go(-1);
-              } else {
-                this.submitLoading = false;
+      try {
+        this.submitLoading = true;
+        this.$refs["baseInfoForm"].validate((valid) => {
+          if (valid) {
+            if (this.baseInfoForm.salesModel === "WHOLESALE") {
+              for (let i = 0; i < this.wholesaleData.length; i++) {
+                this.checkWholesaleNum(i);
+                this.checkWholesalePrice(i);
+                this.wholesaleData[i].goodsId = this.goodsId;
               }
+              this.baseInfoForm.wholesaleList = this.wholesaleData;
+            }
+            this.baseInfoForm.goodsId = this.goodsId;
+            let submit = JSON.parse(JSON.stringify(this.baseInfoForm));
+            console.log('----------------->鎻愪氦',submit);
+            if (
+              submit.goodsGalleryFiles &&
+                submit.goodsGalleryFiles.length <= 0
+            ) {
+              this.submitLoading = false;
+              this.$Message.error("璇蜂笂浼犲晢鍝佸浘鐗�");
+              return;
+            }
+            if (!submit.goodsVideo){
+              this.submitLoading = false;
+              this.$Message.error("璇蜂笂浼犲晢鍝佽棰�");
+              return;
+            }
+            if (submit.templateId === "") submit.templateId = 0;
+            let flag = false;
+            let paramValue = "";
+
+            if (flag) {
+              this.$Message.error(paramValue + " 鍙傛暟鍊间笉鑳戒负绌�");
+              this.submitLoading = false;
+              return;
+            }
+
+            if (this.goodsUnitList && !this.goodsUnitList.find(i => i === this.baseInfoForm.goodsUnit)) {
+              submit.goodsUnit = ""
+              this.$Message.error("鍟嗗搧鍗曚綅涓嶅瓨鍦�");
+              this.submitLoading = false;
+              return;
+            }
+            let skuInfoNames = this.skuInfo.map((n) => n.name);
+            submit.skuList = [];
+            let containEmptyImage = false;
+            this.skuTableData.map((sku) => {
+              let skuCopy = {
+                cost: 1,
+                price: sku.price,
+                quantity: sku.quantity,
+                // alertQuantity: sku.alertQuantity,
+                sn: sku.sn,
+                images: [],
+              };
+              if (this.openImage) {
+                this.skuInfo[0].spec_values.forEach(item => {
+                  if (!item.images || item.images.length === 0) {
+                    containEmptyImage = true;
+                    return;
+                  }
+                  if (item.value === sku[this.skuInfo[0].name]) {
+                    skuCopy.images = item.images
+                  }
+                })
+
+              }
+              if (sku.weight) {
+                skuCopy.weight = sku.weight;
+              }
+              if (this.baseInfoForm.weight) {
+                skuCopy.weight = this.baseInfoForm.weight;
+              }
+              if (sku.id) {
+                skuCopy.id = sku.id;
+              }
+              for (let skuInfoName of skuInfoNames) {
+                skuCopy[skuInfoName] = sku[skuInfoName];
+              }
+              submit.skuList.push(skuCopy);
             });
+            if (containEmptyImage) {
+              this.$Message.error("寮�鍚鏍煎浘鐗囷紝鎵�鏈夎鏍煎浘鐗囦笉鑳戒负绌猴紒");
+              this.submitLoading = false;
+              return;
+            }
+            if (submit.goodsGalleryFiles.length > 0) {
+              submit.goodsGalleryList = submit.goodsGalleryFiles.map(
+                (i) => i
+              );
+            }
+            /** 鍙傛暟鏍¢獙 **/
+            /* Object.keys(submit.goodsParamsList).forEach((item) => {
+            });*/
+            submit.release ? (submit.release = true) : (submit.release = false);
+            submit.recommend
+              ? (submit.recommend = true)
+              : (submit.recommend = false);
+            if (this.goodsId) {
+              API_GOODS.editGoods(this.goodsId, submit).then((res) => {
+                if (res.success) {
+                  this.submitLoading = false;
+                  this.$router.go(-1);
+                } else {
+                  this.submitLoading = false;
+                }
+              });
+            } else {
+              API_GOODS.createGoods(submit).then((res) => {
+                if (res.success) {
+                  this.submitLoading = false;
+                  this.$parent.activestep = 2;
+                  window.scrollTo(0, 0);
+                } else {
+                  this.submitLoading = false;
+                }
+              });
+            }
           } else {
-            API_GOODS.createGoods(submit).then((res) => {
-              if (res.success) {
-                this.submitLoading = false;
-                this.$parent.activestep = 2;
-                window.scrollTo(0, 0);
-              } else {
-                this.submitLoading = false;
-              }
-            });
-          }
-        } else {
-          this.submitLoading = false;
+            this.submitLoading = false;
 
-          this.$Message.error("杩樻湁蹇呭~椤规湭鍋氬鐞嗭紝璇锋鏌ヨ〃鍗�");
-        }
-      });
+            this.$Message.error("杩樻湁蹇呭~椤规湭鍋氬鐞嗭紝璇锋鏌ヨ〃鍗�");
+          }
+        });
+      } finally {
+        this.submitLoading = false;
+      }
     },
     /** 淇濆瓨涓烘ā鏉� */
     saveToDraft() {
@@ -1961,8 +2108,110 @@
         } else if (type === 'localRefresh') {
           this.$Message.error("鍒锋柊澶辫触锛岃閲嶈瘯");
         }
+      }).catch(reason => {
+        console.log("鑾峰彇妯℃澘澶辫触",reason)
       });
-    }
+    },
+    removeVideo(){
+      this.baseInfoForm.showGoodsVideo = null;
+      this.baseInfoForm.goodsVideo = null;
+    },
+    // todo 鏂囦欢涓婁紶
+    async upLoadImg(file) {
+      console.log(file,this.count++);
+      if (this.listImages.length >= 5) {
+        this.$Message.error("鍥剧墖涓婁紶涓嶈兘瓒呰繃5涓�");
+        return;
+      }
+      try {
+        // this.upLoadVideoLoading = true;
+        // 鑾峰彇鏂囦欢涓婁紶涓存椂瀵嗛挜
+        const sts = await getSts();
+        const cos = new COS({
+          getAuthorization: async function (options, callback) {
+            callback({
+              TmpSecretId: sts.data.tmpSecretId,
+              TmpSecretKey: sts.data.tmpSecretKey,
+              SecurityToken: sts.data.sessionToken,
+              // 寤鸿杩斿洖鏈嶅姟鍣ㄦ椂闂翠綔涓虹鍚嶇殑寮�濮嬫椂闂达紝閬垮厤瀹㈡埛绔湰鍦版椂闂村亸宸繃澶у鑷寸鍚嶉敊璇�
+              StartTime: sts.data.stsStartTime, // 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+              ExpiredTime: sts.data.stsEndTime,// 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+              ScopeLimit: true, // 缁嗙矑搴︽帶鍒舵潈闄愰渶瑕佽涓� true锛屼細闄愬埗瀵嗛挜鍙湪鐩稿悓璇锋眰鏃堕噸澶嶄娇鐢�
+            });
+          }
+        })
+        const fileKey = getFileKey(file.name)
+        const upData = await cos.uploadFile({
+          Bucket: sts.data.bucket,
+          Region: sts.data.region,
+          Key: fileKey,
+          Body: file, // 瑕佷笂浼犵殑鏂囦欢瀵硅薄銆�
+          SliceSize: 1024 * 1024 * 5,
+          onProgress: function (progressData) {
+            console.log('涓婁紶杩涘害锛�', progressData);
+          },
+        });
+        console.log("涓婁紶鎴愬姛", upData)
+        this.$nextTick(() => {
+          this.listImages.push(fileKey);
+          this.showListImages.push(sts.data.endpoint + "/" + fileKey);
+          this.baseInfoForm.goodsGalleryFiles.push(fileKey);
+        })
+
+      } catch (e) {
+        console.log("涓婁紶澶辫触", upData)
+        return false;
+      } finally {
+        // this.upLoadVideoLoading = false;
+
+      }
+      return false;
+    },
+    async upLoadVideo(file) {
+      try {
+        // this.upLoadVideoLoading = true;
+        // 鑾峰彇鏂囦欢涓婁紶涓存椂瀵嗛挜
+        const sts = await getSts();
+        const cos = new COS({
+          getAuthorization: async function (options, callback) {
+            callback({
+              TmpSecretId: sts.data.tmpSecretId,
+              TmpSecretKey: sts.data.tmpSecretKey,
+              SecurityToken: sts.data.sessionToken,
+              // 寤鸿杩斿洖鏈嶅姟鍣ㄦ椂闂翠綔涓虹鍚嶇殑寮�濮嬫椂闂达紝閬垮厤瀹㈡埛绔湰鍦版椂闂村亸宸繃澶у鑷寸鍚嶉敊璇�
+              StartTime: sts.data.stsStartTime, // 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+              ExpiredTime: sts.data.stsEndTime,// 鏃堕棿鎴筹紝鍗曚綅绉掞紝濡傦細1580000000
+              ScopeLimit: true, // 缁嗙矑搴︽帶鍒舵潈闄愰渶瑕佽涓� true锛屼細闄愬埗瀵嗛挜鍙湪鐩稿悓璇锋眰鏃堕噸澶嶄娇鐢�
+            });
+          }
+        })
+        const fileKey = getFileKey(file.name)
+        const upData = await cos.uploadFile({
+          Bucket: sts.data.bucket,
+          Region: sts.data.region,
+          Key: fileKey,
+          Body: file, // 瑕佷笂浼犵殑鏂囦欢瀵硅薄銆�
+          SliceSize: 1024 * 1024 * 5,
+          onProgress: function (progressData) {
+            console.log('涓婁紶杩涘害锛�', progressData);
+          },
+        });
+        console.log("涓婁紶鎴愬姛", upData)
+        this.$nextTick(() => {
+          this.baseInfoForm.goodsVideo = fileKey;
+          this.baseInfoForm.showGoodsVideo = sts.data.endpoint + "/" + fileKey;
+          this.baseInfoForm.goodsVideo = fileKey;
+        })
+
+      } catch (e) {
+        console.log("涓婁紶澶辫触", upData)
+        return false;
+      } finally {
+        // this.upLoadVideoLoading = false;
+
+      }
+      return false;
+    },
   },
   mounted() {
     this.accessToken = {
@@ -1988,12 +2237,17 @@
         this.baseInfoForm.goodsType = this.firstData.goodsType;
 
 
-        /** 鑾峰彇璇ュ晢鍩庡垎绫讳笅 鍟嗗搧鍙傛暟淇℃伅 */
-        this.GET_GoodsParams();
-        /** 鏌ヨ鍝佺墝鍒楄〃 */
-        this.getGoodsBrandList();
-        /** 鏌ヨ鍒嗙被缁戝畾鐨勮鏍间俊鎭� */
-        this.Get_SkuInfoByCategory(this.categoryId);
+
+
+        if (this.categoryId!=null && this.categoryId!=='') {
+          /** 鑾峰彇璇ュ晢鍩庡垎绫讳笅 鍟嗗搧鍙傛暟淇℃伅 */
+          this.GET_GoodsParams();
+          console.log('鍒嗙被id------------------>',this.categoryId);
+          /** 鏌ヨ鍒嗙被缁戝畾鐨勮鏍间俊鎭� */
+          this.Get_SkuInfoByCategory(this.categoryId);
+          /** 鏌ヨ鍝佺墝鍒楄〃 */
+          this.getGoodsBrandList();
+        }
         // 鑾峰彇鍟嗗搧鍗曚綅
         this.GET_GoodsUnit();
         // 鑾峰彇褰撳墠搴楅摵鍒嗙被
@@ -2044,4 +2298,45 @@
 .refresh-icon {
   margin-left: 10px;
 }
+
+.demo-upload-list {
+  display: inline-block;
+  width: 60px;
+  height: 60px;
+  text-align: center;
+  line-height: 60px;
+  border: 1px solid transparent;
+  border-radius: 4px;
+  overflow: hidden;
+  background: #fff;
+  position: relative;
+  box-shadow: 0 1px 1px rgba(0, 0, 0, .2);
+  margin-right: 4px;
+}
+
+.demo-upload-list img {
+  width: 100%;
+  height: 100%;
+}
+
+.demo-upload-list-cover {
+  display: none;
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  right: 0;
+  background: rgba(0, 0, 0, .6);
+}
+
+.demo-upload-list:hover .demo-upload-list-cover {
+  display: block;
+}
+
+.demo-upload-list-cover i {
+  color: #fff;
+  font-size: 20px;
+  cursor: pointer;
+  margin: 0 2px;
+}
 </style>
diff --git a/seller/src/views/lili-components/editor/index.vue b/seller/src/views/lili-components/editor/index.vue
index a28d64e..5bd05ee 100644
--- a/seller/src/views/lili-components/editor/index.vue
+++ b/seller/src/views/lili-components/editor/index.vue
@@ -3,7 +3,7 @@
     <!-- 浣跨敤 fullscreen 绫绘潵鎺у埗鏄惁鍏ㄥ睆鏄剧ず -->
     <div :class="{ fullscreen: fullscreen }" class="tinymce-container">
       <!-- 浣跨敤 tinymce-textarea 绫讳綔涓虹紪杈戝櫒鐨勬枃鏈尯鍩� -->
-      <uploadImage @callback="insertImage" />
+      <uploadImage @callback="insertImage"  v-if="showUpload"/>
       <textarea :id="tinymceId" class="tinymce-textarea" />
     </div>
   </div>
@@ -23,6 +23,9 @@
     height:{
       type:String,
       default:'500px'
+    },showUpload:{
+      type:Boolean,
+      default:true
     }
   },
   data() {

--
Gitblit v1.8.0