From e8746fe5bb553c17e0052958d9c39a5e2bc6f6a1 Mon Sep 17 00:00:00 2001
From: zxl <763096477@qq.com>
Date: 星期二, 15 七月 2025 14:58:32 +0800
Subject: [PATCH] 商家端活动申请

---
 manager/src/views/activity/index.vue       |   37 
 manager/src/views/news/index.vue           |  388 ++++++++++-
 seller/src/views/activity/activityList.vue | 1461 ++++++++++++++++++++++++++++++++++++++++++
 seller/src/api/activity.js                 |   31 
 seller/package.json                        |    5 
 seller/src/views/activity/video.js         |   69 ++
 seller/src/libs/axios.js                   |   49 +
 7 files changed, 1,991 insertions(+), 49 deletions(-)

diff --git a/manager/src/views/activity/index.vue b/manager/src/views/activity/index.vue
index 8a74704..9043862 100644
--- a/manager/src/views/activity/index.vue
+++ b/manager/src/views/activity/index.vue
@@ -588,11 +588,9 @@
   activityMembersPage,
   auditActivity
 } from "@/api/activity.js"
-import Editor from '@/components/editor/index.vue'
 import { uploadFileByLmk, delByKey } from "@/api/common.js"
 
 import { quillEditor } from 'vue-quill-editor'
-import Delta from 'quill-delta'
 import 'quill/dist/quill.core.css';
 import 'quill/dist/quill.snow.css';
 import 'quill/dist/quill.bubble.css';
@@ -668,7 +666,7 @@
 
 export default {
   name: "ActivityManagement",
-  components: {Editor, quillEditor},
+  components: { quillEditor},
   data() {
     return {
       auditForm: {
@@ -846,17 +844,39 @@
           }
         },
         {
-          title: '瀹℃牳',
+          title: '瀹℃牳鐘舵��',
           key: 'auditStatus',
           width: 100,
           align: 'center',
           render: (h, params) => {
+            const status = params.row.auditStatus;
+            let tagText, tagColor;
+
+            // 鏍规嵁鐘舵�佽缃枃妗堝拰棰滆壊
+            switch (status) {
+              case 0:
+                tagText = '瀹℃牳涓�';
+                tagColor = 'orange';  // 姗欒壊琛ㄧず杩涜涓�
+                break;
+              case 1:
+                tagText = '宸插鏍�';
+                tagColor = 'green';   // 缁胯壊琛ㄧず閫氳繃
+                break;
+              case 2:
+                tagText = '鏈�氳繃';
+                tagColor = 'red';     // 绾㈣壊琛ㄧず鎷掔粷
+                break;
+              default:
+                tagText = '鏈煡鐘舵��';
+                tagColor = 'default'; // 榛樿鐏拌壊
+            }
+
             return h('Tag', {
               props: {
-                color: params.row.auditStatus === 0 ? 'default' : 'green'
-              }
-            }, params.row.auditStatus === 0 ? '鏈鏍�' : '宸插鏍�')
-          }
+                color: tagColor,
+              },
+            }, tagText);
+          },
         },
         {
           title: '鐘舵��',
@@ -1064,7 +1084,6 @@
 
     // 澶卞幓鐒︾偣
     onEditorBlur(editor) {
-
     },
 
     // 鑾峰緱鐒︾偣
diff --git a/manager/src/views/news/index.vue b/manager/src/views/news/index.vue
index e9d2d95..0b5b888 100644
--- a/manager/src/views/news/index.vue
+++ b/manager/src/views/news/index.vue
@@ -135,7 +135,28 @@
             </Col>
             <Col span="24">
               <FormItem label="鏂伴椈鍐呭锛�" prop="content">
-                <editor ref="editor" @input="getReason" />
+                <Upload
+                  :show-upload-list="false"
+                  ref="upload"
+                  style="display: none"
+                  :before-upload="handleUploadEdit"
+                  :format="['jpg','jpeg','png','gif','mp4','mov']"
+                  :max-size="20480"
+                  action=""
+                  accept="image/*,video/*"
+                >
+                </Upload>
+                <!-- 鍩轰簬elementUi鐨勪笂浼犵粍浠� el-upload end-->
+                <quill-editor
+                  v-model="newsForm.content"
+                  ref="QuillEditor"
+                  class="editor"
+                  :options="editorOption"
+                  @blur="onEditorBlur($event)"
+                  @focus="onEditorFocus($event)"
+                  @ready="onEditorReady($event)"
+                >
+                </quill-editor>
               </FormItem>
             </Col>
           </Row>
@@ -202,11 +223,87 @@
   </div>
 </template>
 <script>
-import Editor from '@/components/editor/index.vue'
 import { getNews,editNews,addNews,publish,delById } from '@/api/news.js'
+import { uploadFileByLmk, delByKey } from "@/api/common.js"
+import { quillEditor } from 'vue-quill-editor'
+
+import 'quill/dist/quill.core.css';
+import 'quill/dist/quill.snow.css';
+import 'quill/dist/quill.bubble.css';
+
+import * as Quill from 'quill' //寮曞叆缂栬緫鍣�
+import VideoBlot from '../activity/video.js';
+
+const toolbarOptions = [
+  ['bold', 'italic', 'underline', 'strike'],        // 鍔犵矖锛屾枩浣擄紝涓嬪垝绾匡紝鍒犻櫎绾�
+  ['blockquote', 'code-block'],                     //寮曠敤锛屼唬鐮佸潡
+  [{ 'header': 1 }, { 'header': 2 }],               // 鍑犵骇鏍囬
+  [{ 'list': 'ordered' }, { 'list': 'bullet' }],    // 鏈夊簭鍒楄〃锛屾棤搴忓垪琛�
+  [{ 'script': 'sub' }, { 'script': 'super' }],     // 涓嬭鏍囷紝涓婅鏍�
+  [{ 'indent': '-1' }, { 'indent': '+1' }],         // 缂╄繘
+  [{ 'direction': 'rtl' }],                         // 鏂囧瓧杈撳叆鏂瑰悜
+  [{ 'size': ['small', false, 'large', 'huge'] }],  // 瀛椾綋澶у皬
+  [{ 'header': [1, 2, 3, 4, 5, 6, false] }],        // 鏍囬
+  [{ 'color': [] }, { 'background': [] }],          // 棰滆壊閫夋嫨
+  // [{ 'font': [] }], // 瀛椾綋
+  [{ 'align': [] }],    // 灞呬腑
+  ['clean'],            // 娓呴櫎鏍峰紡,
+  ['link'],
+  ['myUploadBtn'],
+]
+
+// toolbar鏍囬
+const titleConfig = [
+  { Choice: '.ql-insertMetric', title: '璺宠浆閰嶇疆' },
+  { Choice: '.ql-bold', title: '鍔犵矖' },
+  { Choice: '.ql-italic', title: '鏂滀綋' },
+  { Choice: '.ql-underline', title: '涓嬪垝绾�' },
+  { Choice: '.ql-header', title: '娈佃惤鏍煎紡' },
+  { Choice: '.ql-strike', title: '鍒犻櫎绾�' },
+  { Choice: '.ql-blockquote', title: '鍧楀紩鐢�' },
+  { Choice: '.ql-code', title: '鎻掑叆浠g爜' },
+  { Choice: '.ql-code-block', title: '鎻掑叆浠g爜娈�' },
+  { Choice: '.ql-font', title: '瀛椾綋' },
+  { Choice: '.ql-size', title: '瀛椾綋澶у皬' },
+  { Choice: '.ql-list[value="ordered"]', title: '缂栧彿鍒楄〃' },
+  { Choice: '.ql-list[value="bullet"]', title: '椤圭洰鍒楄〃' },
+  { Choice: '.ql-direction', title: '鏂囨湰鏂瑰悜' },
+  { Choice: '.ql-header[value="1"]', title: 'h1' },
+  { Choice: '.ql-header[value="2"]', title: 'h2' },
+  { Choice: '.ql-align', title: '瀵归綈鏂瑰紡' },
+  { Choice: '.ql-color', title: '瀛椾綋棰滆壊' },
+  { Choice: '.ql-background', title: '鑳屾櫙棰滆壊' },
+  { Choice: '.ql-image', title: '鍥惧儚' },
+  { Choice: '.ql-video', title: '瑙嗛' },
+  { Choice: '.ql-link', title: '娣诲姞閾炬帴' },
+  { Choice: '.ql-formula', title: '鎻掑叆鍏紡' },
+  { Choice: '.ql-clean', title: '娓呴櫎瀛椾綋鏍煎紡' },
+  { Choice: '.ql-script[value="sub"]', title: '涓嬫爣' },
+  { Choice: '.ql-script[value="super"]', title: '涓婃爣' },
+  { Choice: '.ql-indent[value="-1"]', title: '鍚戝乏缂╄繘' },
+  { Choice: '.ql-indent[value="+1"]', title: '鍚戝彸缂╄繘' },
+  { Choice: '.ql-header .ql-picker-label', title: '鏍囬澶у皬' },
+  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '鏍囬涓�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '鏍囬浜�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '鏍囬涓�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '鏍囬鍥�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '鏍囬浜�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '鏍囬鍏�' },
+  { Choice: '.ql-header .ql-picker-item:last-child', title: '鏍囧噯' },
+  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '灏忓彿' },
+  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '澶у彿' },
+  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '瓒呭ぇ鍙�' },
+  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '鏍囧噯' },
+  { Choice: '.ql-align .ql-picker-item:first-child', title: '灞呭乏瀵归綈' },
+  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '灞呬腑瀵归綈' },
+  { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '灞呭彸瀵归綈' },
+  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '涓ょ瀵归綈' }
+]
+
+
 export default {
   name: "newsManagement",
-  components: {Editor},
+  components: {quillEditor},
   data(){
     return{
       // 鍥剧墖棰勮
@@ -316,13 +413,126 @@
           value:1
         }
 
-      ]
+      ],
+
+      file: null,
+      Quill:'',
+      defaultValue: '',
+      editorOption: {
+        placeholder: '璇峰湪杩欓噷杈撳叆',
+        theme: 'snow', //涓婚 snow/bubble
+        modules: {
+          history: {
+            delay: 1000,
+            maxStack: 50,
+            userOnly: false
+          },
+          toolbar: {
+            container: toolbarOptions,
+            handlers: {
+              myUploadBtn: this.myMethod,
+            }
+          }
+        }
+      }
     }
   },
+  // 鍦ㄧ粍浠跺垱寤哄墠娉ㄥ唽
+  beforeCreate() {
+    Quill.register(VideoBlot, true);
+  },
   mounted() {
+    //鍒濆鍖�
+    this.Quill=this.$refs.QuillEditor.quill
     this.getNewsList();
+    this.initTitle();
+    this.initButton();
   },
   methods:{
+    onEditorBlur(editor) {
+    },
+    // 鑾峰緱鐒︾偣
+    onEditorFocus(editor) {
+    },
+    // 寮�濮�
+    onEditorReady(editor) {
+    },
+    myMethod(){
+      this.$refs.upload.handleClick();
+    },
+    initButton(){
+      const editorButton = document.querySelector('.ql-myUploadBtn')
+      editorButton.innerHTML = '<svg t="1751966766109" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1530" fill="currentColor"  style="width: 1em; height: 1em; vertical-align: middle;"><path d="M1024 693.248q0 25.6-8.704 48.128t-24.576 40.448-36.864 30.208-45.568 16.384l1.024 1.024-17.408 0-4.096 0-4.096 0-675.84 0q-5.12 1.024-16.384 1.024-39.936 0-74.752-15.36t-60.928-41.472-40.96-60.928-14.848-74.752 14.848-74.752 40.96-60.928 60.928-41.472 74.752-15.36l1.024 0q-1.024-8.192-1.024-15.36l0-16.384q0-72.704 27.648-137.216t75.776-112.128 112.128-75.264 136.704-27.648 137.216 27.648 112.64 75.264 75.776 112.128 27.648 137.216q0 37.888-8.192 74.24t-22.528 69.12q5.12-1.024 10.752-1.536t10.752-0.512q27.648 0 52.736 10.752t43.52 29.696 29.184 44.032 10.752 53.76zM665.6 571.392q20.48 0 26.624-4.608t-8.192-22.016q-14.336-18.432-31.744-48.128t-36.352-60.416-38.4-57.344-37.888-38.912q-18.432-13.312-27.136-14.336t-25.088 12.288q-18.432 15.36-35.84 38.912t-35.328 50.176-35.84 52.224-36.352 45.056q-18.432 18.432-13.312 32.768t25.6 14.336l16.384 0q9.216 0 19.968 0.512t20.992 0.512l17.408 0q14.336 1.024 18.432 9.728t4.096 24.064q0 17.408-0.512 30.72t-0.512 25.6-0.512 25.6-0.512 30.72q0 7.168 1.536 15.36t5.632 15.36 12.288 11.776 21.504 4.608l23.552 0q9.216 0 27.648 1.024 24.576 0 28.16-12.288t3.584-38.912q0-23.552 0.512-42.496t0.512-51.712q0-23.552 4.608-36.352t19.968-12.8q11.264 0 32.256-0.512t32.256-0.512z" p-id="1531"></path></svg>'
+    },
+
+    initTitle() {
+      document.getElementsByClassName('ql-editor')[0].dataset.placeholder = ''
+      for (let item of titleConfig) {
+        let tip = document.querySelector('.quill-editor ' + item.Choice)
+        if (!tip) continue
+        tip.setAttribute('title', item.title)
+      }
+    },
+    handleUploadEdit(file){
+      const fileType = file.type
+      const isImage = fileType.includes('image')
+      const isVideo = fileType.includes('video')
+
+      if (!isImage && !isVideo) {
+        this.$Message.error('璇蜂笂浼犲浘鐗囨垨瑙嗛鏂囦欢')
+        return false
+      }
+
+      if (file.size > 20 * 1024 * 1024) {
+        this.$Message.error('鏂囦欢澶у皬涓嶈兘瓒呰繃20MB')
+        return false
+      }
+
+      this.file = file
+      this.uploadFile2()
+      return false
+    },
+    uploadFile2() {
+
+      if (!this.file) return
+
+      this.submitLoading = true
+      const formData = new FormData()
+      formData.append('file', this.file)
+      uploadFileByLmk(formData).then(res => {
+        this.submitLoading = false
+        if (res.code === 200) {
+          let url = res.data.url;
+          let fileKey = res.data.fileKey;
+          let fileType = this.getFileType(this.file);
+
+          const range = this.Quill.getSelection();
+          const index = range ? range.index : this.Quill.getLength();
+
+          console.log("--------");
+          if (fileType === 'video') {
+            this.Quill.insertEmbed(index, 'video', {
+              url:url,
+              controls:'controls',
+              width:'100%',
+              height:'auto'
+            });
+          } else if (fileType === 'image') {
+            this.Quill.insertEmbed(index, "image", url);
+          } else {
+            // 濡傛灉涓嶆槸鍥剧墖鎴栬棰戯紝鍙互澶勭悊鍏朵粬绫诲瀷鎴栫粰鍑烘彁绀�
+            this.$Message.warning('涓嶆敮鎸佺殑鏂囦欢绫诲瀷');
+            return;
+          }
+          console.log("--------");
+          console.log(this.newsForm.content)
+          this.Quill.setSelection(index + 1);
+          this.$Message.success('涓婁紶鎴愬姛')
+        }
+      }).catch(() => {
+        this.submitLoading = false
+      })
+    },
     getNewsList(){
       this.loading = true
       getNews(this.searchForm).then(res =>{
@@ -338,54 +548,57 @@
         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
-            })
-          }
 
-        }
-      })
+    saveOrUpdate(){
+      console.log(this.newsForm)
+      // 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
@@ -402,6 +615,7 @@
 
       })
     },
+
     openEdit(row){
       this.modelTitle = '淇敼鏂伴椈';
       this.modelShow = true;
@@ -411,18 +625,23 @@
       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 = '';
+      this.newsForm.content = '';
+      this.newsForm.publish = 0;
 
     },
+
     detail(row){
       this.modelTitle = '娲诲姩璇︽儏'
       this.infoModelShow = true
       this.newsInfo = row
     },
+
     changeStatus(row,action){
       row.statusLoading = true;
 
@@ -436,6 +655,7 @@
         row.statusLoading = false
       })
     },
+
     // 琛ㄦ牸閫夋嫨鍙樺寲
     showSelect(selection) {
       this.selectList = selection.map(item => item.id)
@@ -449,6 +669,7 @@
       this.searchForm.pageNumber = 1
       this.getNewsList()
     },
+
     resetSearch(){
       this.$refs.searchForm.resetFields()
       this.searchForm.pageNumber = 1
@@ -460,6 +681,11 @@
 </script>
 
 <style scoped lang="scss">
+.ql-editor .ql-video {
+  width: 50%;
+  height: auto; /* 鏍规嵁浣犵殑闇�姹傝皟鏁撮珮搴� */
+  max-width: 100%;
+}
 .activity-management {
   .search-form {
     padding: 16px;
@@ -540,4 +766,86 @@
     }
   }
 }
+/*
+  鏂囧瓧澶у皬
+*/
+.ql-snow .ql-picker.ql-size{
+  width: 70px;  // 鑿滃崟鏍忓崰姣斿搴�
+}
+/*
+  瀛椾綋
+*/
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
+  content: "榛戜綋";
+  font-family: "SimHei";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
+  content: "寰蒋闆呴粦";
+  font-family: "Microsoft YaHei";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
+  content: "妤蜂綋";
+  font-family: "KaiTi";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
+  content: "浠垮畫";
+  font-family: "FangSong";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
+  content: "Arial";
+  font-family: "Arial";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
+  content: "Times New Roman";
+  font-family: "Times New Roman";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
+  content: "sans-serif";
+  font-family: "sans-serif";
+}
+
+.ql-font-SimSun {
+  font-family: "SimSun";
+}
+
+.ql-font-SimHei {
+  font-family: "SimHei";
+}
+
+.ql-font-Microsoft-YaHei {
+  font-family: "Microsoft YaHei";
+}
+
+.ql-font-KaiTi {
+  font-family: "KaiTi";
+}
+
+.ql-font-FangSong {
+  font-family: "FangSong";
+}
+
+.ql-font-Arial {
+  font-family: "Arial";
+}
+
+.ql-font-Times-New-Roman {
+  font-family: "Times New Roman";
+}
+
+.ql-font-sans-serif {
+  font-family: "sans-serif";
+}
 </style>
diff --git a/seller/package.json b/seller/package.json
index a64320f..55f0ac0 100644
--- a/seller/package.json
+++ b/seller/package.json
@@ -18,6 +18,10 @@
     "js-cookie": "^2.2.1",
     "node-sass": "^4.14.1",
     "price-color": "^1.0.2",
+    "quill": "^1.3.7",
+    "quill-image-drop-module": "^1.0.3",
+    "quill-image-extend-module": "^1.1.2",
+    "quill-image-resize-module": "^3.0.0",
     "s": "^1.0.0",
     "sass-loader": "^8.0.2",
     "sockjs-client": "^1.4.0",
@@ -30,6 +34,7 @@
     "vue-lazyload": "^1.3.3",
     "vue-print-nb": "^1.7.5",
     "vue-qr": "^2.3.0",
+    "vue-quill-editor": "^3.0.6",
     "vue-router": "^3.1.3",
     "vuedraggable": "^2.23.2",
     "vuex": "^3.4.0",
diff --git a/seller/src/api/activity.js b/seller/src/api/activity.js
new file mode 100644
index 0000000..09cb4bf
--- /dev/null
+++ b/seller/src/api/activity.js
@@ -0,0 +1,31 @@
+import { commonUrl, getRequest,postRequest,deleteRequest,putRequest, uploadFileRequest, uploadFile, request} from "@/libs/axios";
+import { postRequest2 } from "@/libs/axios";
+import {putRequest2} from "../libs/axios";
+
+
+
+// 娲诲姩璇︽儏
+export const activityInfoById = (params) => {
+  return getRequest("/"+params);
+}
+
+// 娲诲姩鍒嗛〉鍒楄〃
+export const getMyApplyActivityPage = (params) => {
+  return getRequest("/lmk/activity/applyActivityPage", params);
+}
+
+export const addActivity = (params) =>{
+  return postRequest2("/lmk/activity/add",params);
+}
+
+export const delActivityById = (params) =>{
+  return deleteRequest();
+}
+
+export const delActivityBatch = (params) =>{
+  return deleteRequest();
+}
+
+export const editActivity = (params) =>{
+  return putRequest2("/lmk/activity",params);
+}
diff --git a/seller/src/libs/axios.js b/seller/src/libs/axios.js
index 768708e..a3dbfdc 100644
--- a/seller/src/libs/axios.js
+++ b/seller/src/libs/axios.js
@@ -17,6 +17,9 @@
     : BASE.API_PROD.common;
 // 鏂囦欢涓婁紶鎺ュ彛
 export const uploadFile = commonUrl + "/common/common/upload/file";
+
+export const uploadFile2 = commonUrl + "/common/lmk/file/upload";
+
 var isRefreshToken = 0;
 const refreshToken = getTokenDebounce();
 const service = axios.create({
@@ -229,6 +232,18 @@
   return service(data);
 };
 
+export const postRequest2 = (url, params, headers) => {
+  let accessToken = getStore("accessToken");
+  return service({
+    method: "post",
+    url,
+    data: params, // 鐩存帴浼犲璞★紝涓嶈鐢� [params] 鍖呰
+    headers: {
+      "Content-Type": "application/json",
+    },
+  });
+};
+
 export const postRequest = (url, params, headers) => {
   let accessToken = getStore("accessToken");
   return service({
@@ -316,6 +331,17 @@
     }
   });
 };
+export const putRequest2 = (url, params, headers) => {
+  let accessToken = getStore("accessToken");
+  return service({
+    method: "put",
+    url,
+    data: params, // 鐩存帴浼犲璞★紝涓嶈鐢� [params] 鍖呰
+    headers: {
+      "Content-Type": "application/json",
+    },
+  });
+};
 
 export const putRequestWithNoForm = (url, params) => {
   let accessToken = getStore("accessToken");
@@ -368,6 +394,29 @@
   });
 };
 
+export const uploadFileRequest2 = (url, params) => {
+  let accessToken = getStore("accessToken");
+  return axios({  // 鐩存帴浣跨敤 axios锛岃�屼笉鏄� service锛堥伩鍏� baseUrl 褰卞搷锛�
+    method: "post",
+    url: `${url}`,  // 鐩存帴浼犲畬鏁� URL锛屽 uploadFile
+    data: params,
+    headers: {
+      accessToken: accessToken,
+      'Content-Type': 'multipart/form-data'
+    }
+  });
+};
+
+export const delFileByFileKeyRequest = (url, params) => {
+  let accessToken = getStore("accessToken");
+  return axios({  // 鐩存帴浣跨敤 axios锛岃�屼笉鏄� service锛堥伩鍏� baseUrl 褰卞搷锛�
+    method: "DELETE",
+    url: `${url}` + '/'+params,  // 鐩存帴浼犲畬鏁� URL锛屽 uploadFile
+    headers: {
+      accessToken: accessToken,
+    }
+  });
+};
 
 
 /**
diff --git a/seller/src/views/activity/activityList.vue b/seller/src/views/activity/activityList.vue
new file mode 100644
index 0000000..bb543ab
--- /dev/null
+++ b/seller/src/views/activity/activityList.vue
@@ -0,0 +1,1461 @@
+<template>
+  <div class="activity-management">
+    <Card>
+      <!-- 鎼滅储琛ㄥ崟 -->
+      <Form
+        ref="searchForm"
+        @keydown.enter.native="handleSearch"
+        :model="searchForm"
+        inline
+        :label-width="80"
+        class="search-form"
+      >
+        <FormItem label="娲诲姩鍚嶇О" prop="activityName">
+          <Input
+            type="text"
+            v-model="searchForm.activityName"
+            placeholder="璇疯緭鍏ユ椿鍔ㄥ悕绉�"
+            clearable
+            @on-clear="handleSearch"
+            style="width: 180px"
+          />
+        </FormItem>
+        <FormItem label="娲诲姩绫诲瀷" prop="activityType">
+          <Select
+            v-model="searchForm.activityType"
+            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>
+        <FormItem label="鎶ュ悕寮�濮嬫椂闂�" prop="reportStartTime">
+          <DatePicker
+            :value="searchForm.reportStartTime"
+            type="datetime"
+            placeholder="閫夋嫨寮�濮嬫椂闂�"
+            style="width: 180px"
+            @on-change="handleSearch('reportStart', $event)"
+            @on-clear="handleSearch"
+          ></DatePicker>
+        </FormItem>
+        <FormItem label="鎶ュ悕缁撴潫鏃堕棿" prop="reportEndTime">
+          <DatePicker
+            :value="searchForm.reportEndTime"
+            type="datetime"
+            placeholder="閫夋嫨缁撴潫鏃堕棿"
+            style="width: 180px"
+            @on-clear="handleSearch"
+            @on-change="handleSearch('reportEnd', $event)"
+          ></DatePicker>
+        </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>
+      </Row>
+
+      <!-- 娲诲姩琛ㄦ牸 -->
+      <Table
+        :loading="loading"
+        border
+        :columns="columns"
+        :data="activityList"
+        ref="table"
+        class="activity-table"
+      >
+        <!-- 灏侀潰灞曠ず鎻掓Ы -->
+        <template slot-scope="{ row }" slot="url">
+          <div class="media-container">
+            <!-- 鍥剧墖绫诲瀷 -->
+            <template v-if="row.coverType === 'image'">
+              <img
+                :src="row.url"
+                alt="娲诲姩灏侀潰"
+                class="thumbnail"
+                @click="previewImage(row.url)"
+              >
+            </template>
+            <!-- 瑙嗛绫诲瀷 -->
+            <template v-else-if="row.coverType === 'video'">
+              <video
+                :src="row.url"
+                class="video-player"
+                controls
+              ></video>
+            </template>
+            <!-- 鏂囧瓧绫诲瀷 -->
+            <template v-else>
+              <div class="text-cover">{{ row.cover || '鏆傛棤灏侀潰鍐呭' }}</div>
+            </template>
+          </div>
+        </template>
+
+        <!-- 鎿嶄綔鎸夐挳鎻掓Ы -->
+        <template slot-scope="{ row }" slot="action">
+          <div class="action-btns">
+            <Button
+              type="info"
+              size="small"
+              @click="detail(row)"
+            >璇︽儏</Button>
+            <Button
+              type="info"
+              size="small"
+              @click="openEdit(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="activityFrom" :label-width="100" :rules="rules">
+          <Row :gutter="16">
+            <Col span="12">
+              <FormItem label="娲诲姩鍚嶇О" prop="activityName">
+                <Input
+                  v-model="activityFrom.activityName"
+                  placeholder="璇疯緭鍏ユ椿鍔ㄥ悕绉�"
+                  clearable
+                />
+              </FormItem>
+            </Col>
+            <Col span="12">
+              <FormItem label="娲诲姩绫诲瀷" prop="activityType" :label-width="100">
+                <Select
+                  v-model="activityFrom.activityType"
+                  placeholder="璇烽�夋嫨娲诲姩绫诲瀷"
+                  clearable
+                >
+                  <Option
+                    v-for="item in typeSelect"
+                    :value="item.value"
+                    :key="item.id"
+                  >
+                    {{ item.label }}
+                  </Option>
+                </Select>
+              </FormItem>
+            </Col>
+            <Col span="12">
+              <FormItem label="鎶ュ悕鏃堕棿娈�" prop="reportTime">
+                <DatePicker
+                  v-model="activityFrom.reportTime"
+                  type="datetimerange"
+                  format="yyyy-MM-dd HH:mm"
+                  placeholder="璇烽�夋嫨鎶ュ悕鏃堕棿娈�"
+                  style="width: 100%"
+                ></DatePicker>
+              </FormItem>
+            </Col>
+            <Col span="12">
+              <FormItem label="娲诲姩鏃堕棿娈�" prop="time">
+                <DatePicker
+                  v-model="activityFrom.time"
+                  type="datetimerange"
+                  format="yyyy-MM-dd HH:mm"
+                  placeholder="璇烽�夋嫨娲诲姩鏃堕棿娈�"
+                  style="width: 100%"
+                ></DatePicker>
+              </FormItem>
+            </Col>
+            <Col span="12">
+              <FormItem label="灏侀潰绫诲瀷" prop="coverType" :labelWidth="100">
+                <Select
+                  v-model="coverType"
+                  placeholder="璇烽�夋嫨灏侀潰绫诲瀷"
+                  @on-change="handleCoverTypeChange"
+                >
+                  <Option
+                    v-for="item in coverTypeOptions"
+                    :value="item.value"
+                    :key="item.id"
+                  >
+                    {{ item.value }}
+                  </Option>
+                </Select>
+              </FormItem>
+            </Col>
+            <Col span="24" v-if="coverType === '杈撳叆鏂囧瓧灏侀潰'">
+              <FormItem label="灏侀潰鏂囧瓧" prop="cover">
+                <Input
+                  v-model="activityFrom.cover"
+                  type="textarea"
+                  :rows="2"
+                  placeholder="璇疯緭鍏ュ皝闈㈡枃瀛�"
+                  style="width: 50%"
+                />
+              </FormItem>
+            </Col>
+            <Col span="24" v-if="coverType === '閫夋嫨鏂囦欢灏侀潰'">
+              <FormItem label="涓婁紶灏侀潰" prop="cover">
+                <Upload
+                  :before-upload="handleBeforeUpload"
+                  :format="['jpg','jpeg','png','gif','mp4','mov']"
+                  :max-size="20480"
+                  action=""
+                  accept="image/*,video/*"
+                >
+                  <Button icon="ios-cloud-upload-outline">涓婁紶灏侀潰鏂囦欢</Button>
+                  <div class="upload-tip">鏀寔鍥剧墖鎴栬棰戞枃浠讹紝鏈�澶�20MB</div>
+                </Upload>
+                <div v-if="file" class="upload-file-info">
+                  宸查�夋枃浠�: {{ file.name }}
+                  <Button type="text" @click="handleRemove">鍒犻櫎</Button>
+                </div>
+              </FormItem>
+            </Col>
+            <!-- 杩欎袱涓〃鍗曢」鍦ㄥ悓涓�Row鍐咃紝浼氭樉绀哄湪鍚屼竴琛� -->
+            <Col span="12">
+              <FormItem label="浜烘暟闄愬埗" prop="limitUserNum">
+                <InputNumber
+                  v-model="activityFrom.limitUserNum"
+                  :min="1"
+                  placeholder="璇疯緭鍏ユ渶澶т汉鏁�"
+                  style="width: 100%"
+                />
+              </FormItem>
+            </Col>
+            <Col span="12" v-if="activityFrom.activityType === 'offline'">
+              <FormItem label="娲诲姩鍦扮偣" prop="activityLocation" >
+                <Input
+                  v-model="activityFrom.activityLocation"
+                  placeholder="璇疯緭鍏ユ椿鍔ㄥ湴鐐�"
+                />
+              </FormItem>
+            </Col>
+            <Col span="24">
+              <FormItem label="娲诲姩鍐呭锛�" prop="activityContent">
+
+                <!-- 鍩轰簬elementUi鐨勪笂浼犵粍浠� el-upload begin-->
+                <Upload
+                  :show-upload-list="false"
+                  ref="upload"
+                  style="display: none"
+                  :before-upload="handleUploadEdit"
+                  :format="['jpg','jpeg','png','gif','mp4','mov']"
+                  :max-size="20480"
+                  action=""
+                  accept="image/*,video/*"
+                >
+                </Upload>
+                <!-- 鍩轰簬elementUi鐨勪笂浼犵粍浠� el-upload end-->
+                <quill-editor
+                  v-model="activityFrom.activityContent"
+                  ref="QuillEditor"
+                  class="editor"
+                  :options="editorOption"
+                  @blur="onEditorBlur($event)"
+                  @focus="onEditorFocus($event)"
+                  @ready="onEditorReady($event)"
+                >
+                </quill-editor>
+              </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>{{ 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%">
+      </Modal>
+    </Card>
+  </div>
+</template>
+
+<script>
+import {
+  getMyApplyActivityPage,
+  addActivity,
+  editActivity,
+} from "@/api/activity.js"
+import { uploadFile2,uploadFileRequest2,delFileByFileKeyRequest } from "@/libs/axios";
+
+import { quillEditor } from 'vue-quill-editor'
+import 'quill/dist/quill.core.css';
+import 'quill/dist/quill.snow.css';
+import 'quill/dist/quill.bubble.css';
+
+import * as Quill from 'quill' //寮曞叆缂栬緫鍣�
+import VideoBlot from './video.js';
+
+const toolbarOptions = [
+  ['bold', 'italic', 'underline', 'strike'],        // 鍔犵矖锛屾枩浣擄紝涓嬪垝绾匡紝鍒犻櫎绾�
+  ['blockquote', 'code-block'],                     //寮曠敤锛屼唬鐮佸潡
+  [{ 'header': 1 }, { 'header': 2 }],               // 鍑犵骇鏍囬
+  [{ 'list': 'ordered' }, { 'list': 'bullet' }],    // 鏈夊簭鍒楄〃锛屾棤搴忓垪琛�
+  [{ 'script': 'sub' }, { 'script': 'super' }],     // 涓嬭鏍囷紝涓婅鏍�
+  [{ 'indent': '-1' }, { 'indent': '+1' }],         // 缂╄繘
+  [{ 'direction': 'rtl' }],                         // 鏂囧瓧杈撳叆鏂瑰悜
+  [{ 'size': ['small', false, 'large', 'huge'] }],  // 瀛椾綋澶у皬
+  [{ 'header': [1, 2, 3, 4, 5, 6, false] }],        // 鏍囬
+  [{ 'color': [] }, { 'background': [] }],          // 棰滆壊閫夋嫨
+  // [{ 'font': [] }], // 瀛椾綋
+  [{ 'align': [] }],    // 灞呬腑
+  ['clean'],            // 娓呴櫎鏍峰紡,
+  ['link'],
+  ['myUploadBtn'],
+]
+
+// toolbar鏍囬
+const titleConfig = [
+  { Choice: '.ql-insertMetric', title: '璺宠浆閰嶇疆' },
+  { Choice: '.ql-bold', title: '鍔犵矖' },
+  { Choice: '.ql-italic', title: '鏂滀綋' },
+  { Choice: '.ql-underline', title: '涓嬪垝绾�' },
+  { Choice: '.ql-header', title: '娈佃惤鏍煎紡' },
+  { Choice: '.ql-strike', title: '鍒犻櫎绾�' },
+  { Choice: '.ql-blockquote', title: '鍧楀紩鐢�' },
+  { Choice: '.ql-code', title: '鎻掑叆浠g爜' },
+  { Choice: '.ql-code-block', title: '鎻掑叆浠g爜娈�' },
+  { Choice: '.ql-font', title: '瀛椾綋' },
+  { Choice: '.ql-size', title: '瀛椾綋澶у皬' },
+  { Choice: '.ql-list[value="ordered"]', title: '缂栧彿鍒楄〃' },
+  { Choice: '.ql-list[value="bullet"]', title: '椤圭洰鍒楄〃' },
+  { Choice: '.ql-direction', title: '鏂囨湰鏂瑰悜' },
+  { Choice: '.ql-header[value="1"]', title: 'h1' },
+  { Choice: '.ql-header[value="2"]', title: 'h2' },
+  { Choice: '.ql-align', title: '瀵归綈鏂瑰紡' },
+  { Choice: '.ql-color', title: '瀛椾綋棰滆壊' },
+  { Choice: '.ql-background', title: '鑳屾櫙棰滆壊' },
+  { Choice: '.ql-image', title: '鍥惧儚' },
+  { Choice: '.ql-video', title: '瑙嗛' },
+  { Choice: '.ql-link', title: '娣诲姞閾炬帴' },
+  { Choice: '.ql-formula', title: '鎻掑叆鍏紡' },
+  { Choice: '.ql-clean', title: '娓呴櫎瀛椾綋鏍煎紡' },
+  { Choice: '.ql-script[value="sub"]', title: '涓嬫爣' },
+  { Choice: '.ql-script[value="super"]', title: '涓婃爣' },
+  { Choice: '.ql-indent[value="-1"]', title: '鍚戝乏缂╄繘' },
+  { Choice: '.ql-indent[value="+1"]', title: '鍚戝彸缂╄繘' },
+  { Choice: '.ql-header .ql-picker-label', title: '鏍囬澶у皬' },
+  { Choice: '.ql-header .ql-picker-item[data-value="1"]', title: '鏍囬涓�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="2"]', title: '鏍囬浜�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="3"]', title: '鏍囬涓�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="4"]', title: '鏍囬鍥�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="5"]', title: '鏍囬浜�' },
+  { Choice: '.ql-header .ql-picker-item[data-value="6"]', title: '鏍囬鍏�' },
+  { Choice: '.ql-header .ql-picker-item:last-child', title: '鏍囧噯' },
+  { Choice: '.ql-size .ql-picker-item[data-value="small"]', title: '灏忓彿' },
+  { Choice: '.ql-size .ql-picker-item[data-value="large"]', title: '澶у彿' },
+  { Choice: '.ql-size .ql-picker-item[data-value="huge"]', title: '瓒呭ぇ鍙�' },
+  { Choice: '.ql-size .ql-picker-item:nth-child(2)', title: '鏍囧噯' },
+  { Choice: '.ql-align .ql-picker-item:first-child', title: '灞呭乏瀵归綈' },
+  { Choice: '.ql-align .ql-picker-item[data-value="center"]', title: '灞呬腑瀵归綈' },
+  { Choice: '.ql-align .ql-picker-item[data-value="right"]', title: '灞呭彸瀵归綈' },
+  { Choice: '.ql-align .ql-picker-item[data-value="justify"]', title: '涓ょ瀵归綈' }
+]
+
+export default {
+  name: "ActivityList",
+  components: { quillEditor},
+  data() {
+    return {
+      infoModelShow: false, //璇︽儏model绐�
+      loading: false, //琛ㄦ牸loading鐘舵��
+      submitLoading: false, //鎻愪氦鎸夐挳loading鐘舵��
+      // 鎼滅储琛ㄥ崟
+      searchForm: {
+        audit: '',
+        activityName: '',
+        activityType: '',
+        reportStartTime: '',
+        reportEndTime: '',
+        pageNumber: 1,
+        pageSize: 10
+      },
+
+      // 娲诲姩鍒楄〃鏁版嵁
+      activityList: [],
+      total: 0,
+
+      // 娲诲姩绫诲瀷閫夐」
+      typeSelect: [
+        {id: 1, value: 'online', label: '绾夸笂'},
+        {id: 2, value: 'offline', label: '绾夸笅'}
+      ],
+      // 灏侀潰绫诲瀷閫夐」
+      coverTypeOptions: [
+        {id: 1, value: '杈撳叆鏂囧瓧灏侀潰'},
+        {id: 2, value: '閫夋嫨鏂囦欢灏侀潰'}
+      ],
+      coverType: '',
+      file: null,
+
+      // 娲诲姩琛ㄥ崟
+      activityFrom: {
+        id: '',
+        activityName: '',
+        activityType: '',
+        reportTime: [],
+        time: [],
+        activityContent: '',
+        cover: '',
+        coverType: '',
+        status: '',
+        reportStartTime: '',
+        reportEndTime: '',
+        startTime: '',
+        endTime: '',
+        recommend: false,
+        limitUserNum: 0,
+        activityLocation: '',
+      },
+      activityInfo: {
+        id: '',
+        activityName: '',
+        activityType: '',
+        reportTime: [],
+        time: [],
+        activityContent: '',
+        cover: '',
+        coverType: '',
+        status: '',
+        reportStartTime: '',
+        reportEndTime: '',
+        startTime: '',
+        endTime: '',
+        recommend: false,
+        limitUserNum: 0,
+        activityLocation: '',
+      },
+
+      // 琛ㄥ崟楠岃瘉瑙勫垯
+      rules: {
+        activityName: [
+          {required: true, message: '璇疯緭鍏ユ椿鍔ㄥ悕绉�', trigger: 'blur'},
+          {max: 50, message: '闀垮害涓嶈兘瓒呰繃50涓瓧绗�', trigger: 'blur'}
+        ],
+        activityType: [
+          {required: true, message: '璇烽�夋嫨娲诲姩绫诲瀷', trigger: 'change'}
+        ],
+        reportTime: [
+          {type: 'array', required: true, message: '璇烽�夋嫨鎶ュ悕鏃堕棿娈�', trigger: 'change'},
+          {validator: this.validateReportTime, trigger: 'change'}
+        ],
+        time: [
+          {type: 'array', required: true, message: '璇烽�夋嫨娲诲姩鏃堕棿娈�', trigger: 'change'},
+          {validator: this.validateActivityTime, trigger: 'change'}
+        ],
+        cover: [
+          {required: true, message: '璇疯緭鍏ュ皝闈㈠唴瀹�', trigger: 'blur'}
+        ],
+        coverType: [
+          {required: true, message: '璇烽�夋嫨灏侀潰绫诲瀷', trigger: 'blur'}
+        ],
+        limitUserNum: [
+          {required: true, type: 'number', message: '璇疯緭鍏ヤ汉鏁伴檺鍒�', trigger: 'blur'},
+          {type: 'number', min: 1, message: '浜烘暟涓嶈兘灏戜簬1浜�', trigger: 'blur'}
+        ],
+        activityLocation: [
+          {required: true, message: '璇疯緭鍏ユ椿鍔ㄥ湴鐐�', trigger: 'blur'},
+          {max: 100, message: '闀垮害涓嶈兘瓒呰繃100涓瓧绗�', trigger: 'blur'}
+        ],
+        activityContent: [
+          {required: false, message: '璇疯緭鍏ユ椿鍔ㄥ唴瀹�', trigger: 'blur'}
+        ]
+      },
+
+      // 琛ㄦ牸鍒楅厤缃�
+      columns: [
+
+        {
+          title: '娲诲姩鍚嶇О',
+          key: 'activityName',
+          minWidth: 120,
+          tooltip: true
+        },
+        {
+          title: '娲诲姩绫诲瀷',
+          key: 'activityType',
+          width: 100,
+          align: 'center',
+          render: (h, params) => {
+            return h('Tag', {}, params.row.activityType === 'online' ? '绾夸笂' : '绾夸笅')
+          }
+        },
+        {
+          title: '瀹℃牳鐘舵��',
+          key: 'auditStatus',
+          width: 100,
+          align: 'center',
+          render: (h, params) => {
+            const status = params.row.auditStatus;
+            let tagText, tagColor;
+
+            // 鏍规嵁鐘舵�佽缃枃妗堝拰棰滆壊
+            switch (status) {
+              case 0:
+                tagText = '瀹℃牳涓�';
+                tagColor = 'orange';  // 姗欒壊琛ㄧず杩涜涓�
+                break;
+              case 1:
+                tagText = '宸插鏍�';
+                tagColor = 'green';   // 缁胯壊琛ㄧず閫氳繃
+                break;
+              case 2:
+                tagText = '鏈�氳繃';
+                tagColor = 'red';     // 绾㈣壊琛ㄧず鎷掔粷
+                break;
+              default:
+                tagText = '鏈煡鐘舵��';
+                tagColor = 'default'; // 榛樿鐏拌壊
+            }
+
+            return h('Tag', {
+              props: {
+                color: tagColor,
+              },
+            }, tagText);
+          },
+        },
+        {
+          title: '鐘舵��',
+          key: 'status',
+          width: 100,
+          align: 'center',
+          render: (h, params) => {
+            const status = params.row.status;
+            const statusMap = {
+              'noStart': {text: '鏈紑濮�', color: 'default'},
+              'report': {text: '鎶ュ悕涓�', color: 'green'},
+              'inProgress': {text: '杩涜涓�', color: 'cyan'},
+              'end': {text: '宸茬粨鏉�', color: 'red'}
+            };
+            const currentStatus = statusMap[status] || {text: status, color: 'default'};
+            return h('Tag', {
+              props: {
+                color: currentStatus.color
+              }
+            }, currentStatus.text);
+          }
+        },
+        {
+          title: '娲诲姩鎶ュ悕鏃堕棿娈�',
+          key: 'activityReportTimeRange',
+          width: 300,
+          render: (h, params) => {
+            return h('div', [
+              h('div', `寮�濮�: ${this.formatDate(params.row.reportStartTime)}`),
+              h('div', `缁撴潫: ${this.formatDate(params.row.reportEndTime)}`)
+            ])
+          }
+        },
+        {
+          title: '娲诲姩鏃堕棿娈�',
+          key: 'activityTimeRange',
+          width: 300,
+          render: (h, params) => {
+            return h('div', [
+              h('div', `寮�濮�: ${this.formatDate(params.row.startTime)}`),
+              h('div', `缁撴潫: ${this.formatDate(params.row.endTime)}`)
+            ])
+          }
+        },
+        {
+          title: '灏侀潰',
+          key: 'url',
+          slot: 'url',
+          width: 150,
+          align: 'center'
+        },
+        {
+          title: '灏侀潰绫诲瀷',
+          key: 'coverType',
+          width: 100,
+          align: 'center',
+          render: (h, params) => {
+            const typeMap = {
+              text: '鏂囨湰',
+              video: '瑙嗛',
+              image: '鍥剧墖'
+            };
+            const text = typeMap[params.row.coverType] || params.row.coverType;
+            return h('span', text);
+          }
+        },
+        {
+          title: '浜烘暟闄愬埗',
+          key: 'limitUserNum',
+          width: 100,
+          align: 'center'
+        },
+        {
+          title: '娲诲姩鍦扮偣',
+          key: 'activityLocation',
+          minWidth: 120,
+          tooltip: true
+        },
+        {
+          title: '鎿嶄綔',
+          slot: 'action',
+          width: 280,
+          align: 'center',
+          fixed: 'right'
+        }
+      ],
+
+      // 鍥剧墖棰勮
+      previewVisible: false,
+      previewImageUrl: '',
+
+      // 妯℃�佹鎺у埗
+      modelShow: false,
+      modelTitle: '',
+
+      //缂栬緫鍣ㄩ厤缃�
+      // 瀵屾枃鏈紪杈戝櫒閰嶇疆
+      Quill:'',
+      defaultValue: '',
+      editorOption: {
+        placeholder: '璇峰湪杩欓噷杈撳叆',
+        theme: 'snow', //涓婚 snow/bubble
+        modules: {
+          history: {
+            delay: 1000,
+            maxStack: 50,
+            userOnly: false
+          },
+          toolbar: {
+            container: toolbarOptions,
+            handlers: {
+              myUploadBtn: this.myMethod,
+            }
+          }
+        }
+      }
+
+    }
+  },
+  // 鍦ㄧ粍浠跺垱寤哄墠娉ㄥ唽
+  beforeCreate() {
+    Quill.register(VideoBlot, true);
+  },
+  mounted() {
+    //鍒濆鍖�
+    this.Quill=this.$refs.QuillEditor.quill
+    this.init()
+    this.initTitle()
+    this.initButton();
+  },
+  methods: {
+    myMethod(){
+      this.$refs.upload.handleClick();
+    },
+    initButton(){
+      const editorButton = document.querySelector('.ql-myUploadBtn')
+      editorButton.innerHTML = '<svg t="1751966766109" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1530" fill="currentColor"  style="width: 1em; height: 1em; vertical-align: middle;"><path d="M1024 693.248q0 25.6-8.704 48.128t-24.576 40.448-36.864 30.208-45.568 16.384l1.024 1.024-17.408 0-4.096 0-4.096 0-675.84 0q-5.12 1.024-16.384 1.024-39.936 0-74.752-15.36t-60.928-41.472-40.96-60.928-14.848-74.752 14.848-74.752 40.96-60.928 60.928-41.472 74.752-15.36l1.024 0q-1.024-8.192-1.024-15.36l0-16.384q0-72.704 27.648-137.216t75.776-112.128 112.128-75.264 136.704-27.648 137.216 27.648 112.64 75.264 75.776 112.128 27.648 137.216q0 37.888-8.192 74.24t-22.528 69.12q5.12-1.024 10.752-1.536t10.752-0.512q27.648 0 52.736 10.752t43.52 29.696 29.184 44.032 10.752 53.76zM665.6 571.392q20.48 0 26.624-4.608t-8.192-22.016q-14.336-18.432-31.744-48.128t-36.352-60.416-38.4-57.344-37.888-38.912q-18.432-13.312-27.136-14.336t-25.088 12.288q-18.432 15.36-35.84 38.912t-35.328 50.176-35.84 52.224-36.352 45.056q-18.432 18.432-13.312 32.768t25.6 14.336l16.384 0q9.216 0 19.968 0.512t20.992 0.512l17.408 0q14.336 1.024 18.432 9.728t4.096 24.064q0 17.408-0.512 30.72t-0.512 25.6-0.512 25.6-0.512 30.72q0 7.168 1.536 15.36t5.632 15.36 12.288 11.776 21.504 4.608l23.552 0q9.216 0 27.648 1.024 24.576 0 28.16-12.288t3.584-38.912q0-23.552 0.512-42.496t0.512-51.712q0-23.552 4.608-36.352t19.968-12.8q11.264 0 32.256-0.512t32.256-0.512z" p-id="1531"></path></svg>'
+    },
+
+    initTitle() {
+      document.getElementsByClassName('ql-editor')[0].dataset.placeholder = ''
+      for (let item of titleConfig) {
+        let tip = document.querySelector('.quill-editor ' + item.Choice)
+        if (!tip) continue
+        tip.setAttribute('title', item.title)
+      }
+    },
+
+    // 澶卞幓鐒︾偣
+    onEditorBlur(editor) {
+    },
+
+    // 鑾峰緱鐒︾偣
+    onEditorFocus(editor) {
+    },
+
+    // 寮�濮�
+    onEditorReady(editor) {
+    },
+    handleUploadEdit(file){
+      const fileType = file.type
+      const isImage = fileType.includes('image')
+      const isVideo = fileType.includes('video')
+
+      if (!isImage && !isVideo) {
+        this.$Message.error('璇蜂笂浼犲浘鐗囨垨瑙嗛鏂囦欢')
+        return false
+      }
+
+      if (file.size > 20 * 1024 * 1024) {
+        this.$Message.error('鏂囦欢澶у皬涓嶈兘瓒呰繃20MB')
+        return false
+      }
+
+      this.file = file
+      this.uploadFileEdit()
+      return false
+    },
+// 涓婁紶鏂囦欢
+    uploadFileEdit() {
+      if (!this.file) return
+
+      this.submitLoading = true
+      const formData = new FormData()
+      formData.append('file', this.file)
+      uploadFileRequest2(uploadFile2,formData).then(res => {
+        this.submitLoading = false
+        if (res.data.code === 200) {
+          let url = res.data.data.url;
+          let fileKey = res.data.data.fileKey;
+          let fileType = this.getFileType(this.file);
+
+          const range = this.Quill.getSelection();
+          const index = range ? range.index : this.Quill.getLength();
+
+          console.log(fileType)
+          if (fileType === 'video') {
+            this.Quill.insertEmbed(index, 'video', {
+              url:url,
+              controls:'controls',
+              width:'100%',
+              height:'auto'
+            });
+          } else if (fileType === 'image') {
+            this.Quill.insertEmbed(index, "image", url);
+          } else {
+            // 濡傛灉涓嶆槸鍥剧墖鎴栬棰戯紝鍙互澶勭悊鍏朵粬绫诲瀷鎴栫粰鍑烘彁绀�
+            this.$Message.warning('涓嶆敮鎸佺殑鏂囦欢绫诲瀷');
+            return;
+          }
+          console.log(this.activityFrom.activityContent)
+          this.Quill.setSelection(index + 1);
+          this.$Message.success('涓婁紶鎴愬姛')
+        }
+      }).catch(() => {
+        this.submitLoading = false
+      })
+    },
+    getFileType(file) {
+      // 鑾峰彇鏂囦欢绫诲瀷鎴栨墿灞曞悕
+      let type, extension;
+
+      if (file instanceof File) {
+        // 濡傛灉鏄疐ile瀵硅薄
+        type = file.type;
+        const name = file.name.toLowerCase();
+        extension = name.substring(name.lastIndexOf('.') + 1);
+      } else if (typeof file === 'string') {
+        // 濡傛灉鏄瓧绗︿覆锛堟枃浠跺悕鎴朥RL锛�
+        const name = file.toLowerCase();
+        extension = name.substring(name.lastIndexOf('.') + 1);
+
+        // 灏濊瘯浠嶶RL涓彁鍙朚IME绫诲瀷锛堝鏋滄湁锛�
+        const mimeMatch = file.match(/^data:(.+?);/);
+        if (mimeMatch) {
+          type = mimeMatch[1];
+        }
+      } else {
+        return 'unknown';
+      }
+
+      // 甯歌鍥剧墖鍜岃棰戠殑MIME绫诲瀷
+      const imageTypes = [
+        'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/bmp', 'image/svg+xml'
+      ];
+
+      const videoTypes = [
+        'video/mp4', 'video/webm', 'video/ogg', 'video/quicktime', 'video/x-msvideo', 'video/x-matroska'
+      ];
+
+      // 妫�鏌IME绫诲瀷
+      if (type) {
+        if (imageTypes.includes(type)) return 'image';
+        if (videoTypes.includes(type)) return 'video';
+      }
+
+      // 甯歌鍥剧墖鍜岃棰戠殑鎵╁睍鍚�
+      const imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'svg'];
+      const videoExtensions = ['mp4', 'webm', 'ogg', 'mov', 'avi', 'mkv'];
+
+      // 妫�鏌ユ枃浠舵墿灞曞悕
+      if (extension) {
+        if (imageExtensions.includes(extension)) return 'image';
+        if (videoExtensions.includes(extension)) return 'video';
+      }
+
+      return 'unknown';
+    },
+
+    escapeStringHTML(str) {
+      if (!str) return str;
+      str = str.replace(/&lt;/g, '<');
+      str = str.replace(/&gt;/g, '>');
+      return str;
+    },
+    // 鎻愪氦
+    detail(row) {
+      this.modelTitle = '娲诲姩璇︽儏'
+      this.infoModelShow = true
+      this.activityInfo = row
+      this.activityInfo.activityContent = this.escapeStringHTML(this.activityInfo.activityContent);
+      this.$nextTick(() => {
+        this.processVideos();
+      });
+
+    },
+    processVideos() {
+      const videos = this.$el.querySelectorAll('video');
+      videos.forEach(video => {
+        // 纭繚瑙嗛鍏冪礌鏈夊繀瑕佺殑灞炴��
+        video.setAttribute('controls', '');
+        video.setAttribute('playsinline', ''); // 閽堝绉诲姩绔�
+        video.load();
+      });
+    },
+    // 鑾峰彇瀵屾枃鏈紪杈戝櫒鐨勫唴瀹�
+    // 鍒濆鍖栨暟鎹�
+    init() {
+      this.getMyApplyActivityPage()
+    },
+
+    // 鑾峰彇娲诲姩鍒楄〃
+    getMyApplyActivityPage() {
+      this.loading = true
+      getMyApplyActivityPage(this.searchForm).then(res => {
+        this.loading = false
+        if (res.code === 200) {
+          // 涓烘瘡涓�琛屾坊鍔爈oading鐘舵��
+          this.activityList = res.data.map(item => ({
+            ...item,
+            recommendLoading: false,
+            statusLoading: false
+          }))
+          this.total = res.total
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+
+    // 鎼滅储娲诲姩
+    handleSearch(type, value) {
+      if (type === 'reportStart') {
+        this.searchForm.reportStartTime = value
+      } else if (type === 'reportEnd') {
+        this.searchForm.reportEndTime = value
+      }
+
+      this.searchForm.pageNumber = 1
+      this.getMyApplyActivityPage()
+    },
+
+    // 閲嶇疆鎼滅储
+    resetSearch() {
+      this.$refs.searchForm.resetFields()
+      this.searchForm.pageNumber = 1
+      this.getMyApplyActivityPage()
+    },
+
+    // 鏀瑰彉椤电爜
+    changePage(page) {
+      this.searchForm.pageNumber = page
+      this.getMyApplyActivityPage()
+    },
+
+    // 鏀瑰彉姣忛〉鏉℃暟
+    changePageSize(pageSize) {
+      this.searchForm.pageNumber = 1
+      this.searchForm.pageSize = pageSize
+      this.getMyApplyActivityPage()
+    },
+
+    // 鎵撳紑鏂板妯℃�佹
+    openAdd() {
+      this.modelTitle = '鏂板娲诲姩'
+      this.modelShow = true
+      this.coverType = '杈撳叆鏂囧瓧灏侀潰'
+      this.file = null
+      this.$refs.form.resetFields()
+      this.activityFrom.id = ''
+    },
+
+    // 鎵撳紑缂栬緫妯℃�佹
+    openEdit(row) {
+      this.modelTitle = '缂栬緫娲诲姩'
+      this.modelShow = true
+      this.$nextTick(() => {
+        this.$refs.form.resetFields()
+        console.log(row)
+        // 濉厖琛ㄥ崟鏁版嵁
+        this.activityFrom = {
+          id: row.id,
+          activityName: row.activityName,
+          activityType: row.activityType,
+          reportTime: [
+            this.formatDate(row.reportStartTime, 'YYYY-MM-DD HH:mm:ss'),
+            this.formatDate(row.reportEndTime, 'YYYY-MM-DD HH:mm:ss')
+          ],
+          time: [
+            this.formatDate(row.startTime, 'YYYY-MM-DD HH:mm:ss'),
+            this.formatDate(row.endTime, 'YYYY-MM-DD HH:mm:ss')
+          ],
+          activityContent: row.activityContent,
+          cover: row.cover,
+          coverType: row.coverType,
+          status: row.status,
+          reportStartTime: row.reportStartTime,
+          reportEndTime: row.reportEndTime,
+          startTime: row.startTime,
+          endTime: row.endTime,
+          recommend: row.recommend,
+          limitUserNum: row.limitUserNum,
+          activityLocation: row.activityLocation
+        }
+        // 璁剧疆灏侀潰绫诲瀷
+        this.coverType = row.coverType === 'text' ? '杈撳叆鏂囧瓧灏侀潰' : '閫夋嫨鏂囦欢灏侀潰'
+      })
+    },
+
+    infoModelClose() {
+      this.infoModelShow = false
+    },
+    // 鍏抽棴妯℃�佹
+    modelClose() {
+      this.modelShow = false
+      this.file = null
+      this.submitLoading = false
+      this.handleRemove();
+      this.$refs.form.resetFields()
+    },
+
+    // 淇濆瓨鎴栨洿鏂版椿鍔�
+    saveOrUpdate() {
+      // 璁剧疆灏侀潰绫诲瀷
+      this.activityFrom.coverType = this.coverType === '杈撳叆鏂囧瓧灏侀潰' ? 'text' :
+        this.file ? this.getFileCategory(this.file.type) :
+          this.activityFrom.coverType
+
+      this.$refs.form.validate(valid => {
+        if (valid) {
+          this.submitLoading = true
+
+          // 澶勭悊鏃堕棿鏁版嵁
+          if (this.activityFrom.reportTime && this.activityFrom.reportTime.length === 2) {
+            this.activityFrom.reportStartTime = this.formatDate(this.activityFrom.reportTime[0], 'YYYY-MM-DD HH:mm:ss')
+            this.activityFrom.reportEndTime = this.formatDate(this.activityFrom.reportTime[1], 'YYYY-MM-DD HH:mm:ss')
+          }
+
+          if (this.activityFrom.time && this.activityFrom.time.length === 2) {
+            this.activityFrom.startTime = this.formatDate(this.activityFrom.time[0], 'YYYY-MM-DD HH:mm:ss')
+            this.activityFrom.endTime = this.formatDate(this.activityFrom.time[1], 'YYYY-MM-DD HH:mm:ss')
+          }
+
+          const api = this.activityFrom.id ? editActivity : addActivity
+          api(this.activityFrom).then(res => {
+            this.submitLoading = false
+            if (res.code === 200) {
+              this.$Message.success(res.msg)
+              this.modelClose()
+              this.getMyApplyActivityPage()
+            }
+          }).catch(() => {
+            this.submitLoading = false
+          })
+        }
+      })
+    },
+    // 灏侀潰绫诲瀷鍙樺寲澶勭悊
+    handleCoverTypeChange(type) {
+      if (type === '閫夋嫨鏂囦欢灏侀潰') {
+        this.activityFrom.cover = ''
+      } else {
+        this.file = null
+      }
+    },
+    // 鏂囦欢涓婁紶鍓嶅鐞�
+    handleBeforeUpload(file) {
+      const fileType = file.type
+      const isImage = fileType.includes('image')
+      const isVideo = fileType.includes('video')
+
+      if (!isImage && !isVideo) {
+        this.$Message.error('璇蜂笂浼犲浘鐗囨垨瑙嗛鏂囦欢')
+        return false
+      }
+
+      if (file.size > 20 * 1024 * 1024) {
+        this.$Message.error('鏂囦欢澶у皬涓嶈兘瓒呰繃20MB')
+        return false
+      }
+
+      this.file = file
+      this.uploadFile()
+      return false
+    },
+    // 涓婁紶鏂囦欢
+    uploadFile() {
+      if (!this.file) return
+
+      this.submitLoading = true
+      const formData = new FormData()
+      formData.append('file', this.file)
+
+      uploadFileRequest2(uploadFile2,formData).then(res => {
+        this.submitLoading = false
+        if (res.data.code === 200) {
+          this.activityFrom.cover = res.data.data.fileKey
+          this.$Message.success('涓婁紶鎴愬姛')
+        }
+      }).catch(() => {
+        this.submitLoading = false
+      })
+    },
+
+    // 鍒犻櫎鏂囦欢
+    handleRemove() {
+      //鐐瑰嚮鍏抽棴绐楀彛鏃剁‘淇濇枃浠跺凡琚竻闄�
+      if (this.file === null) {
+        return;
+      }
+      if (!this.activityFrom.cover) {
+        this.file = null
+        return
+      }
+      delFileByFileKeyRequest(this.activityFrom.cover).then(res => {
+        if (res.code === 200) {
+          this.file = null
+          this.activityFrom.cover = ''
+        }
+      })
+    },
+
+    // 棰勮鍥剧墖
+    previewImage(url) {
+      this.previewImageUrl = url
+      this.previewVisible = true
+    },
+
+    // 鑾峰彇鏂囦欢鍒嗙被
+    getFileCategory(mimeType) {
+      const typeMap = {
+        'image': 'image',
+        'video': 'video',
+        'audio': 'audio',
+        'application': 'application'
+      }
+
+      const typePrefix = mimeType.split('/')[0]
+      return typeMap[typePrefix] || 'unknown'
+    },
+
+    // 鏍煎紡鍖栨棩鏈�
+    formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') {
+      if (!date) return '';
+
+      const d = new Date(date);
+      if (isNaN(d.getTime())) return '';
+
+      const padZero = (num) => String(num).padStart(2, '0'); // 鏇村彲闈犵殑琛ラ浂鏂规硶
+
+      const year = d.getFullYear();
+      const month = padZero(d.getMonth() + 1); // 鏈堜唤 0-11 鈫� +1
+      const day = padZero(d.getDate());
+      const hours = padZero(d.getHours());
+      const minutes = padZero(d.getMinutes());
+      const seconds = padZero(d.getSeconds());
+      return format
+        .replace('YYYY', year)
+        .replace('MM', month)
+        .replace('DD', day)
+        .replace('HH', hours)
+        .replace('mm', minutes)
+        .replace('ss', seconds);
+    },
+
+    // 楠岃瘉鎶ュ悕鏃堕棿
+    validateReportTime(rule, value, callback) {
+      if (!value || value.length !== 2) {
+        callback(new Error('璇烽�夋嫨瀹屾暣鐨勬姤鍚嶆椂闂存'))
+        return
+      }
+
+      const [start, end] = value
+      if (new Date(start) >= new Date(end)) {
+        callback(new Error('鎶ュ悕缁撴潫鏃堕棿蹇呴』鏅氫簬寮�濮嬫椂闂�'))
+        return
+      }
+
+      if (this.activityFrom.time && this.activityFrom.time.length === 2) {
+        const activityStart = this.activityFrom.time[0]
+        if (new Date(end) > new Date(activityStart)) {
+          callback(new Error('鎶ュ悕缁撴潫鏃堕棿涓嶈兘鏅氫簬娲诲姩寮�濮嬫椂闂�'))
+          return
+        }
+      }
+
+      callback()
+    },
+
+    // 楠岃瘉娲诲姩鏃堕棿
+    validateActivityTime(rule, value, callback) {
+      if (!value || value.length !== 2) {
+        callback(new Error('璇烽�夋嫨瀹屾暣鐨勬椿鍔ㄦ椂闂存'))
+        return
+      }
+
+      const [start, end] = value
+      if (new Date(start) >= new Date(end)) {
+        callback(new Error('娲诲姩缁撴潫鏃堕棿蹇呴』鏅氫簬寮�濮嬫椂闂�'))
+        return
+      }
+
+      if (this.activityFrom.reportTime && this.activityFrom.reportTime.length === 2) {
+        const reportEnd = this.activityFrom.reportTime[1]
+        if (new Date(reportEnd) > new Date(start)) {
+          callback(new Error('娲诲姩寮�濮嬫椂闂村繀椤绘櫄浜庢姤鍚嶇粨鏉熸椂闂�'))
+          return
+        }
+      }
+
+      callback()
+    }
+  },
+}
+</script>
+
+<style lang="scss" scoped>
+.quill-editor {
+
+}
+
+.ql-editor .ql-video {
+  width: 50%;
+  height: auto; /* 鏍规嵁浣犵殑闇�姹傝皟鏁撮珮搴� */
+  max-width: 100%;
+}
+
+.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;
+    }
+  }
+
+  .operation {
+    margin-bottom: 16px;
+
+    .ivu-btn {
+      margin-right: 8px;
+    }
+  }
+
+  .activity-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);
+        }
+      }
+
+      .video-player {
+        max-width: 100%;
+        max-height: 100px;
+        background: #000;
+      }
+
+      .text-cover {
+        padding: 8px;
+        background: #f8f8f9;
+        border-radius: 4px;
+        max-width: 100%;
+        word-break: break-all;
+      }
+    }
+
+    .action-btns {
+      display: flex;
+      flex-wrap: wrap;
+      justify-content: center;
+
+      .ivu-btn {
+        margin: 4px;
+        font-size: 12px;
+        padding: 2px 6px;
+        min-width: 60px;
+      }
+    }
+  }
+
+  .page-footer {
+    margin-top: 16px;
+    padding: 8px 0;
+  }
+
+  .members-modal {
+    .members-table {
+      margin-bottom: 16px;
+    }
+  }
+
+  .upload-file-info {
+    margin-top: 8px;
+    padding: 8px;
+    background: #f8f8f9;
+    border-radius: 4px;
+  }
+
+  .upload-tip {
+    font-size: 12px;
+    color: #999;
+    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;
+}
+/*
+  鏂囧瓧澶у皬
+*/
+.ql-snow .ql-picker.ql-size{
+  width: 70px;  // 鑿滃崟鏍忓崰姣斿搴�
+}
+/*
+  瀛椾綋
+*/
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=SimHei]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=SimHei]::before {
+  content: "榛戜綋";
+  font-family: "SimHei";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Microsoft-YaHei]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Microsoft-YaHei]::before {
+  content: "寰蒋闆呴粦";
+  font-family: "Microsoft YaHei";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=KaiTi]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=KaiTi]::before {
+  content: "妤蜂綋";
+  font-family: "KaiTi";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=FangSong]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=FangSong]::before {
+  content: "浠垮畫";
+  font-family: "FangSong";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Arial]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Arial]::before {
+  content: "Arial";
+  font-family: "Arial";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=Times-New-Roman]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=Times-New-Roman]::before {
+  content: "Times New Roman";
+  font-family: "Times New Roman";
+}
+
+.ql-snow .ql-picker.ql-font .ql-picker-label[data-value=sans-serif]::before,
+.ql-snow .ql-picker.ql-font .ql-picker-item[data-value=sans-serif]::before {
+  content: "sans-serif";
+  font-family: "sans-serif";
+}
+
+.ql-font-SimSun {
+  font-family: "SimSun";
+}
+
+.ql-font-SimHei {
+  font-family: "SimHei";
+}
+
+.ql-font-Microsoft-YaHei {
+  font-family: "Microsoft YaHei";
+}
+
+.ql-font-KaiTi {
+  font-family: "KaiTi";
+}
+
+.ql-font-FangSong {
+  font-family: "FangSong";
+}
+
+.ql-font-Arial {
+  font-family: "Arial";
+}
+
+.ql-font-Times-New-Roman {
+  font-family: "Times New Roman";
+}
+
+.ql-font-sans-serif {
+  font-family: "sans-serif";
+}
+</style>
diff --git a/seller/src/views/activity/video.js b/seller/src/views/activity/video.js
new file mode 100644
index 0000000..166112f
--- /dev/null
+++ b/seller/src/views/activity/video.js
@@ -0,0 +1,69 @@
+import { Quill } from 'vue-quill-editor';
+
+const BlockEmbed = Quill.import('blots/block/embed');
+const Link = Quill.import('formats/link');
+
+const ATTRIBUTES = ['height', 'width', 'controls', 'src', ];
+
+class VideoBlot extends BlockEmbed {
+  static create(value) {
+    const node = super.create();
+
+    if (typeof value === 'object') {
+      node.setAttribute('src', this.sanitize(value.url));
+      node.setAttribute('width', value.width || '100%');
+      node.setAttribute('height', value.height || 'auto');
+      node.setAttribute('controls', value.controls || 'controls');
+    } else {
+      node.setAttribute('src', this.sanitize(value));
+    }
+
+    return node;
+  }
+
+  static formats(node) {
+    return ATTRIBUTES.reduce((formats, attribute) => {
+      if (node.hasAttribute(attribute)) {
+        formats[attribute] = node.getAttribute(attribute);
+      }
+      return formats;
+    }, {});
+  }
+
+  static sanitize(url) {
+    return Link.sanitize(url);
+  }
+
+  static value(node) {
+    return {
+      url: node.getAttribute('src'),
+      width: node.getAttribute('width'),
+      height: node.getAttribute('height'),
+      controls: node.getAttribute('controls'),
+    };
+  }
+
+  format(name, value) {
+    if (ATTRIBUTES.includes(name)) {
+      if (value) {
+        this.domNode.setAttribute(name, value);
+      } else {
+        this.domNode.removeAttribute(name);
+      }
+    } else {
+      super.format(name, value);
+    }
+  }
+}
+
+VideoBlot.blotName = 'video';
+VideoBlot.className = 'ql-video';
+VideoBlot.tagName = 'video';
+
+// 娣诲姞涓嶄細琚� sanitize 鐨勬爣璁�
+VideoBlot.sanitize = function(url) {
+  const sanitized = Link.sanitize(url);
+  return sanitized === Link.PROTOCOL_WHITELIST[0] ? 'about:blank' : sanitized;
+};
+
+export default VideoBlot;

--
Gitblit v1.8.0