peng
6 天以前 7f072a3fed7882989b676c6775dd67a88feddc39
manager/src/views/video/VideoList.vue
@@ -115,10 +115,25 @@
              </FormItem>
            </Col>
          </Row>
          <Row>
            <Col span="24" v-show="uploadVideoForm.videoFileKey && !uploadVideoForm.coverUrl">
              <FormItem label="上传封面" prop="coverUrl" :label-width="80">
                <Upload
                  :multiple="true"
                  :before-upload="upLoadImagCover"
                  accept="image/*"
                  action=""
                >
                  <Button icon="ios-cloud-upload-outline">选择封面</Button>
                </Upload>
              </FormItem>
            </Col>
          </Row>
          <Row :gutter="24">
            <Col span="12" v-if="uploadVideoForm.videoFileKey">
              <FormItem :labelWidth="80">
                <Button @click="reloadVideo" type="primary">重新上传视频</Button>
                <Button @click="reloadVideo" type="primary" >重新上传视频</Button>
                <Button type="primary" @click="clearCoverImage" v-show="uploadVideoForm.coverUrl" style="margin-left: 20px">重新上传封面</Button>
              </FormItem>
            </Col>
          </Row>
@@ -134,9 +149,9 @@
                        <Icon type="ios-trash-outline" @click.native="handleRemove(item)"></Icon>
                      </div>
                    </template>
                    <!--                    <template v-else>-->
                    <!--                      <Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>-->
                    <!--                    </template>-->
                    <!--                      <template v-else>-->
                    <!--                        <Progress v-if="item.showProgress" :percent="item.percentage" hide-info></Progress>-->
                    <!--                      </template>-->
                  </div>
                  <Upload
                    ref="upload"
@@ -212,14 +227,16 @@
                          align-items: center;justify-content: flex-start;border: 1px solid gray;margin-top: 10px;
                          padding: 10px;border-radius: 20px">
                    <div>
                      <img :src="endpoint+'/'+item.thumbnail" style="width: 80px;height: 80px">
                      <img :src="item.thumbnail.includes('http') ? item.thumbnail : endpoint + '/' + item.thumbnail"
                           style="width: 80px;height: 80px">
                    </div>
                    <div style="display: flex;flex-direction: column;margin-left: 20px">
                      <div style="font-size: 1.5em;font-weight: bold">{{ item.goodsName }}</div>
                      <div style="color: #ff6f6f;display: flex;align-content: center;justify-content: flex-start">
                        <div> ¥{{ item.price }}</div>
                        <div style="margin-left: 10px">
                          <InputNumber v-model="item.goodsNum" :min="0" :max="99" controls-outside @on-change="changeGoodsNum(item.goodsSkuId,index,item.goodsNum)"
                          <InputNumber v-model="item.goodsNum" :min="0" :max="99" controls-outside
                                       @on-change="changeGoodsNum(item.goodsSkuId,index,item.goodsNum)"
                                       style="vertical-align: center;width: 100px"></InputNumber>
                        </div>
                      </div>
@@ -402,6 +419,9 @@
          <Button type="primary" size="small" style="margin-right: 5px" v-if="row.status === '99'"
                  @click="openAuditing(row)">审核
          </Button>
          <Button type="primary" size="small" style="margin-right: 5px"
                  @click="editVideo(row)">编辑
          </Button>
          <Button type="error" size="small" style="margin-right: 5px" v-if="row.status === '1'"
                  @click="openVideoDown(row)">下架
          </Button>
@@ -411,8 +431,97 @@
          <Button type="success" size="small" style="margin-right: 5px" v-else-if="row.status === '0'"
                  @click="videoUp(row)">上架
          </Button>
          <Button type="error" size="small" style="margin-right: 5px"
                  @click="openComment(row)">
            查看评论
          </Button>
        </template>
      </Table>
      <Modal
        v-model="showVideoComment"
        title="视频评论"
        width="1000"
        :mask-closable="false">
        <Form :model="commentForm" ref="commentForm">
          <Row type="flex" :gutter="16">
            <Col>
              <FormItem :label-width="70" label="内容:" prop="commentContent">
                <Input style="width: 120px"
                       v-model="commentForm.commentContent" placeholder="请输入内容"
                       @on-clear="commentHandleSearch"
                       @on-change="commentHandleSearch"></Input>
              </FormItem>
            </Col>
            <Col>
              <FormItem :label-width="70" label="用户昵称:" prop="nickName">
                <Input style="width: 120px" v-model="commentForm.nickName" placeholder="请输入内容"
                       @on-clear="commentHandleSearch"
                       @on-change="commentHandleSearch"></Input>
              </FormItem>
            </Col>
            <Col>
              <FormItem :label-width="70" label="开始时间:" prop="startTime">
                <DatePicker
                  :v-model="commentForm.startTime"
                  type="datetime"
                  placeholder="选择开始时间"
                  style="width: 120px"
                  @on-change="commentHandleSearch($event)"
                  @on-clear="commentHandleSearch"
                ></DatePicker>
              </FormItem>
            </Col>
            <Col>
              <FormItem :label-width="70" label="结束时间:" prop="endTime">
                <DatePicker
                  :v-model="commentForm.endTime"
                  type="datetime"
                  placeholder="选择结束时间"
                  style="width: 120px"
                  @on-change="commentHandleSearch($event)"
                  @on-clear="commentHandleSearch"
                ></DatePicker>
              </FormItem>
            </Col>
          </Row>
        </Form>
      <div slot="footer">
        <Button type="text" @click="closeVideoDown">关闭</Button>
        <Button type="primary" @click="videoDown">确认</Button>
      </div>
          <Table
            :loading="commentLoading"
            border
            :columns="commentColumns"
            :data="commentData"
            ref="commentTable"
            sortable="custom"
            >
           <template slot-scope="{ row, index }" slot="action">
              <Button type="error" size="small"
              @click="removeComment(row)">删除</Button>
           </template>
          </Table>
        <Row type="flex" justify="end" class="page-footer">
          <Page
            :current="commentForm.pageNumber"
            :total="commentTotal"
            :page-size="commentForm.pageSize"
            @on-change="commentChangePage"
            @on-page-size-change="commentChangePageSize"
            :page-size-opts="[10, 20, 50]"
            size="small"
            show-total
            show-elevator
            show-sizer
          ></Page>
        </Row>
        <div slot="footer">
        </div>
      </Modal>
      <Modal
        v-model="showGeneralQrCode"
        title="二维码"
@@ -428,7 +537,7 @@
        ></vue-qr>
        <div slot="footer">
          <Button type="text" @click="closeGeneralQrCode">关闭</Button>
<!--          <Button type="primary" @click="generalQrCode">确认</Button>-->
          <!--          <Button type="primary" @click="generalQrCode">确认</Button>-->
        </div>
      </Modal>
      <Row type="flex" justify="end" class="mt_10">
@@ -450,7 +559,19 @@
</template>
<script>
import {getVideos, recommendSet, getVideoById, auditingVideo, up, down, recreateIndex,publish} from "@/api/video";
import {
  getVideos,
  recommendSet,
  getVideoById,
  auditingVideo,
  up,
  down,
  recreateIndex,
  publish,
  updatePublish,
  getCommentPage,
  removeById
} from "@/api/video";
import {getVideoTagList, recommend, videoGoodsEsPage} from "@/api/videoTag";
import {getFilePreview, getSts} from "@/api/file";
import Editor from '@/components/editor/index.vue'
@@ -459,10 +580,16 @@
import {getFileKey} from "@/utils/file";
import vuedraggable from "vuedraggable";
import vueQr from "vue-qr";
import uploadImage from "../../components/editor/upload-image.vue";
export default {
  name: "VideoList",
  components: {vuedraggable, Editor, GoodsExpandRow,"vue-qr": vueQr},
  computed: {
    uploadImage() {
      return uploadImage
    }
  },
  components: {vuedraggable, Editor, GoodsExpandRow, "vue-qr": vueQr},
  watch: {
    'uploadVideoForm.videoContentType'(newValue, oldValue) {
      if (newValue === 'video') {
@@ -478,6 +605,7 @@
      }
    },
    chooseTag(newValue, oldValue) {
      console.log('触发新值变化',newValue);
      this.uploadVideoForm.tags = newValue.map(item => {
        const findTag = this.videoTagList.find(tagItem => {
          return tagItem.tagName === item
@@ -499,10 +627,54 @@
  },
  data() {
    return {
      commentTotal:0,
      commentForm:{
        commentContent:'',
        videoId:'',
        nikeName:'',
        startTime:'',
        endTime:'',
        pageNumber:1,
        pageSize:10
      },
      commentColumns:[
        // {
        //   type: 'selection',
        //   width: 60,
        //   align: 'center'
        // },
        {
          title: "用户名",
          key: "userNickname",
          minWidth: 240,
          tooltip: true,
        },{
          title: "内容",
          key: "commentContent",
          minWidth: 240,
          tooltip: true,
        },{
          title: "评论时间",
          key: "createTime",
          minWidth: 240,
          tooltip: true,
        },{
          title: "操作",
          key: "action",
          slot: "action",
          align: "center",
          width: 200,
          fixed: "right"
        }
      ],
      commentData:[],
      showVideoComment:false,
      commentLoading:false,
      // https://myk.9village.cn/scanpage/recommend?shareType=videoRecommend&videoId=1948284811844190209
      baseQRCodeUrl: this.QRcodeBaseUrl+ '/scanpage/recommend',
      QRCodeUrl:'',
      showGeneralQrCode:false,
      baseQRCodeUrl: this.QRcodeBaseUrl + '/scanpage/recommend',
      QRCodeUrl: '',
      showGeneralQrCode: false,
      endpoint: '',
      searchGoods: '',
      videoTagList: [],
@@ -516,6 +688,8 @@
      videoProgress: 0,
      upLoadVideoShow: false,
      uploadVideoForm: {
        coverUrl:null,
        showCoverUrl:null,
        id: '',
        title: '',
        cover: "",
@@ -689,6 +863,7 @@
          slot: "action",
          align: "center",
          width: 200,
          fixed: "right"
        },
      ],
      goodsData: [],
@@ -704,19 +879,158 @@
    this.getTags('')
  },
  methods: {
    closeGeneralQrCode(){
    commentChangePage(page) {
      this.commentForm.pageNumber = page
      this.commentPage()
    },
    // 改变报名人员每页条数
    commentChangePageSize(pageSize) {
      this.commentForm.pageNumber = 1
      this.commentForm.pageSize = pageSize
      this.commentPage()
    },
    commentPage(){
      this.commentLoading = true;
      getCommentPage(this.commentForm).then(res =>{
        this.commentLoading = false;
        if (res.code === 200){
          this.commentData = res.data;
          this.commentData.forEach(item =>{
            item.createTime = this.formatDate(item.createTime);
          })
        }
      })
    },
    commentHandleSearch(){
      this.commentPage();
    },
    removeComment(row){
      removeById(row.id).then(res=>{
        if (res.code === 200){
          this.$Message.success(res.msg);
        }else {
          this.$Message.error(res.msg);
        }
        this.commentPage();
      })
    },
    formatDate(date, format = 'yyyy-MM-dd HH:mm:ss') {
      if (!date) return '';
      const d = new Date(date);
      if (isNaN(d.getTime())) return date; // 无效日期直接返回原值
      const padZero = (num) => (num < 10 ? `0${num}` : num.toString());
      return format
        .replace('yyyy', d.getFullYear())
        .replace('MM', padZero(d.getMonth() + 1))
        .replace('dd', padZero(d.getDate()))
        .replace('HH', padZero(d.getHours()))
        .replace('mm', padZero(d.getMinutes()))
        .replace('ss', padZero(d.getSeconds()));
    },
    commentShowSelect(){
      // this.selectList = selection.map(item => item.id)
      // this.selectCount = selection.length
    },
    openComment(row){
      console.log(row)
      this.commentForm.videoId = row.id;
      this.showVideoComment = true;
      this.commentPage();
    },
    async editVideo(row) {
      // this.uploadVideoForm = {};
      // this.uploadVideoForm = row;
      // this.showUploadVideoShow = true;
      this.videoTagList = []
     await recommend({
        searchType: "HOT"
      }).then(res => {
        this.videoTagList = res.data;
      })
      this.upLoadVideoShow = true;
      console.log('--------------------->',row.tagList)
      if (row.tagList){
        this.chooseTag = row.tagList.map(item => {
          return item.tagName
        })
      }
      console.log('选中列表---》',row.goodsList)
      if (row.goodsList){
        row.goodsList.forEach(item => {
          item.goodsSkuId = item.id
        })
      }
      this.uploadVideoForm = {
        id: '',
        title: '',
        cover: "",
        videoFileKey: "",
        videoDuration: 0,
        videoFit: "cover",
        videoContentType: 'video',
        videoImgs: [],
        showListImages: [],
        tags: [],
        fileInfo: {},
        goodsList: []
      }
      if (row.tagList){
        // 遍历已选择的标签
        row.tagList.forEach(tag => {
          // 检查标签是否已存在于videoTagList中
          const exists = this.videoTagList.some(item => item.tagName === tag.tagName);
          // 如果不存在,则添加到选项列表
          if (!exists) {
            this.videoTagList.push({
              id: tag.id, // 生成临时ID
              tagName: tag.tagName
            });
          }
        });
      }
      this.uploadVideoForm = row
      console.log("打印值",this.uploadVideoForm)
      this.uploadVideoForm.fileInfo= {};
      this.uploadVideoForm.videoImgs = JSON.parse(this.uploadVideoForm.videoImgs)
      const sts = await getSts();
      if (this.uploadVideoForm.videoContentType === 'video') {
        this.uploadVideoForm.showVideoUrl = sts.data.endpoint + '/' + this.uploadVideoForm.videoFileKey
        if (this.uploadVideoForm.coverUrl !== '' && this.uploadVideoForm.coverUrl != null) {
          this.uploadVideoForm.showCoverUrl =  this.uploadVideoForm.coverUrl
        }
      } else if (this.uploadVideoForm.videoContentType === 'img') {
        this.uploadVideoForm.showListImages = this.uploadVideoForm.videoImgs.map(item => {
          return sts.data.endpoint + '/' + item
        })
      }
      console.log("处理过后",this.uploadVideoForm)
      this.searchGoodsList();
    },
    closeGeneralQrCode() {
      this.showGeneralQrCode = false;
      this.QRCodeUrl = '';
    },
    generalQrCode(row){
    generalQrCode(row) {
      this.showGeneralQrCode = true
      console.log('-------------------->',row);
      this.QRCodeUrl = this.baseQRCodeUrl + '?shareType=videoRecommend' + '&videoId='+ row.id;
      console.log('-------------------->', row);
      this.QRCodeUrl = this.baseQRCodeUrl + '?shareType=videoRecommend' + '&videoId=' + row.id;
      console.log(this.QRCodeUrl)
    },
    //todo 保留后续可能会使用
    changeGoodsNum(id,index,goodsNum){
      console.log('-------------------->',id,index,goodsNum)
    changeGoodsNum(id, index, goodsNum) {
      console.log('-------------------->', id, index, goodsNum)
    },
    chooseGoods(id) {
      const goods = this.goodsData.find(item => {
@@ -753,38 +1067,59 @@
      this.upLoadVideoShow = false;
    },
    submitVideoUpload() {
      this.uploadVideoForm.goodsList =  this.uploadVideoForm.goodsList.filter(item => {
        return item.goodsNum >0;
      console.log(this.uploadVideoForm.coverUrl)
      if (this.uploadVideoForm.coverUrl === null || this.uploadVideoForm.coverUrl === undefined) {
        this.$Message.error('标题不能为空');
        return;
      }
      this.uploadVideoForm.goodsList = this.uploadVideoForm.goodsList.filter(item => {
        return item.goodsNum > 0;
      })
      if (!this.uploadVideoForm.title) {
        this.$Message.error('标题不能为空');
        return;
      }
      //表单校验
      if (this.uploadVideoForm.videoContentType==='video') {
        if (!this.uploadVideoForm.videoFileKey){
      if (this.uploadVideoForm.videoContentType === 'video') {
        if (!this.uploadVideoForm.videoFileKey) {
          this.$Message.error('视频不能为空');
          return;
        }
      }
      if (this.uploadVideoForm.videoContentType==='img') {
        if (this.uploadVideoForm.videoImgs<1){
      if (this.uploadVideoForm.videoContentType === 'img') {
        if (this.uploadVideoForm.videoImgs < 1) {
          this.$Message.error('图片不能为空');
          return;
        }
      }
      publish(this.uploadVideoForm).then(response => {
        if (response.code == 200) {
          this.$Message.success("视频发布成功");
          this.upLoadVideoShow = false;
          this.getDataList();
        }
      }).then(error=>{
        this.$Message.success(error);
      })
      console.log('提交表单--------------->', this.uploadVideoForm)
      if (this.uploadVideoForm.id) {
        updatePublish(this.uploadVideoForm).then(response => {
          if (response.code == 200) {
            this.$Message.success("视频修改成功");
            this.upLoadVideoShow = false;
            this.getDataList();
          }
        }).then(error => {
          this.$Message.success(error);
        })
      } else {
        publish(this.uploadVideoForm).then(response => {
          if (response.code == 200) {
            this.$Message.success("视频发布成功");
            this.upLoadVideoShow = false;
            this.getDataList();
          }
        }).then(error => {
          this.$Message.success(error);
        })
      }
    },
    //todo 后续可能会使用预留
    createVideoTag(e) {
      console.log('------------>',e)
    },
    handleRemove(file) {
      const fileList2 = this.uploadVideoForm.showListImages;
@@ -795,13 +1130,62 @@
      this.imgName = name;
      this.visible = true;
    },
    async upLoadImagCover(file) {
      try {
        // 获取文件上传临时密钥
        const sts = await getSts();
        const cos = new COS({
          getAuthorization: async function (options, callback) {
            callback({
              TmpSecretId: sts.data.tmpSecretId,
              TmpSecretKey: sts.data.tmpSecretKey,
              SecurityToken: sts.data.sessionToken,
              // 建议返回服务器时间作为签名的开始时间,避免客户端本地时间偏差过大导致签名错误
              StartTime: sts.data.stsStartTime, // 时间戳,单位秒,如:1580000000
              ExpiredTime: sts.data.stsEndTime,// 时间戳,单位秒,如:1580000000
              ScopeLimit: true, // 细粒度控制权限需要设为 true,会限制密钥只在相同请求时重复使用
            });
          }
        })
        const fileKey = getFileKey(file.name)
        const upData = await cos.uploadFile({
          Bucket: sts.data.bucket,
          Region: sts.data.region,
          Key: fileKey,
          Body: file, // 要上传的文件对象。cover
          SliceSize: 1024 * 1024 * 5,
          onProgress: function (progressData) {
            console.log('上传进度:', progressData);
          },
        });
        this.$set(this.uploadVideoForm, 'coverUrl', fileKey);
        this.$set(this.uploadVideoForm, 'showCoverUrl', `${sts.data.endpoint}/${fileKey}`);
        this.uploadVideoForm.cover = fileKey;
        if (this.$refs.videoInfo) {
          this.$refs.videoInfo.poster = this.uploadVideoForm.showCoverUrl;
          this.$refs.videoInfo.load(); // 重新加载视频
        }
        console.log(this.uploadVideoForm)
      } catch (e) {
        console.log("上传失败", upData)
      } finally {
      }
      return false;
    },
    clearCoverImage(){
      this.$set(this.uploadVideoForm, 'coverUrl', '');
      this.$set(this.uploadVideoForm, 'showCoverUrl', '');
      this.$set(this.uploadVideoForm, 'temp', new Date().getTime());
    },
    async upLoadImg(file) {
      if (this.uploadVideoForm.videoImgs >= 5) {
        this.$Message.error("图片上传不能超过5个");
        return;
      }
      try {
        // this.upLoadVideoLoading = true;
        // 获取文件上传临时密钥
        const sts = await getSts();
        const cos = new COS({
@@ -838,7 +1222,6 @@
        console.log("上传失败", upData)
        return false;
      } finally {
        // this.upLoadVideoLoading = false;
      }
      return false;
@@ -903,7 +1286,7 @@
          this.uploadVideoForm.showVideoUrl = sts.data.endpoint + "/" + fileKey;
        })
        console.log("上传成功", upData)
        const duration = this.$refs.healthVideoInfo.duration;
        const duration = this.$refs.videoInfo.duration;
        console.log('-测试获取时间信息---------------->', duration);
      } catch (e) {
        console.log("上传失败", upData)
@@ -1109,7 +1492,7 @@
    // 获取列表数据
    getGoodsDataList() {
      let search = this.searchGoodsForm;
      console.log('-------------------------->',this.searchGoodsForm)
      console.log('-------------------------->', this.searchGoodsForm)
      if (search.pageNumber > 0) {
        search.pageNumber = search.pageNumber - 1;
      }
@@ -1166,7 +1549,7 @@
    },
    // 分页 改变页码
    goodsChangePage(v) {
      console.log('-------------------------->分页',v);
      console.log('-------------------------->分页', v);
      this.searchGoodsForm.pageNumber = v;
      this.getGoodsDataList();
    },