Forráskód Böngészése

卓美马甲功能

yuhongqi 2 napja
szülő
commit
d01a4efba0

+ 39 - 0
src/api/life/vest.js

@@ -0,0 +1,39 @@
+import request from '@/utils/request'
+
+export function listLifeVest(query) {
+  return request({
+    url: '/life/vest/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getLifeVest(id) {
+  return request({
+    url: '/life/vest/' + id,
+    method: 'get'
+  })
+}
+
+export function addLifeVest(data) {
+  return request({
+    url: '/life/vest',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateLifeVest(data) {
+  return request({
+    url: '/life/vest',
+    method: 'put',
+    data: data
+  })
+}
+
+export function delLifeVest(id) {
+  return request({
+    url: '/life/vest/' + id,
+    method: 'delete'
+  })
+}

+ 55 - 0
src/api/life/video.js

@@ -0,0 +1,55 @@
+import request from '@/utils/request'
+
+export function listLifeVideo(query) {
+  return request({
+    url: '/life/video/list',
+    method: 'get',
+    params: query
+  })
+}
+
+export function getLifeVideo(videoId) {
+  return request({
+    url: '/life/video/' + videoId,
+    method: 'get'
+  })
+}
+
+export function addLifeVideo(data) {
+  return request({
+    url: '/life/video',
+    method: 'post',
+    data: data
+  })
+}
+
+export function updateLifeVideo(data) {
+  return request({
+    url: '/life/video',
+    method: 'put',
+    data: data
+  })
+}
+
+export function delLifeVideo(videoId) {
+  return request({
+    url: '/life/video/' + videoId,
+    method: 'delete'
+  })
+}
+
+export function shelfLifeVideo(data) {
+  return request({
+    url: '/life/video/shelf',
+    method: 'put',
+    data: data
+  })
+}
+
+export function searchLifeVideoProduct(query) {
+  return request({
+    url: '/life/video/product/search',
+    method: 'get',
+    params: query
+  })
+}

+ 13 - 0
src/views/hisStore/components/productOrder.vue

@@ -163,6 +163,11 @@
                   {{order.virtualPhone }}
                 </span>
             </el-descriptions-item>
+            <el-descriptions-item label="发货人手机号"  >
+                <span v-if="order != null ">
+                  {{order.senderPhone }}
+                </span>
+            </el-descriptions-item>
             <el-descriptions-item label="收货地址"  >
               <el-popover
                 v-if="order!=null"
@@ -556,6 +561,9 @@
         <el-form-item label="物流单号" prop="deliveryId"  >
           <el-input v-model="editDyForm.deliveryId" placeholder="请输入物流单号" />
         </el-form-item>
+        <el-form-item label="发货人手机号" prop="senderPhone"  >
+          <el-input v-model="editDyForm.senderPhone" placeholder="请输入发货人手机号(物流订阅/查询用)" maxlength="20" />
+        </el-form-item>
         <el-form-item label="虚拟手机号" prop="virtualPhone"  >
           <el-input v-model="editDyForm.virtualPhone" placeholder="请输入虚拟手机号" />
         </el-form-item>
@@ -1022,6 +1030,7 @@ export default {
       editDyForm:{
         deliverySn:null,
         deliveryId:null,
+        senderPhone: null,
         virtualPhone: null,
       },
       editForm:{
@@ -1559,6 +1568,9 @@ export default {
           if (!this.editDyForm.virtualPhone) {
             this.editDyForm.virtualPhone = '';//如果为null就设置为空字符串
           }
+          if (this.editDyForm.senderPhone == null) {
+            this.editDyForm.senderPhone = '';
+          }
           updateDeliveryId(this.editDyForm).then(response => {
             if (response.code === 200) {
               this.msgSuccess("操作成功");
@@ -1685,6 +1697,7 @@ export default {
       this.editDyForm.id = this.order.id;
       this.editDyForm.deliveryId = this.order.deliveryId;
       this.editDyForm.deliverySn = this.order.deliverySn;
+      this.editDyForm.senderPhone = this.order.senderPhone;
       this.editDyForm.virtualPhone = this.order.virtualPhone;
     },
     getOrder(orderId){

+ 172 - 0
src/views/life/vest/index.vue

@@ -0,0 +1,172 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="80px">
+      <el-form-item label="关键字" prop="keyword">
+        <el-input v-model="queryParams.keyword" placeholder="昵称/ID" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['life:vest:add']">新增</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="vestList">
+      <el-table-column label="马甲号ID" align="center" prop="id" width="100"/>
+      <el-table-column label="头像" align="center" width="80">
+        <template slot-scope="scope">
+          <el-image v-if="scope.row.avatar" :src="scope.row.avatar" style="width:40px;height:40px;border-radius:50%" fit="cover"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="昵称" align="center" prop="nickName"/>
+      <el-table-column label="简介" align="center" prop="intro" show-overflow-tooltip/>
+      <el-table-column label="状态" align="center" prop="status" width="80">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.status === 1" type="success">启用</el-tag>
+          <el-tag v-else type="info">禁用</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="220" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['life:vest:edit']">编辑</el-button>
+          <el-button size="mini" type="text" icon="el-icon-video-camera" @click="goVideo(scope.row)" v-hasPermi="['life:video:list']">内容配置</el-button>
+          <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" v-hasPermi="['life:vest:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
+
+    <el-dialog :title="title" :visible.sync="open" width="520px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="90px">
+        <el-form-item label="昵称" prop="nickName">
+          <el-input v-model="form.nickName" placeholder="2-10个字" maxlength="10"/>
+        </el-form-item>
+        <el-form-item label="头像" prop="avatar">
+          <image-upload v-model="form.avatar" :limit="1"/>
+        </el-form-item>
+        <el-form-item label="简介" prop="intro">
+          <el-input v-model="form.intro" type="textarea" :rows="3" placeholder="选填"/>
+        </el-form-item>
+        <el-form-item label="状态" prop="status">
+          <el-radio-group v-model="form.status">
+            <el-radio :label="1">启用</el-radio>
+            <el-radio :label="0">禁用</el-radio>
+          </el-radio-group>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listLifeVest, getLifeVest, addLifeVest, updateLifeVest, delLifeVest } from '@/api/life/vest'
+
+export default {
+  name: 'LifeVest',
+  data() {
+    return {
+      loading: true,
+      showSearch: true,
+      total: 0,
+      vestList: [],
+      title: '',
+      open: false,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        keyword: null
+      },
+      form: {},
+      rules: {
+        nickName: [
+          { required: true, message: '昵称不能为空', trigger: 'blur' },
+          { min: 2, max: 10, message: '长度需为2-10字', trigger: 'blur' }
+        ],
+        avatar: [{ required: true, message: '头像不能为空', trigger: 'change' }],
+        status: [{ required: true, message: '请选择状态', trigger: 'change' }]
+      }
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    getList() {
+      this.loading = true
+      listLifeVest(this.queryParams).then(res => {
+        this.vestList = res.rows
+        this.total = res.total
+        this.loading = false
+      })
+    },
+    cancel() {
+      this.open = false
+      this.reset()
+    },
+    reset() {
+      this.form = {
+        id: null,
+        nickName: null,
+        avatar: null,
+        intro: null,
+        status: 1
+      }
+      this.resetForm('form')
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.handleQuery()
+    },
+    handleAdd() {
+      this.reset()
+      this.open = true
+      this.title = '新增马甲号'
+    },
+    handleUpdate(row) {
+      this.reset()
+      getLifeVest(row.id).then(res => {
+        this.form = res.data
+        this.open = true
+        this.title = '编辑马甲号'
+      })
+    },
+    submitForm() {
+      this.$refs['form'].validate(valid => {
+        if (!valid) return
+        const req = this.form.id != null ? updateLifeVest(this.form) : addLifeVest(this.form)
+        req.then(() => {
+          this.msgSuccess('操作成功')
+          this.open = false
+          this.getList()
+        })
+      })
+    },
+    handleDelete(row) {
+      this.$confirm('确认删除马甲号「' + row.nickName + '」吗?', '警告', { type: 'warning' }).then(() => {
+        return delLifeVest(row.id)
+      }).then(() => {
+        this.getList()
+        this.msgSuccess('删除成功')
+      }).catch(() => {})
+    },
+    goVideo(row) {
+      this.$router.push({ path: '/live/life/video', query: { vestId: row.id } })
+    }
+  }
+}
+</script>

+ 327 - 0
src/views/life/video/index.vue

@@ -0,0 +1,327 @@
+<template>
+  <div class="app-container">
+    <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="90px">
+      <el-form-item label="马甲号" prop="vestId">
+        <el-select v-model="queryParams.vestId" filterable clearable placeholder="全部马甲" size="small" style="width:180px">
+          <el-option v-for="v in vestOptions" :key="v.id" :label="v.nickName + '(' + v.id + ')'" :value="v.id"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item label="关键字" prop="keyword">
+        <el-input v-model="queryParams.keyword" placeholder="标题/ID/文件名" clearable size="small" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="上架" prop="isShow">
+        <el-select v-model="queryParams.isShow" clearable placeholder="全部" size="small" style="width:100px">
+          <el-option label="上架" :value="1"/>
+          <el-option label="下架" :value="0"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-row :gutter="10" class="mb8">
+      <el-col :span="1.5">
+        <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" v-hasPermi="['life:video:add']">新增</el-button>
+      </el-col>
+      <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+    </el-row>
+
+    <el-table border v-loading="loading" :data="videoList">
+      <el-table-column label="视频ID" align="center" prop="videoId" width="90"/>
+      <el-table-column label="封面" align="center" width="80">
+        <template slot-scope="scope">
+          <el-image v-if="scope.row.coverUrl" :src="scope.row.coverUrl" style="width:50px;height:50px" fit="cover"/>
+        </template>
+      </el-table-column>
+      <el-table-column label="标题" align="center" prop="title" show-overflow-tooltip/>
+      <el-table-column label="文件名" align="center" prop="fileName" show-overflow-tooltip/>
+      <el-table-column label="马甲ID" align="center" prop="vestId" width="80"/>
+      <el-table-column label="时长(秒)" align="center" prop="duration" width="90"/>
+      <el-table-column label="上架" align="center" width="80">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.isShow === 1" type="success">是</el-tag>
+          <el-tag v-else type="info">否</el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="主推" align="center" width="80">
+        <template slot-scope="scope">
+          <el-tag v-if="scope.row.isHot === 1" type="warning">是</el-tag>
+          <span v-else>否</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="播放/赞/藏/享" align="center" width="140">
+        <template slot-scope="scope">
+          {{ scope.row.views || 0 }}/{{ scope.row.likes || 0 }}/{{ scope.row.favoriteNum || 0 }}/{{ scope.row.shareNum || 0 }}
+        </template>
+      </el-table-column>
+      <el-table-column label="操作" align="center" width="200" class-name="small-padding fixed-width">
+        <template slot-scope="scope">
+          <el-button size="mini" type="text" @click="handleUpdate(scope.row)" v-hasPermi="['life:video:edit']">修改</el-button>
+          <el-button size="mini" type="text" @click="handleShelf(scope.row)" v-hasPermi="['life:video:edit']">
+            {{ scope.row.isShow === 1 ? '下架' : '上架' }}
+          </el-button>
+          <el-button size="mini" type="text" @click="handleDelete(scope.row)" v-hasPermi="['life:video:remove']">删除</el-button>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList"/>
+
+    <el-dialog :title="title" :visible.sync="open" width="720px" append-to-body>
+      <el-form ref="form" :model="form" :rules="rules" label-width="110px">
+        <el-form-item label="马甲号" prop="vestId">
+          <el-select v-model="form.vestId" filterable placeholder="请选择马甲号" style="width:100%">
+            <el-option v-for="v in vestOptions" :key="v.id" :label="v.nickName + '(' + v.id + ')'" :value="v.id"/>
+          </el-select>
+        </el-form-item>
+        <el-form-item label="视频标题" prop="title">
+          <el-input v-model="form.title" maxlength="20" show-word-limit placeholder="不超过20字"/>
+        </el-form-item>
+        <el-form-item label="文件名称" prop="fileName">
+          <el-input v-model="form.fileName" placeholder="上传文件名或标识"/>
+        </el-form-item>
+        <el-form-item label="封面" prop="coverUrl">
+          <image-upload v-model="form.coverUrl" :limit="1"/>
+        </el-form-item>
+        <el-form-item label="视频地址" prop="videoUrl">
+          <el-input v-model="form.videoUrl" placeholder="mp4 地址(素材库上传后粘贴)"/>
+        </el-form-item>
+        <el-form-item label="时长(秒)" prop="duration">
+          <el-input-number v-model="form.duration" :min="0" :controls="false"/>
+        </el-form-item>
+        <el-form-item label="是否上架" prop="isShow">
+          <el-radio-group v-model="form.isShow">
+            <el-radio :label="1">上架</el-radio>
+            <el-radio :label="0">下架</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="今日主推" prop="isHot">
+          <el-radio-group v-model="form.isHot">
+            <el-radio :label="1">是</el-radio>
+            <el-radio :label="0">否</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="关联商品">
+          <el-button type="primary" size="mini" @click="openProductDialog">选择商品</el-button>
+          <el-table :data="selectedProducts" border size="mini" style="margin-top:8px">
+            <el-table-column label="商品ID" prop="productId" width="90"/>
+            <el-table-column label="名称" prop="productName" show-overflow-tooltip/>
+            <el-table-column label="价格" prop="price" width="90"/>
+            <el-table-column label="库存" prop="stock" width="80"/>
+            <el-table-column label="操作" width="80">
+              <template slot-scope="scope">
+                <el-button type="text" size="mini" @click="removeProduct(scope.$index)">删除</el-button>
+              </template>
+            </el-table-column>
+          </el-table>
+        </el-form-item>
+      </el-form>
+      <div slot="footer" class="dialog-footer">
+        <el-button type="primary" @click="submitForm">确 定</el-button>
+        <el-button @click="cancel">取 消</el-button>
+      </div>
+    </el-dialog>
+
+    <el-dialog title="选择商品" :visible.sync="productOpen" width="780px" append-to-body>
+      <el-form :inline="true" size="small">
+        <el-form-item label="商品名称">
+          <el-input v-model="productQuery.productName" clearable @keyup.enter.native="searchProduct"/>
+        </el-form-item>
+        <el-form-item>
+          <el-button type="primary" size="mini" @click="searchProduct">搜索</el-button>
+        </el-form-item>
+      </el-form>
+      <el-table :data="productList" border v-loading="productLoading" max-height="400">
+        <el-table-column label="ID" prop="productId" width="80"/>
+        <el-table-column label="图片" width="70">
+          <template slot-scope="scope">
+            <el-image v-if="scope.row.image" :src="scope.row.image" style="width:40px;height:40px" fit="cover"/>
+          </template>
+        </el-table-column>
+        <el-table-column label="名称" prop="productName" show-overflow-tooltip/>
+        <el-table-column label="价格" prop="price" width="90"/>
+        <el-table-column label="库存" prop="stock" width="80"/>
+        <el-table-column label="操作" width="100">
+          <template slot-scope="scope">
+            <el-button type="text" size="mini" :disabled="isSelected(scope.row.productId)" @click="pickProduct(scope.row)">
+              {{ isSelected(scope.row.productId) ? '已选' : '选择' }}
+            </el-button>
+          </template>
+        </el-table-column>
+      </el-table>
+      <pagination v-show="productTotal>0" :total="productTotal" :page.sync="productQuery.pageNum" :limit.sync="productQuery.pageSize" @pagination="searchProduct"/>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { listLifeVest } from '@/api/life/vest'
+import { listLifeVideo, getLifeVideo, addLifeVideo, updateLifeVideo, delLifeVideo, shelfLifeVideo, searchLifeVideoProduct } from '@/api/life/video'
+
+export default {
+  name: 'LifeVideo',
+  data() {
+    return {
+      loading: true,
+      showSearch: true,
+      total: 0,
+      videoList: [],
+      vestOptions: [],
+      title: '',
+      open: false,
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        vestId: null,
+        keyword: null,
+        isShow: null
+      },
+      form: {},
+      rules: {
+        vestId: [{ required: true, message: '请选择马甲号', trigger: 'change' }],
+        title: [{ required: true, message: '标题不能为空', trigger: 'blur' }],
+        coverUrl: [{ required: true, message: '封面不能为空', trigger: 'change' }],
+        videoUrl: [{ required: true, message: '视频地址不能为空', trigger: 'blur' }],
+        isShow: [{ required: true, message: '请选择是否上架', trigger: 'change' }]
+      },
+      selectedProducts: [],
+      productOpen: false,
+      productLoading: false,
+      productList: [],
+      productTotal: 0,
+      productQuery: {
+        pageNum: 1,
+        pageSize: 10,
+        productName: null
+      }
+    }
+  },
+  created() {
+    if (this.$route.query.vestId) {
+      this.queryParams.vestId = Number(this.$route.query.vestId)
+    }
+    this.loadVests()
+    this.getList()
+  },
+  methods: {
+    loadVests() {
+      listLifeVest({ pageNum: 1, pageSize: 500 }).then(res => {
+        this.vestOptions = res.rows || []
+      })
+    },
+    getList() {
+      this.loading = true
+      listLifeVideo(this.queryParams).then(res => {
+        this.videoList = res.rows
+        this.total = res.total
+        this.loading = false
+      })
+    },
+    cancel() {
+      this.open = false
+      this.reset()
+    },
+    reset() {
+      this.form = {
+        videoId: null,
+        vestId: this.queryParams.vestId || null,
+        title: null,
+        fileName: null,
+        coverUrl: null,
+        videoUrl: null,
+        duration: 0,
+        isShow: 1,
+        isHot: 0,
+        productIds: []
+      }
+      this.selectedProducts = []
+      this.resetForm('form')
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.getList()
+    },
+    resetQuery() {
+      this.resetForm('queryForm')
+      this.queryParams.vestId = null
+      this.handleQuery()
+    },
+    handleAdd() {
+      this.reset()
+      this.open = true
+      this.title = '新增生活号视频'
+    },
+    handleUpdate(row) {
+      this.reset()
+      getLifeVideo(row.videoId).then(res => {
+        this.form = Object.assign({}, res.data)
+        const ids = res.data.productIds || []
+        this.form.productIds = ids
+        this.selectedProducts = ids.map(id => ({ productId: id, productName: '商品#' + id, price: '-', stock: '-' }))
+        // 回填商品详情
+        if (ids.length) {
+          searchLifeVideoProduct({ pageNum: 1, pageSize: 100 }).then(p => {
+            const map = {}
+            ;(p.rows || []).forEach(item => { map[item.productId] = item })
+            this.selectedProducts = ids.map(id => map[id] || { productId: id, productName: '商品#' + id })
+          })
+        }
+        this.open = true
+        this.title = '修改生活号视频'
+      })
+    },
+    submitForm() {
+      this.$refs['form'].validate(valid => {
+        if (!valid) return
+        this.form.productIds = this.selectedProducts.map(p => p.productId)
+        const req = this.form.videoId != null ? updateLifeVideo(this.form) : addLifeVideo(this.form)
+        req.then(() => {
+          this.msgSuccess('操作成功')
+          this.open = false
+          this.getList()
+        })
+      })
+    },
+    handleShelf(row) {
+      const next = row.isShow === 1 ? 0 : 1
+      shelfLifeVideo({ videoId: row.videoId, isShow: next }).then(() => {
+        this.msgSuccess('操作成功')
+        this.getList()
+      })
+    },
+    handleDelete(row) {
+      this.$confirm('删除后不可恢复,确认删除该视频?', '警告', { type: 'warning' }).then(() => {
+        return delLifeVideo(row.videoId)
+      }).then(() => {
+        this.getList()
+        this.msgSuccess('删除成功')
+      }).catch(() => {})
+    },
+    openProductDialog() {
+      this.productOpen = true
+      this.searchProduct()
+    },
+    searchProduct() {
+      this.productLoading = true
+      searchLifeVideoProduct(this.productQuery).then(res => {
+        this.productList = res.rows || []
+        this.productTotal = res.total || 0
+        this.productLoading = false
+      }).catch(() => { this.productLoading = false })
+    },
+    isSelected(productId) {
+      return this.selectedProducts.some(p => p.productId === productId)
+    },
+    pickProduct(row) {
+      if (!this.isSelected(row.productId)) {
+        this.selectedProducts.push(row)
+      }
+    },
+    removeProduct(index) {
+      this.selectedProducts.splice(index, 1)
+    }
+  }
+}
+</script>

+ 32 - 0
src/views/live/live/index.vue

@@ -546,6 +546,23 @@
             <el-radio :label="2">下架</el-radio>
           </el-radio-group>
         </el-form-item>
+        <el-form-item label="可见范围" prop="visibleScope">
+          <el-radio-group v-model="form.visibleScope">
+            <el-radio :label="0">私域直播</el-radio>
+            <el-radio :label="1">公域直播</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="直播马甲号" prop="vestId">
+          <el-select v-model="form.vestId" filterable clearable placeholder="请选择马甲号" style="width:100%">
+            <el-option
+              v-for="item in lifeVestOptions"
+              :key="item.id"
+              :label="item.nickName + '(' + item.id + ')'"
+              :value="item.id"
+            />
+          </el-select>
+          <div style="color:#909399;font-size:12px;line-height:1.4;margin-top:4px">公域直播必须绑定马甲号;私域可不选</div>
+        </el-form-item>
         <el-form-item label="直播标签配置" prop="liveTagList">
           <el-table
             :data="form.liveTagList"
@@ -784,6 +801,7 @@ import {
 } from "@/api/live/live";
 import { exportLiveMsgComments } from "@/api/live/liveMsg";
 import { listLiveGroupType, addLiveGroupType } from "@/api/live/liveGroupType";
+import { listLifeVest } from "@/api/life/vest";
 import Editor from "@/components/Editor/wang";
 import user from "@/store/modules/user";
 import VideoUpload from "@/components/LiveVideoUpload/single.vue";
@@ -910,6 +928,7 @@ export default {
       defaultImg: "https://via.placeholder.com/400x400?text=二维码加载失败", // 占位图
       comapnyDropList: [],
       markTypeDropList: [],
+      lifeVestOptions: [],
       queryTagParams:{
         pageNum: 1,
         pageSize: 5,
@@ -925,6 +944,7 @@ export default {
     this.getList();
     this.getGroupList();
     this.initCompanyDropList();
+    this.loadLifeVestOptions();
     this.getDicts("live_mark_type").then((response) => {
       this.markTypeDropList = response.data;
     });
@@ -1242,6 +1262,8 @@ export default {
         transcodeFileKey: null,
         liveTagList: [],
         liveGroupType: null,
+        visibleScope: 0,
+        vestId: null,
       };
       this.videoUrl = "";
       this.resetForm("form");
@@ -1350,6 +1372,9 @@ export default {
       if (this.form.liveType == 2 && this.videoUrl.length == 0) {
         return this.$message.error("请上传视频");
       }
+      if (this.form.visibleScope === 1 && !this.form.vestId) {
+        return this.$message.error("公域直播必须绑定马甲号");
+      }
       console.log(this.form);
       this.$refs["form"].validate((valid) => {
         if (valid) {
@@ -1370,6 +1395,13 @@ export default {
         }
       });
     },
+    loadLifeVestOptions() {
+      listLifeVest({ pageNum: 1, pageSize: 500 }).then((res) => {
+        this.lifeVestOptions = res.rows || [];
+      }).catch(() => {
+        this.lifeVestOptions = [];
+      });
+    },
     /** 删除按钮操作 */
     handleDelete(row) {
       const liveIds = row.liveId || this.ids;