|
|
@@ -1,38 +1,118 @@
|
|
|
<template>
|
|
|
<div class="app-container">
|
|
|
<div style="padding-bottom: 20px">
|
|
|
- <span v-if="courseName!=null">{{ courseName }}</span>
|
|
|
+ <span v-if="courseName != null">{{ courseName }}</span>
|
|
|
</div>
|
|
|
<el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
|
|
|
<el-form-item label="小节名称" prop="title">
|
|
|
- <el-input
|
|
|
- v-model="queryParams.title"
|
|
|
- placeholder="请输入小节名称"
|
|
|
- clearable
|
|
|
- size="small"
|
|
|
- @keyup.enter.native="handleQuery"
|
|
|
- />
|
|
|
+ <el-input v-model="queryParams.title" placeholder="请输入小节名称" clearable size="small"
|
|
|
+ @keyup.enter.native="handleQuery"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="小节id" prop="videoId">
|
|
|
+ <el-input v-model="queryParams.videoId" 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="['course:userCourseVideo:add']">新增目录
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain :disabled="!ids || ids.length <= 0" size="mini" @click="openUpdates"
|
|
|
+ v-hasPermi="['course:userCourseVideo:updateTime']">修改时间
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain size="mini" @click="openAdds"
|
|
|
+ v-hasPermi="['course:userCourseVideo:batchAdd']">批量添加
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col v-if="usePublicVideoLibrary" :span="1.5">
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ plain
|
|
|
+ size="mini"
|
|
|
+ :disabled="!ids || ids.length <= 0"
|
|
|
+ v-hasPermi="['course:userCourseVideo:edit']"
|
|
|
+ @click="openBatchWatchIntegralDialog"
|
|
|
+ >批量修改</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain size="mini" @click="updateRedPageckeOpen"
|
|
|
+ v-hasPermi="['course:userCourseVideo:updateRed']">修改红包
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="danger" plain icon="el-icon-delete" size="mini" :disabled="multiple" @click="handleDelete"
|
|
|
+ v-hasPermi="['course:userCourseVideo:remove']">删除
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="warning" plain icon="el-icon-edit" size="mini" @click="handleCourseSort"
|
|
|
+ v-hasPermi="['course:userCourseVideo:sort']">修改课节排序
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="el-icon-delete" size="mini" @click="handleSync"
|
|
|
+ v-hasPermi="['course:userCourseVideo:sync']">同步模板数据
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="el-icon-edit" size="mini" :disabled="multiple" @click="handleDown"
|
|
|
+ v-hasPermi="['course:userCourseVideo:batchDown']">批量下架
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="el-icon-edit" size="mini" :disabled="multiple" @click="handleUp"
|
|
|
+ v-hasPermi="['course:userCourseVideo:batchUp']">批量上架</el-button>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="1.5">
|
|
|
+ <el-button type="primary" plain icon="el-icon-edit" size="mini" :disabled="multiple" @click="handleEditCover"
|
|
|
+ v-hasPermi="['course:userCourseVideo:batchEditCover']">批量修改封面图
|
|
|
+ </el-button>
|
|
|
+ </el-col>
|
|
|
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
|
|
+ </el-row>
|
|
|
<el-table border v-loading="loading" :data="userCourseVideoList" @selection-change="handleSelectionChange">
|
|
|
- <el-table-column type="selection" width="55" align="center" />
|
|
|
- <el-table-column label="视频ID" align="center" prop="videoId" />
|
|
|
- <el-table-column label="小节名称" align="center" show-overflow-tooltip prop="title" />
|
|
|
- <el-table-column label="视频文件名称" align="center" show-overflow-tooltip prop="fileName" >
|
|
|
+ <el-table-column type="selection" width="55" align="center"/>
|
|
|
+ <el-table-column label="视频ID" align="center" prop="videoId"/>
|
|
|
+ <el-table-column label="小节名称" align="center" show-overflow-tooltip prop="title"/>
|
|
|
+ <el-table-column label="视频文件名称" align="center" show-overflow-tooltip prop="fileName">
|
|
|
</el-table-column>
|
|
|
<el-table-column label="视频时长" align="center" prop="duration">
|
|
|
- <template slot-scope="{ row }">
|
|
|
- {{ formatDuration(row.duration) }}
|
|
|
- </template>
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ {{ formatDuration(row.duration) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="看课开始时间" align="center" prop="duration">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag v-if="row.viewStartTime">{{ row.viewStartTime }}</el-tag>
|
|
|
+ <el-tag type="danger" v-if="!row.viewStartTime">无</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="看课结束时间" align="center" prop="duration">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag v-if="row.viewEndTime">{{ row.viewEndTime }}</el-tag>
|
|
|
+ <el-tag type="danger" v-if="!row.viewEndTime">无</el-tag>
|
|
|
+ </template>
|
|
|
</el-table-column>
|
|
|
- <el-table-column label="排序" align="center" prop="courseSort" />
|
|
|
- <el-table-column label="上传时间" align="center" prop="createTime" />
|
|
|
- <el-table-column label="默认红包" align="center" prop="redPacketMoney" />
|
|
|
- <el-table-column label="公司红包" align="center" prop="companyRedPacketMoney" />
|
|
|
+ <el-table-column label="领取红包时间" align="center" prop="duration">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ <el-tag v-if="row.lastJoinTime">{{ row.lastJoinTime }}</el-tag>
|
|
|
+ <el-tag type="danger" v-if="!row.lastJoinTime">无</el-tag>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="红包金额" align="center" prop="redPacketMoney"/>
|
|
|
+ <el-table-column label="排序" align="center" prop="courseSort"/>
|
|
|
+ <el-table-column v-if="usePublicVideoLibrary" label="观看时长(分钟)" align="center" width="120" prop="watchDurationMinutes"/>
|
|
|
+ <el-table-column v-if="usePublicVideoLibrary" label="积分奖励" align="center" width="100" prop="integralReward"/>
|
|
|
+ <el-table-column label="上传时间" align="center" prop="createTime"/>
|
|
|
<el-table-column label="是否上架" align="center" prop="isOnPut">
|
|
|
<template slot-scope="{ row }">
|
|
|
<el-tag v-if="row.isOnPut == 0">是</el-tag>
|
|
|
@@ -41,508 +121,1800 @@
|
|
|
</el-table-column>
|
|
|
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
|
|
<template slot-scope="scope">
|
|
|
- <el-button
|
|
|
- size="mini"
|
|
|
- type="text"
|
|
|
- @click="handleDetails(scope.row)"
|
|
|
- >查看</el-button>
|
|
|
-
|
|
|
- <el-button
|
|
|
- size="mini"
|
|
|
- type="text"
|
|
|
- v-hasPermi="['course:userCourseVideo:edit']"
|
|
|
- @click="updateMoney(scope.row)"
|
|
|
- >设置红包金额</el-button>
|
|
|
-
|
|
|
- <el-button size="mini"
|
|
|
- type="text" @click="openTagDialog(scope.row)">
|
|
|
- 绑定看课标签
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
|
|
|
+ v-hasPermi="['course:userCourseVideo:edit']">修改
|
|
|
+ </el-button>
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-edit" @click="handleComment(scope.row)"
|
|
|
+ v-hasPermi="['course:courseWatchComment:list']">查看评论
|
|
|
+ </el-button>
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
|
|
|
+ v-hasPermi="['course:userCourseVideo:remove']">删除
|
|
|
</el-button>
|
|
|
<el-button size="mini"
|
|
|
- type="text" v-if="projectFrom === 'hzyy'" @click="openDialog(scope.row)">
|
|
|
- 复制看课链接
|
|
|
+ type="text" v-if="projectFrom === 'myhk'" @click="openXsyDialog(scope.row)">
|
|
|
+ 复制参数
|
|
|
</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-drawer
|
|
|
- :with-header="false"
|
|
|
- size="75%"
|
|
|
- :visible.sync="open" append-to-body>
|
|
|
- <userCourseVideoDetails ref="userCourseVideoDetails" />
|
|
|
- </el-drawer>
|
|
|
-
|
|
|
- <el-dialog title="设置红包金额" :visible.sync="moneyOpen" width="600px" append-to-body>
|
|
|
- <el-form ref="form" label-width="100px">
|
|
|
- <el-form-item label="红包金额" prop="corpId">
|
|
|
- <el-input-number v-model="redPacketMoneyForm.redPacketMoney" :min="0.1" :max="200" :step="0.1" ></el-input-number>
|
|
|
+ <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="1000px" append-to-body>
|
|
|
+ <el-form ref="form" :model="form" :rules="rules" label-width="110px" v-loading="uploadLoading">
|
|
|
+ <el-form-item label="视频标题" prop="title">
|
|
|
+ <el-input v-model="form.title" placeholder="请输入内容"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="视频描述" prop="description">
|
|
|
+ <el-input v-model="form.description" type="textarea" :rows="2" placeholder="请输入内容"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="课程排序" prop="courseSort">
|
|
|
+ <el-input-number v-model="form.courseSort" :min="1"></el-input-number>
|
|
|
</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="dialogVisible"
|
|
|
- width="400px"
|
|
|
- @close="resetRoomForm"
|
|
|
- append-to-body>
|
|
|
- <el-form :model="roomLinkForm" label-width="120px">
|
|
|
- <!-- 新增下拉框 -->
|
|
|
- <el-form-item label="销售企微选择">
|
|
|
- <el-select
|
|
|
- v-model="roomLinkForm.qwUserId"
|
|
|
- placeholder="请选择销售企微"
|
|
|
- style="width: 100%">
|
|
|
+
|
|
|
+ <el-form-item label="视频缩略图" prop="thumbnail">
|
|
|
+ <el-upload v-model="form.thumbnail" class="avatar-uploader" :action="uploadUrl" :show-file-list="false"
|
|
|
+ :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
|
|
|
+ <img v-if="form.thumbnail" :src="form.thumbnail" class="avatar" width="300px">
|
|
|
+ <i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ <video-upload :type="1" :isPrivate="isPrivate" :use-public-video-library="usePublicVideoLibrary" :fileKey.sync="form.fileKey" :fileSize.sync="form.fileSize"
|
|
|
+ :videoUrl.sync="videoUrl" :fileName.sync="form.fileName" :line_1.sync="form.lineOne"
|
|
|
+ :line_2.sync="form.lineTwo" :line_3.sync="form.lineThree" :thumbnail.sync="form.thumbnail"
|
|
|
+ :uploadType.sync="form.uploadType" :isTranscode.sync="form.isTranscode"
|
|
|
+ :transcodeFileKey.sync="form.transcodeFileKey" @video-duration="handleVideoDuration"
|
|
|
+ @change="handleVideoChange" @selectProjects="handleSelectProjects" ref="videoUpload"
|
|
|
+ append-to-body/>
|
|
|
+
|
|
|
+<!-- <el-form-item label="关联疗法" >-->
|
|
|
+<!--<!– <el-button size="small" type="primary" @click="choosePackage">选取疗法</el-button>–>-->
|
|
|
+<!-- <el-table border width="100%" style="margin-top:5px;" :data="packageList">-->
|
|
|
+<!-- <el-table-column label="疗法名称" align="center" prop="packageName"/>-->
|
|
|
+<!-- <el-table-column label="疗法图片" align="center" prop="imgUrl">-->
|
|
|
+<!-- <template slot-scope="scope">-->
|
|
|
+<!-- <img :src="scope.row.imgUrl" style="height: 80px;">-->
|
|
|
+<!-- </template>-->
|
|
|
+<!-- </el-table-column>-->
|
|
|
+<!-- <el-table-column label="疗法别名" align="center" prop="secondName"/>-->
|
|
|
+<!-- <el-table-column label="总金额" align="center" prop="totalPrice"/>-->
|
|
|
+<!-- <!– 根据课程类型控制是否显示弹出时间列:0是公域(显示),1是私域(不显示) –>-->
|
|
|
+<!-- <el-table-column label="弹出时间" align="center" width="250px" v-if="isPrivate == 0">-->
|
|
|
+<!-- <template slot-scope="scope">-->
|
|
|
+<!-- <div>-->
|
|
|
+<!-- <el-time-select-->
|
|
|
+<!-- v-model="scope.row.duration"-->
|
|
|
+<!-- size="mini"-->
|
|
|
+<!-- placeholder="选择时间"-->
|
|
|
+<!-- :picker-options="getPickerOptions()"-->
|
|
|
+<!-- @change="handleTimeChange(scope.$index, scope.row)"-->
|
|
|
+<!-- ></el-time-select>-->
|
|
|
+<!-- </div>-->
|
|
|
+<!-- </template>-->
|
|
|
+<!-- </el-table-column>-->
|
|
|
+<!-- <el-table-column label="操作" align="center" width="100px" fixed="right">-->
|
|
|
+<!-- <template slot-scope="scope">-->
|
|
|
+<!-- <el-button-->
|
|
|
+<!-- size="mini"-->
|
|
|
+<!-- type="text"-->
|
|
|
+<!-- icon="el-icon-delete"-->
|
|
|
+<!-- @click="handlePackageDelete(scope.row)"-->
|
|
|
+<!-- >删除</el-button>-->
|
|
|
+<!-- </template>-->
|
|
|
+<!-- </el-table-column>-->
|
|
|
+<!-- </el-table>-->
|
|
|
+<!-- </el-form-item >-->
|
|
|
+
|
|
|
+ <el-form-item label="课题选择" prop="questionBankId">
|
|
|
+ <el-button size="small" type="primary" @click="chooseQuestionBank">选取课题</el-button>
|
|
|
+ <el-table border width="100%" style="margin-top:5px;" :data="form.questionBankList">
|
|
|
+ <el-table-column label="问题" align="center" prop="title">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-tooltip class="item" effect="dark" :content="scope.row.title" placement="top">
|
|
|
+ <div
|
|
|
+ style="display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden; text-overflow: ellipsis;">
|
|
|
+ <span>{{ scope.row.title }}</span>
|
|
|
+ </div>
|
|
|
+ </el-tooltip>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="类别" align="center" prop="type">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <dict-tag :options="typeOptions" :value="scope.row.type"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="答案" align="center" prop="answer"/>
|
|
|
+ <el-table-column label="操作" align="center" width="100px" fixed="right">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-delete"
|
|
|
+ @click="handleQuestionBankDelete(scope.row)">删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="红包金额" prop="redPacketMoney">
|
|
|
+ <el-input-number v-model="form.redPacketMoney" :min="0.1" :max="200" :step="0.1"></el-input-number>
|
|
|
+ </el-form-item>
|
|
|
+ <!-- v-if="!!form.randomRedPacketRulesArr" -->
|
|
|
+ <el-form-item v-if="!!enableRandomRedPacket" label="随机红包金额" >
|
|
|
+ <template >
|
|
|
+ <div v-for="(rule, index) in form.randomRedPacketRulesArr" :key="index" class="form-row">
|
|
|
+ <el-form-item
|
|
|
+ label="随机红包金额区间"
|
|
|
+ :prop="`randomRedPacketRulesArr.${index}.minAmount`"
|
|
|
+ :rules="[
|
|
|
+ { required: true, message: '请输入最小金额', trigger: 'blur' },
|
|
|
+ { validator: validateMinAmount, trigger: 'blur', index: index }
|
|
|
+ ]"
|
|
|
+ class="form-item-amount"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model.number="rule.minAmount"
|
|
|
+ type="number"
|
|
|
+ :min="0.01"
|
|
|
+ :precision="2"
|
|
|
+ :step="0.01"
|
|
|
+ placeholder="最小金额"
|
|
|
+ size="small"
|
|
|
+ class="amount-input"
|
|
|
+ @input="handleAmountInput(rule, 'minAmount')"
|
|
|
+ ></el-input>
|
|
|
+ <span class="separator">-</span>
|
|
|
+ <el-input
|
|
|
+ v-model.number="rule.maxAmount"
|
|
|
+ type="number"
|
|
|
+ :min="rule.minAmount || 0.01"
|
|
|
+ :precision="2"
|
|
|
+ :step="0.01"
|
|
|
+ placeholder="最大金额"
|
|
|
+ size="small"
|
|
|
+ class="amount-input"
|
|
|
+ @input="handleAmountInput(rule, 'maxAmount')"
|
|
|
+ ></el-input>
|
|
|
+ <span class="suffix">元</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item
|
|
|
+ label="随机权重"
|
|
|
+ :prop="`randomRedPacketRulesArr.${index}.weight`"
|
|
|
+ :rules="[
|
|
|
+ { required: true, message: '请输入权重', trigger: 'blur' },
|
|
|
+ { type: 'integer', message: '权重必须为整数', trigger: 'blur' },
|
|
|
+ ]"
|
|
|
+ class="form-item-weight"
|
|
|
+ >
|
|
|
+ <el-input
|
|
|
+ v-model.number="rule.weight"
|
|
|
+ type="number"
|
|
|
+ :min="1"
|
|
|
+ placeholder="权重"
|
|
|
+ size="small"
|
|
|
+ ></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ <el-tooltip class="item" effect="dark" content="权重越高,被随机到的概率越大" placement="top">
|
|
|
+ <i class="el-icon-question"></i>
|
|
|
+ </el-tooltip>
|
|
|
+ <div class="action-buttons">
|
|
|
+ <el-button
|
|
|
+ icon="el-icon-plus"
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ @click="addRule(index)"
|
|
|
+ class="add-btn"
|
|
|
+ >
|
|
|
+ 新增
|
|
|
+ </el-button>
|
|
|
+ <el-button
|
|
|
+ icon="el-icon-delete"
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ @click="deleteRule(index)"
|
|
|
+ :disabled="form.randomRedPacketRulesArr.length <= 1"
|
|
|
+ class="delete-btn"
|
|
|
+ >
|
|
|
+ 删除
|
|
|
+ </el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否关联商品" prop="isProduct">
|
|
|
+ <el-radio-group v-model="form.isProduct">
|
|
|
+ <el-radio :label="1">是</el-radio>
|
|
|
+ <el-radio :label="0">否</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否先导课" prop="isFirst">
|
|
|
+ <el-radio-group v-model="form.isFirst">
|
|
|
+ <el-radio :label="1">是</el-radio>
|
|
|
+ <el-radio :label="0">否</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否启用倍速" prop="isSpeed">
|
|
|
+ <el-radio-group v-model="form.isSpeed">
|
|
|
+ <el-radio :label="1">是</el-radio>
|
|
|
+ <el-radio :label="0">否</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="是否上架" prop="isOnPut">
|
|
|
+ <el-radio-group v-model="form.isOnPut">
|
|
|
+ <el-radio :label="0">上架</el-radio>
|
|
|
+ <el-radio :label="1">下架</el-radio>
|
|
|
+ </el-radio-group>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="课程优惠券" prop="courseCouponId">
|
|
|
+ <el-select v-model="form.courseCouponId" clearable placeholder="请选择课程优惠券">
|
|
|
<el-option
|
|
|
- v-for="item in qwUserList"
|
|
|
+ v-for="item in courseCouponList"
|
|
|
:key="item.id"
|
|
|
- :label="formatOptionLabel(item)"
|
|
|
+ :label="item.title"
|
|
|
:value="item.id">
|
|
|
</el-option>
|
|
|
</el-select>
|
|
|
</el-form-item>
|
|
|
+ <el-form-item label="商品选择" v-if="form.isProduct === 1">
|
|
|
+ <el-button size="small" type="primary" @click="chooseCourseProduct">选取商品</el-button>
|
|
|
+ <el-table border width="100%" style="margin-top:5px;" :data="form.courseProducts">
|
|
|
+ <el-table-column label="商品名称" align="center" prop="productName"/>
|
|
|
+ <el-table-column label="产品条码" align="center" prop="barCode"/>
|
|
|
+ <el-table-column label="商品价格" align="center" prop="productPrice"/>
|
|
|
+ <el-table-column label="库存" align="center" prop="stock"/>
|
|
|
+ <el-table-column label="操作" align="center" width="100px" fixed="right">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button size="mini" type="text" icon="el-icon-delete"
|
|
|
+ @click="handleCourseProductDelete(scope.row)">删除
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </el-form-item>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item v-if="form.isProduct === 1" label="商品售卖时间" prop="listingStartTime">
|
|
|
+ <el-input-number v-model="form.listingStartTime" :min="0" label="商品售卖时间"></el-input-number>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-form-item v-if="form.isProduct === 1" label="结束售卖时间" prop="listingStartTime">
|
|
|
+ <el-input-number v-model="form.listingEndTime" :min="0" label="结束售卖时间"></el-input-number>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-form-item v-if="usePublicVideoLibrary" label="观看时长" prop="watchDurationMinutes">
|
|
|
+ <el-input-number
|
|
|
+ v-model="form.watchDurationMinutes"
|
|
|
+ :min="0"
|
|
|
+ :precision="0"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ placeholder="请输入"
|
|
|
+ class="input-num-fixed"
|
|
|
+ style="width: 200px"
|
|
|
+ />
|
|
|
+ <span class="form-unit">分钟</span>
|
|
|
+ <span class="form-hint">注释:用户在页面的停留时间</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item v-if="usePublicVideoLibrary" label="积分奖励" prop="integralReward">
|
|
|
+ <el-input-number
|
|
|
+ v-model="form.integralReward"
|
|
|
+ :min="0"
|
|
|
+ :precision="0"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ placeholder="请输入"
|
|
|
+ class="input-num-fixed"
|
|
|
+ style="width: 200px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="课程介绍图" prop="courseIntroImg">
|
|
|
+ <el-upload
|
|
|
+ class="avatar-uploader"
|
|
|
+ :action="uploadUrl"
|
|
|
+ :show-file-list="false"
|
|
|
+ :on-success="handleCourseIntroSuccess"
|
|
|
+ :before-upload="beforeCourseIntroUpload">
|
|
|
+ <img v-if="form.courseIntroImg" :src="form.courseIntroImg" class="avatar" style="max-width: 300px; max-height: 200px;">
|
|
|
+ <i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
|
|
+ </el-upload>
|
|
|
+ <div style="margin-top:5px;">
|
|
|
+ <el-button v-if="form.courseIntroImg" size="mini" type="danger" @click="form.courseIntroImg = null">删除图片</el-button>
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+<!-- <el-form-item label="精选留言">-->
|
|
|
+<!-- <el-button size="small" type="primary" @click="openCommentImportDialog">导入留言</el-button>-->
|
|
|
+<!-- <el-button size="small" style="margin-left: 8px;" @click="openUserCommentDialog">用户留言</el-button>-->
|
|
|
+<!-- </el-form-item>-->
|
|
|
</el-form>
|
|
|
<div slot="footer" class="dialog-footer">
|
|
|
- <el-button @click="dialogVisible = false">取消</el-button>
|
|
|
- <el-button type="primary" @click="confirm">确认</el-button>
|
|
|
+ <el-button type="primary" @click="submitForm">确 定</el-button>
|
|
|
+ <el-button @click="cancel">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog title="导入精选留言" :visible.sync="commentImportDialog.visible" width="600px" append-to-body>
|
|
|
+ <el-upload
|
|
|
+ drag
|
|
|
+ :auto-upload="false"
|
|
|
+ :limit="1"
|
|
|
+ accept=".xls,.xlsx"
|
|
|
+ :on-change="handleCommentFileChange"
|
|
|
+ :file-list="commentImportDialog.fileList">
|
|
|
+ <i class="el-icon-upload"></i>
|
|
|
+ <div class="el-upload__text">将Excel文件拖到此处,或<em>点击上传</em></div>
|
|
|
+ <div class="el-upload__tip" slot="tip">仅支持.xls/.xlsx格式</div>
|
|
|
+ </el-upload>
|
|
|
+ <div style="margin-top: 10px;">
|
|
|
+ <el-button size="small" type="text" @click="handleDownloadTemplate">下载Excel导入模板</el-button>
|
|
|
+ </div>
|
|
|
+ <div v-if="commentImportDialog.historyList.length > 0" style="margin-top: 15px;">
|
|
|
+ <el-divider content-position="left">历史上传留言</el-divider>
|
|
|
+ <el-table :data="commentImportDialog.historyList" border size="small" max-height="300">
|
|
|
+ <el-table-column label="昵称" prop="nickName" width="100"/>
|
|
|
+ <el-table-column label="评论内容" prop="content" show-overflow-tooltip/>
|
|
|
+ <el-table-column label="上传时间" prop="createTime" width="160"/>
|
|
|
+ <el-table-column label="操作" width="70" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-button type="text" size="mini" style="color:#F56C6C" @click="handleDeleteComment(scope.row)">删除</el-button>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+ </div>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" :loading="commentImportDialog.loading" @click="handleImportComments">确认导入</el-button>
|
|
|
+ <el-button @click="commentImportDialog.visible = false">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog :title="title" :visible.sync="updateBatchData.open" width="1000px" append-to-body>
|
|
|
+ <el-form ref="form" :model="updateBatchData.form" label-width="110px">
|
|
|
+ <el-form-item label="看课时间" prop="timeRange">
|
|
|
+ <el-time-picker is-range v-model="updateBatchData.form.timeRange" range-separator="至"
|
|
|
+ start-placeholder="开始时间"
|
|
|
+ value-format="HH:mm:ss" end-placeholder="结束时间" placeholder="选择时间范围">
|
|
|
+ </el-time-picker>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="领取红包时间" prop="lastJoinTime">
|
|
|
+ <el-time-picker v-model="updateBatchData.form.lastJoinTime" :selectableRange="updateBatchData.form.timeRange"
|
|
|
+ value-format="HH:mm:ss" placeholder="选择时间范围">
|
|
|
+ </el-time-picker>
|
|
|
+ <p style="color: red;margin: 0;font-size: 12px">超过领取红包时间,只允许看课,不允许领取红包</p>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="updateBatch">确 定</el-button>
|
|
|
+ <el-button @click="updateBatchData.open = false">取 消</el-button>
|
|
|
</div>
|
|
|
</el-dialog>
|
|
|
|
|
|
- <AutoTagDialog
|
|
|
- :visible.sync="tagDialogVisible"
|
|
|
- :title="tagDialogTitle"
|
|
|
- :videoId="currentVideoId"
|
|
|
- append-to-body
|
|
|
- />
|
|
|
+ <el-dialog title="批量修改观看时长与积分" :visible.sync="batchWatchIntegral.open" width="520px" append-to-body>
|
|
|
+ <p class="batch-watch-tip">已选 <strong>{{ ids.length }}</strong> 条课节,将统一更新为下方数值(仅本课程下已选中的记录)。</p>
|
|
|
+ <el-form label-width="120px">
|
|
|
+ <el-form-item label="观看时长">
|
|
|
+ <el-input-number
|
|
|
+ v-model="batchWatchIntegral.form.watchDurationMinutes"
|
|
|
+ :min="0"
|
|
|
+ :precision="0"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ style="width: 200px"
|
|
|
+ />
|
|
|
+ <span class="form-unit">分钟</span>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="积分奖励">
|
|
|
+ <el-input-number
|
|
|
+ v-model="batchWatchIntegral.form.integralReward"
|
|
|
+ :min="0"
|
|
|
+ :precision="0"
|
|
|
+ :step="1"
|
|
|
+ controls-position="right"
|
|
|
+ style="width: 200px"
|
|
|
+ />
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="batchWatchIntegral.open = false">取 消</el-button>
|
|
|
+ <el-button type="primary" @click="submitBatchWatchIntegral">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <el-dialog :title="questionBank.title" :visible.sync="questionBank.open" width="1000px" append-to-body>
|
|
|
+ <question-bank ref="questionBank" @questionBankResult="questionBankResult"></question-bank>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog :title="courseProduct.title" :visible.sync="courseProduct.open" width="1000px" append-to-body>
|
|
|
+ <course-product ref="courseProduct" @courseProductResult="courseProductResult"></course-product>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog title="视频库选择" :visible.sync="addBatchData.open" width="900px" append-to-body>
|
|
|
+ <!-- 搜索条件 -->
|
|
|
+ <el-form :inline="true" :model="addBatchData.queryParams" class="library-search">
|
|
|
+ <el-form-item label="素材名称">
|
|
|
+ <el-input v-model="addBatchData.queryParams.resourceName" placeholder="请输入素材名称" clearable size="small"
|
|
|
+ @keyup.enter.native="resourceList"/>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="类型">
|
|
|
+ <el-select v-model="addBatchData.queryParams.typeId" @change="changeCateType" placeholder="请选择素材类型"
|
|
|
+ clearable
|
|
|
+ size="small">
|
|
|
+ <el-option v-for="item in addBatchData.typeOptions" :key="item.dictValue" :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"/>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item label="子类型">
|
|
|
+ <el-select v-model="addBatchData.queryParams.typeSubId" placeholder="请选择素材子类型" clearable size="small">
|
|
|
+ <el-option v-for="item in addBatchData.typeSubOptions" :key="item.dictValue" :label="item.dictLabel"
|
|
|
+ :value="item.dictValue"/>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ <el-form-item>
|
|
|
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="resourceList">搜索</el-button>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+
|
|
|
+ <!-- 视频列表 -->
|
|
|
+ <el-table v-loading="addBatchData.loading" :data="addBatchData.list"
|
|
|
+ @selection-change="handVideoleSelectionChange" height="400px">
|
|
|
+ <el-table-column type="selection" width="55" align="center"/>
|
|
|
+ <el-table-column label="素材名称" align="center" prop="resourceName"/>
|
|
|
+ <el-table-column label="文件名称" align="center" prop="fileName"/>
|
|
|
+ <el-table-column label="排序" align="center" prop="sort"/>
|
|
|
+ <el-table-column label="缩略图" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-popover placement="right" title="" trigger="hover">
|
|
|
+ <img alt="" slot="reference" :src="scope.row.thumbnail" style="width: 80px; height: 50px"/>
|
|
|
+ <img alt="" :src="scope.row.thumbnail" style="max-width: 150px;"/>
|
|
|
+ </el-popover>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="视频时长" align="center">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <span>{{ formatDuration(scope.row.duration) }}</span>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ </el-table>
|
|
|
+
|
|
|
+ <!-- 分页 -->
|
|
|
+ <pagination v-show="addBatchData.total > 0" :total="addBatchData.total"
|
|
|
+ :page.sync="addBatchData.queryParams.pageNum" :limit.sync="addBatchData.queryParams.pageSize"
|
|
|
+ @pagination="resourceList"/>
|
|
|
+
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="batchVideoSave">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog title="章节红包" :visible.sync="redData.open" :close-on-click-modal="false" width="900px" append-to-body>
|
|
|
+ <el-table border v-loading="redData.loading" :data="redData.list" height="600px">
|
|
|
+ <el-table-column label="小节名称" align="center" show-overflow-tooltip prop="title">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input class="el-input" v-model="scope.row.title"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="视频文件名称" align="center" show-overflow-tooltip prop="fileName">
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="视频时长" align="center" prop="duration">
|
|
|
+ <template slot-scope="{ row }">
|
|
|
+ {{ formatDuration(row.duration) }}
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="红包金额" align="center" prop="redPacketMoney">
|
|
|
+ <template slot-scope="scope">
|
|
|
+ <el-input class="el-input" v-model="scope.row.redPacketMoney"/>
|
|
|
+ </template>
|
|
|
+ </el-table-column>
|
|
|
+ <el-table-column label="排序" align="center" prop="courseSort"/>
|
|
|
+ <el-table-column label="上传时间" align="center" prop="createTime"/>
|
|
|
+ </el-table>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="batchRedSave">确 定</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog :title="commentDialog.title" :visible.sync="commentDialog.open" width="1000px" append-to-body
|
|
|
+ :close-on-click-modal="false">
|
|
|
+ <course-watch-comment ref="courseWatchComment" :courseId="commentDialog.courseId" :videoId="commentDialog.videoId"
|
|
|
+ v-if="commentDialog.open">
|
|
|
+ </course-watch-comment>
|
|
|
+ </el-dialog>
|
|
|
+ <el-dialog :title="userCommentDialog.title" :visible.sync="userCommentDialog.open" width="1000px" append-to-body
|
|
|
+ :close-on-click-modal="false" @opened="onUserCommentDialogOpened">
|
|
|
+ <user-course-section-comment
|
|
|
+ v-if="userCommentDialog.open"
|
|
|
+ ref="userCourseSectionComment"
|
|
|
+ :course-id="userCommentDialog.courseId"
|
|
|
+ :video-id="userCommentDialog.videoId"
|
|
|
+ />
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
|
|
|
+ <el-dialog title="修改课节排序" :visible.sync="openVideoSort" style="width: 1600px;" append-to-body>
|
|
|
+ <draggable v-model="userCourseVideoSortList" @end="onDragEndDay" style="padding: 10px">
|
|
|
+ <el-button style="margin: 8px 4px;" v-for="(item, index) in userCourseVideoSortList"
|
|
|
+ :class="item.newCourseSort != item.courseSort ? 'red':''">第{{
|
|
|
+ item.newCourseSort
|
|
|
+ }}序(原排序第{{ item.courseSort }})
|
|
|
+ </el-button>
|
|
|
+ </draggable>
|
|
|
+ <div style="float: right;margin-top: -20px">
|
|
|
+ <el-button type="primary" @click="saveSorts">保存</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 批量修改封面 -->
|
|
|
+ <el-dialog :title="batchEditCoverDialog.title" :visible.sync="batchEditCoverDialog.visible" width="500px" append-to-body>
|
|
|
+ <el-form ref="batchEditCoverDialogForm"
|
|
|
+ :model="batchEditCoverDialog.form"
|
|
|
+ :rules="batchEditCoverDialog.rules"
|
|
|
+ v-loading="batchEditCoverDialog.uploadLoading">
|
|
|
+ <el-form-item label="视频封面" prop="thumbnail">
|
|
|
+ <el-upload v-model="batchEditCoverDialog.form.thumbnail"
|
|
|
+ class="avatar-uploader"
|
|
|
+ :action="uploadUrl"
|
|
|
+ :show-file-list="false"
|
|
|
+ :on-success="handleCoverSuccess"
|
|
|
+ :before-upload="beforeAvatarUpload">
|
|
|
+ <img v-if="batchEditCoverDialog.form.thumbnail" :src="batchEditCoverDialog.form.thumbnail" class="avatar" width="300px">
|
|
|
+ <i v-else class="el-icon-plus avatar-uploader-icon"></i>
|
|
|
+ </el-upload>
|
|
|
+ </el-form-item>
|
|
|
+ </el-form>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button type="primary" @click="submitEditCoverForm">确 定</el-button>
|
|
|
+ <el-button @click="cancelEditCoverForm">取 消</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
+
|
|
|
+ <!-- 销售易参数弹窗 -->
|
|
|
+ <el-dialog
|
|
|
+ title="复制销售易参数"
|
|
|
+ :visible.sync="xsyDialogVisible"
|
|
|
+ width="500px"
|
|
|
+ append-to-body
|
|
|
+ >
|
|
|
+ <div style="margin-bottom: 20px;">
|
|
|
+ <el-input
|
|
|
+ v-model="xsyParams"
|
|
|
+ type="textarea"
|
|
|
+ :rows="3"
|
|
|
+ readonly
|
|
|
+ placeholder="参数将显示在这里"
|
|
|
+ class="xsy-textarea"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div slot="footer" class="dialog-footer">
|
|
|
+ <el-button @click="xsyDialogVisible = false">取消</el-button>
|
|
|
+ <el-button type="primary" @click="copyXsyParams">复制参数</el-button>
|
|
|
+ </div>
|
|
|
+ </el-dialog>
|
|
|
</div>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
-import {getVideoListByCourseId, updatePacketMoney, updateUserCourseVideoUpdate} from "@/api/course/userCourseVideo";
|
|
|
-import userCourseVideoDetails from '../../components/course/userCourseVideoDetails.vue';
|
|
|
-import {createLinkUrl, createRoomLinkUrl, queryQwIds} from "@/api/course/sopCourseLink";
|
|
|
-import AutoTagDialog from "@/views/components/tag/AutoTagDialog.vue";
|
|
|
-import {addTag, updateTag} from "@/api/tag/api";
|
|
|
+import {
|
|
|
+ addUserCourseVideo,
|
|
|
+ batchSaveVideo,
|
|
|
+ batchUpdateRed,
|
|
|
+ delUserCourseVideo,
|
|
|
+ getSort,
|
|
|
+ getUserCourseVideo,
|
|
|
+ getVideoListByCourseId,
|
|
|
+ getPublicVideoListByCourseId,
|
|
|
+ getVideoListByCourseIdAll,
|
|
|
+ sortCourseVideo,
|
|
|
+ updates,
|
|
|
+ updateUserCourseVideo,
|
|
|
+ batchUpdateWatchIntegral,
|
|
|
+ syncTemplate, batchDownUserCourseVideo, batchEditCover, batchUpUserCourseVideo, getPublicUserCourseVideo
|
|
|
+} from '@/api/course/userCourseVideo'
|
|
|
+// import {syncTemplate} from '@/api/course/userCourse'
|
|
|
+import QuestionBank from "@/views/course/courseQuestionBank/QuestionBank.vue";
|
|
|
+import CourseProduct from "@/views/course/fsCourseProduct/CourseProduct.vue";
|
|
|
+import VideoUpload from "@/components/VideoUpload/index.vue";
|
|
|
+import {listVideoResource, listPublicVideoResource} from '@/api/course/videoResource';
|
|
|
+import {getByIds} from '@/api/course/courseQuestionBank'
|
|
|
+import CourseWatchComment from "./courseWatchComment.vue";
|
|
|
+import UserCourseSectionComment from "./userCourseSectionComment.vue";
|
|
|
+import {getCateListByPid, getCatePidList, getPublicCateListByPid, getPublicCatePidList} from '@/api/course/userCourseCategory'
|
|
|
+import {downloadCommentImportTemplate, importComments, listFeaturedComments, delUserCourseComment} from '@/api/course/userCourseComment'
|
|
|
+import draggable from 'vuedraggable'
|
|
|
+import { getConfigByKey } from '@/api/system/config'
|
|
|
+import { options as courserCouponOptions} from "@/api/his/courserCoupon";
|
|
|
|
|
|
export default {
|
|
|
- name: "userCourseCatalog",
|
|
|
- components: {
|
|
|
- userCourseVideoDetails,
|
|
|
- AutoTagDialog
|
|
|
- },
|
|
|
- props: {
|
|
|
- video: {
|
|
|
- type: Object,
|
|
|
- required: true,
|
|
|
+ name: "userCourseCatalog",
|
|
|
+ components: {VideoUpload, QuestionBank, CourseWatchComment, UserCourseSectionComment, CourseProduct, draggable},
|
|
|
+ props: {
|
|
|
+ /** 为 true 时「视频库选择」使用公域分类 + 公域素材接口;默认 false 走原 list / 原分类下拉 */
|
|
|
+ usePublicVideoLibrary: {
|
|
|
+ type: Boolean,
|
|
|
+ default: false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch:{
|
|
|
+ // 深度监听 rules 数组的变化,以更新总权重
|
|
|
+ "form.randomRedPacketRulesArr": {
|
|
|
+ handler(val) {
|
|
|
+ // this.calculateTotalWeight();
|
|
|
+ this.validateRules();
|
|
|
},
|
|
|
+ deep: true,
|
|
|
},
|
|
|
- data() {
|
|
|
- return {
|
|
|
- currentRow: null,
|
|
|
- // 假设这里有当前课程小节的数据传入,里面含id等
|
|
|
- tagGroups: [],
|
|
|
- tagsInGroup: [],
|
|
|
- tagDialogVisible: false,
|
|
|
- tagDialogTitle: "",
|
|
|
- tagDialogFormData: null,
|
|
|
- currentVideoId:null,
|
|
|
- projectFrom:process.env.VUE_APP_PROJECT_FROM,
|
|
|
- tagDialog: {
|
|
|
- videoId: null,
|
|
|
- groupId: null,
|
|
|
- watchTagId: null,
|
|
|
- finishTagId: null,
|
|
|
- tgId: null,
|
|
|
- watchingTgId: null,
|
|
|
- watchedTgId: null
|
|
|
- },
|
|
|
- linkForm:{
|
|
|
- days:null,
|
|
|
- courseId:null,
|
|
|
- videoId:null
|
|
|
- },
|
|
|
- roomLinkForm:{
|
|
|
- courseId:null,
|
|
|
- videoId:null,
|
|
|
- qwUserId:null,
|
|
|
- qwUserName:null,
|
|
|
- corpId:null,
|
|
|
- title:null,
|
|
|
- },
|
|
|
- dialogVisible: false, // 控制弹框显示
|
|
|
- //短链
|
|
|
- sortLink:'',
|
|
|
- //课题
|
|
|
- questionBank:{
|
|
|
- title:'',
|
|
|
- open:false,
|
|
|
- },
|
|
|
- moneyOpen:false,
|
|
|
- videoUrl: "",
|
|
|
- uploadTypeOptions: [
|
|
|
- { dictLabel: "线路一", dictValue: 2 },
|
|
|
-
|
|
|
- { dictLabel: "线路二", dictValue: 1 },
|
|
|
- { dictLabel: "线路三", dictValue: 3 },
|
|
|
- ],
|
|
|
- uploadLoading:false,
|
|
|
- courseId:null,
|
|
|
- videoName:'',
|
|
|
- title: "",
|
|
|
- redPacketMoneyForm:{
|
|
|
- redPacketMoney:null,
|
|
|
- voidId:null
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ courseCouponList: [],
|
|
|
+ duration: null,
|
|
|
+ packageList: [],
|
|
|
+ //课题
|
|
|
+ package: {
|
|
|
+ title: '',
|
|
|
+ open: false,
|
|
|
+ },
|
|
|
+ //课题
|
|
|
+ questionBank: {
|
|
|
+ title: '',
|
|
|
+ open: false,
|
|
|
+ },
|
|
|
+ //拍商品
|
|
|
+ courseProduct: {
|
|
|
+ title: '',
|
|
|
+ open: false,
|
|
|
+ },
|
|
|
+ isPrivate: null,
|
|
|
+ videoUrl: "",
|
|
|
+ uploadTypeOptions: [
|
|
|
+ {dictLabel: "线路一", dictValue: 2},
|
|
|
+ {dictLabel: "线路二", dictValue: 3},
|
|
|
+ ],
|
|
|
+ uploadLoading: false,
|
|
|
+ courseId: null,
|
|
|
+ videoName: '',
|
|
|
+ title: "",
|
|
|
+ // 是否显示弹出层
|
|
|
+ open: false,
|
|
|
+ uploadUrl: process.env.VUE_APP_BASE_API + "/common/uploadOSS",
|
|
|
+ baseUrl: process.env.VUE_APP_BASE_API,
|
|
|
+ projectFrom:process.env.VUE_APP_PROJECT,
|
|
|
+ typeOptions: [],
|
|
|
+ files: [],
|
|
|
+ fileList: [],
|
|
|
+ // 上传成功后的地址
|
|
|
+ videoURL: '',
|
|
|
+ // 进度条百分比
|
|
|
+ progress: 0,
|
|
|
+ // 上传视频获取成功后拿到的fileID【备用】
|
|
|
+ fileId: '',
|
|
|
+ courseName: null,
|
|
|
+ userCourseVideoList: [],
|
|
|
+ userCourseVideoSortList: [],
|
|
|
+ total: 0,
|
|
|
+ redData: {
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 99999,
|
|
|
+ courseId: null,
|
|
|
},
|
|
|
- // 是否显示弹出层
|
|
|
+ list: [],
|
|
|
open: false,
|
|
|
- uploadUrl:process.env.VUE_APP_BASE_API+"/common/uploadHuaWeiObs",
|
|
|
- baseUrl: process.env.VUE_APP_BASE_API,
|
|
|
- typeOptions:[],
|
|
|
- files:[],
|
|
|
- fileList: [],
|
|
|
- // 上传成功后的地址
|
|
|
- videoURL: '',
|
|
|
- // 进度条百分比
|
|
|
- progress: 0,
|
|
|
- // 上传视频获取成功后拿到的fileID【备用】
|
|
|
- fileId: '',
|
|
|
- courseName:null,
|
|
|
- userCourseVideoList:[],
|
|
|
-
|
|
|
- fetchingQwIds: false,
|
|
|
- qwUserList:[],
|
|
|
+ loading: true,
|
|
|
+ form: {}
|
|
|
+ },
|
|
|
+ queryParams: {
|
|
|
+ pageNum: 1,
|
|
|
+ pageSize: 10,
|
|
|
+ courseId: null,
|
|
|
+ videoId: null,
|
|
|
+ title: null
|
|
|
+ },
|
|
|
+ addBatchData: {
|
|
|
+ open: false,
|
|
|
+ loading: true,
|
|
|
+ form: {},
|
|
|
+ select: [], // 按用户选择顺序存储视频ID
|
|
|
total: 0,
|
|
|
queryParams: {
|
|
|
pageNum: 1,
|
|
|
pageSize: 10,
|
|
|
- courseId:null,
|
|
|
- title:null
|
|
|
+ resourceName: null,
|
|
|
+ typeId: null,
|
|
|
+ typeSubId: null
|
|
|
},
|
|
|
- // 显示搜索条件
|
|
|
- showSearch: true,
|
|
|
- // 遮罩层
|
|
|
- loading: true,
|
|
|
- // 导出遮罩层
|
|
|
- exportLoading: false,
|
|
|
- // 选中数组
|
|
|
- ids: [],
|
|
|
- // 非单个禁用
|
|
|
- single: true,
|
|
|
- // 非多个禁用
|
|
|
- multiple: true,
|
|
|
- // 表单参数
|
|
|
- form: {},
|
|
|
- // 表单校验
|
|
|
- rules: {
|
|
|
- title: [
|
|
|
- { required: true, message: "小节名称不能为空", trigger: "change" }
|
|
|
- ],
|
|
|
- courseSort: [
|
|
|
- { required: true, message: "排序不能为空", trigger: "change" }
|
|
|
- ],
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- created() {
|
|
|
- this.getDicts("sys_course_temp_type").then(response => {
|
|
|
- this.typeOptions = response.data;
|
|
|
- });
|
|
|
- },
|
|
|
- methods: {
|
|
|
- formatOptionLabel(item) {
|
|
|
- return item.corpName ? `${item.qwUserName} (${item.corpName})` : item.qwUserName;
|
|
|
+ typeOptions: [],
|
|
|
+ typeSubOptions: []
|
|
|
},
|
|
|
- closeTagDialog(){
|
|
|
- this.tagDialogVisible = false;
|
|
|
+ // 显示搜索条件
|
|
|
+ showSearch: true,
|
|
|
+ // 遮罩层
|
|
|
+ loading: true,
|
|
|
+ // 导出遮罩层
|
|
|
+ exportLoading: false,
|
|
|
+ // 选中数组
|
|
|
+ ids: [],
|
|
|
+ // 非单个禁用
|
|
|
+ single: true,
|
|
|
+ // 非多个禁用
|
|
|
+ multiple: true,
|
|
|
+ loading3: false,
|
|
|
+ openVideoSort: false,
|
|
|
+ // 表单参数
|
|
|
+ form: {
|
|
|
+ isOnPut: 0,
|
|
|
+ courseProducts: [],
|
|
|
+ courseIntroImg: null,
|
|
|
+ randomRedPacketRules:null,
|
|
|
+ randomRedPacketRulesArr:[
|
|
|
+ {
|
|
|
+ minAmount: 0.01,
|
|
|
+ maxAmount: 0.01,
|
|
|
+ weight: 100,
|
|
|
+ }
|
|
|
+ ]
|
|
|
},
|
|
|
- openTagDialog(row) {
|
|
|
- this.currentRow = row;
|
|
|
-
|
|
|
+ updateBatchData: {
|
|
|
+ open: false,
|
|
|
+ form: {}
|
|
|
+ },
|
|
|
+ batchWatchIntegral: {
|
|
|
+ open: false,
|
|
|
+ form: {
|
|
|
+ watchDurationMinutes: 0,
|
|
|
+ integralReward: 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 表单校验
|
|
|
+ rules: {
|
|
|
+ title: [
|
|
|
+ {required: true, message: "小节名称不能为空", trigger: "change"}
|
|
|
+ ],
|
|
|
+ courseSort: [
|
|
|
+ {required: true, message: "排序不能为空", trigger: "change"}
|
|
|
+ ],
|
|
|
|
|
|
- this.tagDialogVisible = true;
|
|
|
- this.currentVideoId = row.videoId;
|
|
|
},
|
|
|
- updateTagsInGroup(groupId) {
|
|
|
- let tagGroup = this.tagGroups.find(e=> e.groupId === groupId);
|
|
|
-
|
|
|
- this.tagsInGroup = tagGroup.tag || [];
|
|
|
- // 切换组时清空标签选择
|
|
|
- this.tagDialog.watchTagId = null;
|
|
|
- this.tagDialog.finishTagId = null;
|
|
|
- this.tagDialog.tgId = tagGroup.id;
|
|
|
+ // 评论弹窗数据
|
|
|
+ commentDialog: {
|
|
|
+ open: false,
|
|
|
+ courseId: null,
|
|
|
+ videoId: null,
|
|
|
+ title: ""
|
|
|
},
|
|
|
- resetDialog() {
|
|
|
- this.tagDialog = {
|
|
|
- videoId: null,
|
|
|
- groupId: null,
|
|
|
- watchTagId: null,
|
|
|
- finishTagId: null,
|
|
|
- };
|
|
|
- this.tagGroups = [];
|
|
|
- this.tagsInGroup = [];
|
|
|
+ userCommentDialog: {
|
|
|
+ open: false,
|
|
|
+ courseId: null,
|
|
|
+ videoId: null,
|
|
|
+ title: ""
|
|
|
},
|
|
|
- // 打开弹框
|
|
|
- openDialog(row) {
|
|
|
- if (!this.fetchingQwIds) {
|
|
|
- this.fetchingQwIds = true;
|
|
|
- queryQwIds().then(response => {
|
|
|
- if (response.code === 200){
|
|
|
- this.qwUserList = response.list;
|
|
|
- }
|
|
|
- }).finally(() => {
|
|
|
- this.fetchingQwIds = false;
|
|
|
- // 在请求完成后再显示弹框
|
|
|
- this.showDialog(row);
|
|
|
- });
|
|
|
- } else {
|
|
|
- // 如果已经在请求中,直接显示弹框
|
|
|
- this.showDialog(row);
|
|
|
+ enableRandomRedPacket:false,
|
|
|
+ // 批量修改封面
|
|
|
+ batchEditCoverDialog: {
|
|
|
+ title: '修改视频封面',
|
|
|
+ visible: false,
|
|
|
+ uploadLoading: false,
|
|
|
+ form: {
|
|
|
+ thumbnail: null,
|
|
|
+ },
|
|
|
+ rules: {
|
|
|
+ thumbnail: [
|
|
|
+ {required: true, message: "视频封面不能为空", trigger: "change"}
|
|
|
+ ],
|
|
|
}
|
|
|
},
|
|
|
- // 新增方法:显示弹框
|
|
|
- showDialog(row) {
|
|
|
- this.roomLinkForm.courseId = row.courseId;
|
|
|
- this.roomLinkForm.videoId = row.videoId;
|
|
|
- this.roomLinkForm.title = row.title;
|
|
|
-
|
|
|
- this.dialogVisible = true;
|
|
|
+ // 销售易弹窗
|
|
|
+ xsyDialogVisible: false,
|
|
|
+ xsyParams: '',
|
|
|
+ // 精选留言导入弹窗
|
|
|
+ commentImportDialog: {
|
|
|
+ visible: false,
|
|
|
+ loading: false,
|
|
|
+ fileList: [],
|
|
|
+ file: null,
|
|
|
+ historyList: [],
|
|
|
+ courseId: null,
|
|
|
+ videoId: null
|
|
|
},
|
|
|
- // 确认按钮操作
|
|
|
- confirm() {
|
|
|
- if (!this.roomLinkForm.qwUserId) {
|
|
|
- this.$message.error("请选择销售企微!");
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ this.getDicts("sys_course_temp_type").then(response => {
|
|
|
+ this.typeOptions = response.data;
|
|
|
+ });
|
|
|
+ getConfigByKey('randomRedpacket:config').then(res=>{
|
|
|
+ let configData = res.data;
|
|
|
+ if(!!configData && !!configData.configValue){
|
|
|
+ let configValue = JSON.parse(configData.configValue);
|
|
|
+ if(!!configValue.enableRandomRedpacket){
|
|
|
+ this.enableRandomRedPacket = configValue.enableRandomRedpacket;
|
|
|
+ console.log("this.enableRandomRedPacket ::" + this.enableRandomRedPacket)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }).catch(res=>{
|
|
|
+
|
|
|
+ });
|
|
|
+ courserCouponOptions().then(res=>{
|
|
|
+ this.courseCouponList = res.data;
|
|
|
+ }).catch(res=>{
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getPickerOptions() {
|
|
|
+ const durationInMinutes = Math.floor(this.form.duration / 60); // 将秒转换为分钟
|
|
|
+ const endHour = Math.floor(durationInMinutes / 60); // 起始小时
|
|
|
+ const endMinute = durationInMinutes % 60; // 起始分钟
|
|
|
+ return {
|
|
|
+ start: "00:00", // 固定开始时间
|
|
|
+ step: "00:01", // 时间间隔
|
|
|
+ end: `${endHour.toString().padStart(2, "0")}:${endMinute
|
|
|
+ .toString()
|
|
|
+ .padStart(2, "0")}`, // 动态结束时间
|
|
|
+ };
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理时间选择框值变化
|
|
|
+ handleTimeChange(index, row) {
|
|
|
+ // 确保 packageList 中的数据被正确更新
|
|
|
+ this.$set(this.packageList, index, row);
|
|
|
+ // 同步更新 form.packageJson 字段
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 确保每个疗法包都有 duration 字段
|
|
|
+ this.packageList.forEach(item => {
|
|
|
+ if (item.duration === undefined || item.duration === null) {
|
|
|
+ item.duration = ''; // 空值应初始化为空字符串而不是null,避免显示"null"
|
|
|
+ }
|
|
|
+ });
|
|
|
+ this.form.packageJson = JSON.stringify(this.packageList);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ handlePackageDelete(row) {
|
|
|
+ this.packageList.splice(this.packageList.findIndex(item => item.packageId === row.packageId), 1)
|
|
|
+ },
|
|
|
+ choosePackage() {
|
|
|
+ this.package.open = true;
|
|
|
+ this.package.title = '疗法选择';
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 选择课题
|
|
|
+ */
|
|
|
+ chooseQuestionBank() {
|
|
|
+ this.questionBank.open = true;
|
|
|
+ this.questionBank.title = '课题选择';
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 选择拍商品
|
|
|
+ */
|
|
|
+ chooseCourseProduct() {
|
|
|
+ this.courseProduct.open = true;
|
|
|
+ this.courseProduct.title = '拍商品选择';
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ //选择疗法
|
|
|
+ selectPackage(row) {
|
|
|
+ const drug = {};
|
|
|
+ for (var i = 0; i < this.packageList.length; i++) {
|
|
|
+ if (this.packageList[i].packageId == row.packageId) {
|
|
|
+ this.$message.warning("疗法已存在!")
|
|
|
return;
|
|
|
}
|
|
|
- // 获取选中的用户信息
|
|
|
- const selectedUser = this.qwUserList.find(user => user.id === this.roomLinkForm.qwUserId);
|
|
|
- if (selectedUser) {
|
|
|
- // 将用户信息填充到表单中
|
|
|
- this.roomLinkForm.qwUserName = selectedUser.qwUserName;
|
|
|
- this.roomLinkForm.corpId = selectedUser.corpId;
|
|
|
- console.log(this.roomLinkForm);
|
|
|
- // 调用创建链接的API
|
|
|
- createRoomLinkUrl(this.roomLinkForm).then(response => {
|
|
|
- if (response.code === 200){
|
|
|
- this.msgSuccess("创建成功");
|
|
|
- this.copyLink(response.link);
|
|
|
- console.log(response.link);
|
|
|
+ }
|
|
|
+ drug.packageId = row.packageId;
|
|
|
+ drug.packageName = row.packageName;
|
|
|
+ drug.secondName = row.secondName;
|
|
|
+ drug.totalPrice = row.totalPrice;
|
|
|
+ drug.imgUrl = row.imgUrl;
|
|
|
+ this.packageList.push(drug);
|
|
|
+ this.$message({
|
|
|
+ message: '添加成功',
|
|
|
+ type: 'success'
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ courseProductResult(val) {
|
|
|
+ this.form.courseProducts = this.form.courseProducts || [];
|
|
|
+ for (var i = 0; i < this.form.courseProducts.length; i++) {
|
|
|
+ if (this.form.courseProducts[i].id == val.id) {
|
|
|
+ return this.$message.error("当前商品已选择")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //先置空 只选择一件商品
|
|
|
+ this.form.courseProducts = [];
|
|
|
+ this.form.courseProducts.push(val);
|
|
|
+ this.$message({
|
|
|
+ message: '添加成功',
|
|
|
+ type: 'success'
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ //选择结果
|
|
|
+ questionBankResult(val) {
|
|
|
+
|
|
|
+ // 确保 questionBankList 是数组
|
|
|
+ this.form.questionBankList = this.form.questionBankList || [];
|
|
|
+
|
|
|
+ for (var i = 0; i < this.form.questionBankList.length; i++) {
|
|
|
+ if (this.form.questionBankList[i].id == val.id) {
|
|
|
+ return this.$message.error("当前课题已选择")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.form.questionBankList.push(val);
|
|
|
+ this.$message({
|
|
|
+ message: '添加成功',
|
|
|
+ type: 'success'
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ //删除课题
|
|
|
+ handleQuestionBankDelete(row) {
|
|
|
+ this.form.questionBankList.splice(this.form.questionBankList.findIndex(item => item.id === row.id), 1)
|
|
|
+ },
|
|
|
+
|
|
|
+ //删除商品
|
|
|
+ handleCourseProductDelete(row) {
|
|
|
+ this.form.courseProducts.splice(this.form.courseProducts.findIndex(item => item.id === row.id), 1)
|
|
|
+ },
|
|
|
+ handleVideoChange() {
|
|
|
+ if (this.form.uploadType == 1) {
|
|
|
+ this.videoUrl = this.form.lineOne;
|
|
|
+ } else if (this.form.uploadType == 2) {
|
|
|
+ this.videoUrl = this.form.lineTwo;
|
|
|
+ } else if (this.form.uploadType == 3) {
|
|
|
+ this.videoUrl = this.form.lineThree;
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 视频库课题
|
|
|
+ handleSelectProjects(projectIds) {
|
|
|
+ this.form.questionBankList = []
|
|
|
+ if (!projectIds || projectIds.length === 0 || this.isPrivate === 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const params = {ids: projectIds}
|
|
|
+ getByIds(params).then(response => {
|
|
|
+ if (response.code === 200) {
|
|
|
+ response.data.forEach(item => {
|
|
|
+ let isExist = this.form.questionBankList.some(q => q.id === item.id)
|
|
|
+ if (!isExist) {
|
|
|
+ this.form.questionBankList.push(item)
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
+ })
|
|
|
+ },
|
|
|
+ handleVideoDuration(duration) {
|
|
|
+ this.form.duration = duration;
|
|
|
+ },
|
|
|
+ formatDuration(seconds) {
|
|
|
+ if (seconds === null || seconds === undefined) {
|
|
|
+ return '未上传视频';
|
|
|
+ }
|
|
|
+ const hours = Math.floor(seconds / 3600);
|
|
|
+ const minutes = Math.floor((seconds % 3600) / 60);
|
|
|
+ const remainingSeconds = seconds % 60;
|
|
|
|
|
|
- // 关闭弹框
|
|
|
- this.dialogVisible = false;
|
|
|
- },
|
|
|
- // 重置表单
|
|
|
- resetForm() {
|
|
|
- this.linkForm={
|
|
|
- days:null,
|
|
|
- courseId:null,
|
|
|
- videoId:null
|
|
|
+ const formattedHours = hours > 0 ? hours.toString() + ':' : '';
|
|
|
+ const formattedMinutes = minutes.toString().padStart(2, '0');
|
|
|
+ const formattedSeconds = remainingSeconds.toString().padStart(2, '0');
|
|
|
+
|
|
|
+ return `${formattedHours}${formattedMinutes}:${formattedSeconds}`;
|
|
|
+ },
|
|
|
+
|
|
|
+ handleAvatarSuccess(res, file) {
|
|
|
+ if (res.code == 200) {
|
|
|
+ this.form.thumbnail = res.url;
|
|
|
+ this.$forceUpdate()
|
|
|
+ } else {
|
|
|
+ this.msgError(res.msg);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ beforeAvatarUpload(file) {
|
|
|
+ const isLt1M = file.size / 1024 / 1024 < 5;
|
|
|
+ if (!isLt1M) {
|
|
|
+ this.$message.error('上传图片大小不能超过 5MB!');
|
|
|
+ }
|
|
|
+ return isLt1M;
|
|
|
+ },
|
|
|
+ getDetails(courseId, courseName, isPrivate) {
|
|
|
+ this.isPrivate = isPrivate
|
|
|
+ this.courseName = courseName
|
|
|
+ this.courseId = courseId;
|
|
|
+ this.queryParams.courseId = courseId;
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ getList() {
|
|
|
+ this.loading = true;
|
|
|
+ const api = this.usePublicVideoLibrary ? getPublicVideoListByCourseId : getVideoListByCourseId;
|
|
|
+ api(this.queryParams).then(response => {
|
|
|
+ this.userCourseVideoList = response.rows;
|
|
|
+ this.total = response.total;
|
|
|
+ this.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 取消按钮
|
|
|
+ cancel() {
|
|
|
+ this.open = false;
|
|
|
+ this.reset();
|
|
|
+ },
|
|
|
+ // 表单重置
|
|
|
+ reset() {
|
|
|
+ this.form = {
|
|
|
+ videoId: null,
|
|
|
+ title: null,
|
|
|
+ description: null,
|
|
|
+ url: null,
|
|
|
+ thumbnail: null,
|
|
|
+ duration: null,
|
|
|
+ createTime: null,
|
|
|
+ uploadType: null,
|
|
|
+ lineOne: null,
|
|
|
+ lineTwo: null,
|
|
|
+ lineThree: null,
|
|
|
+ fileName: null,
|
|
|
+ userId: null,
|
|
|
+ cateId: null,
|
|
|
+ courseId: null,
|
|
|
+ likes: null,
|
|
|
+ views: null,
|
|
|
+ comments: null,
|
|
|
+ status: 0,
|
|
|
+ courseSort: 1,
|
|
|
+ isHot: null,
|
|
|
+ isShow: null,
|
|
|
+ isAudit: null,
|
|
|
+ auditBy: null,
|
|
|
+ auditTime: null,
|
|
|
+ updateTime: null,
|
|
|
+ source: null,
|
|
|
+ isDel: null,
|
|
|
+ shares: null,
|
|
|
+ tags: null,
|
|
|
+ productId: null,
|
|
|
+ productJson: null,
|
|
|
+ questionBankId: null,
|
|
|
+ questionBankList: [],
|
|
|
+ redPacketMoney: 0,
|
|
|
+ isTranscode: 0,
|
|
|
+ transcodeFileKey: null,
|
|
|
+ isProduct: 0,
|
|
|
+ isFirst: 0,
|
|
|
+ isSpeed: 0,
|
|
|
+ isOnPut: 0,
|
|
|
+ listingStartTime: null,
|
|
|
+ listingEndTime: null,
|
|
|
+ watchDurationMinutes: null,
|
|
|
+ integralReward: null,
|
|
|
+ randomRedPacketRules:null,
|
|
|
+ randomRedPacketRulesArr:[
|
|
|
+ {
|
|
|
+ minAmount: 0.01,
|
|
|
+ maxAmount: 0.01,
|
|
|
+ weight: 100,
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ courseIntroImg: null
|
|
|
+ };
|
|
|
+ this.videoURL = '';
|
|
|
+ this.progress = 0;
|
|
|
+ this.resetForm("form");
|
|
|
+ },
|
|
|
+ /** 搜索按钮操作 */
|
|
|
+ handleQuery() {
|
|
|
+ this.queryParams.pageNum = 1;
|
|
|
+ this.getList();
|
|
|
+ },
|
|
|
+ /** 重置按钮操作 */
|
|
|
+ resetQuery() {
|
|
|
+ this.resetForm("queryForm");
|
|
|
+ this.handleQuery();
|
|
|
+ },
|
|
|
+ // 多选框选中数据
|
|
|
+ handleSelectionChange(selection) {
|
|
|
+ this.ids = selection.map(item => item.videoId)
|
|
|
+ this.single = selection.length !== 1
|
|
|
+ this.multiple = !selection.length
|
|
|
+ },
|
|
|
+ // 视频库多选框选中数据(按用户点击顺序记录)
|
|
|
+ handVideoleSelectionChange(selection) {
|
|
|
+ // 提取当前选中的所有ID
|
|
|
+ const selectedIds = selection.map(item => item.id);
|
|
|
+ // 处理新增选中项:保留用户点击顺序
|
|
|
+ selectedIds.forEach(id => {
|
|
|
+ if (!this.addBatchData.select.includes(id)) {
|
|
|
+ this.addBatchData.select.push(id);
|
|
|
}
|
|
|
- },
|
|
|
+ });
|
|
|
+ // 处理取消选中项:移除已取消的ID
|
|
|
+ this.addBatchData.select = this.addBatchData.select.filter(id => selectedIds.includes(id));
|
|
|
+ },
|
|
|
+ handleAdd() {
|
|
|
+ this.reset();
|
|
|
+ this.form.courseId = this.courseId;
|
|
|
+ this.open = true;
|
|
|
+ this.title = "添加课堂视频";
|
|
|
+ this.videoUrl = '';
|
|
|
+ this.packageList = [];
|
|
|
+ getSort(this.courseId).then(response => {
|
|
|
+ this.form.courseSort = Number(response.data);
|
|
|
+ })
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$refs.videoUpload.resetUpload();
|
|
|
+ }, 500);
|
|
|
|
|
|
- resetRoomForm() {
|
|
|
- this.roomLinkForm={
|
|
|
- courseId:null,
|
|
|
- videoId:null,
|
|
|
- qwUserId:null,
|
|
|
+ },
|
|
|
+ /** 修改按钮操作 */
|
|
|
+ handleUpdate(row) {
|
|
|
+ this.reset();
|
|
|
+ this.form.isOnPut=row.isOnPut
|
|
|
+ this.packageList = [];
|
|
|
+ const videoId = row.videoId || this.ids
|
|
|
+ const api = this.usePublicVideoLibrary ? getPublicUserCourseVideo : getUserCourseVideo;
|
|
|
+ api(videoId).then(response => {
|
|
|
+ console.log(response);
|
|
|
+ this.form = response.data;
|
|
|
+ this.$set(this.form, 'courseIntroImg', response.data.courseIntroImg || null);
|
|
|
+ this.$set(this.form, 'isOnPut', response.data.isOnPut !== undefined ? response.data.isOnPut : 0);
|
|
|
+ if(!!this.form.randomRedPacketRules){
|
|
|
+ this.$set(this.form, 'randomRedPacketRulesArr', JSON.parse(this.form.randomRedPacketRules)) ;
|
|
|
+ // this.form.randomRedPacketRulesArr = JSON.parse(this.form.randomRedPacketRules);
|
|
|
+ }else{
|
|
|
+ //处理初始值
|
|
|
+ this.form.randomRedPacketRulesArr = [{
|
|
|
+ minAmount: 0.01,
|
|
|
+ maxAmount: 0.01,
|
|
|
+ weight: 100,
|
|
|
+ }]
|
|
|
}
|
|
|
- },
|
|
|
- handleCreateLink(){
|
|
|
- createLinkUrl(this.linkForm).then(response => {
|
|
|
- if (response.code === 200){
|
|
|
- this.copyLink(response.url);
|
|
|
+ if (response.data.videoUrl != null && response.data.videoUrl !== '') {
|
|
|
+ this.videoUrl = response.data.videoUrl;
|
|
|
+ }
|
|
|
+ if (this.form.packageJson != null) {
|
|
|
+ this.packageList = JSON.parse(this.form.packageJson);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (response.data.viewStartTime != null && response.data.viewEndTime != null) {
|
|
|
+ this.form.timeRange = [response.data.viewStartTime, response.data.viewEndTime]
|
|
|
+ }
|
|
|
+ setTimeout(() => {
|
|
|
+ this.$refs.videoUpload.resetUpload();
|
|
|
+ }, 500);
|
|
|
+ this.open = true;
|
|
|
+ this.title = "修改课堂视频";
|
|
|
+ });
|
|
|
+
|
|
|
+ },
|
|
|
+ /** 提交按钮 */
|
|
|
+ submitForm() {
|
|
|
+ this.$refs["form"].validate(valid => {
|
|
|
+
|
|
|
+ if (valid) {
|
|
|
+ this.form.videoUrl = this.videoUrl;
|
|
|
+ if (this.form.videoUrl == null || this.form.videoUrl === '') {
|
|
|
+ this.$message({
|
|
|
+ message: '请上传视频!',
|
|
|
+ type: 'warning'
|
|
|
+ });
|
|
|
+ return
|
|
|
}
|
|
|
- });
|
|
|
- },
|
|
|
- copyLink(url) {
|
|
|
- const link = url;
|
|
|
- // navigator clipboard 需要https等安全上下文
|
|
|
- if (navigator.clipboard && window.isSecureContext) {
|
|
|
- // navigator clipboard 向剪贴板写文本
|
|
|
- navigator.clipboard.writeText(link).then(() => {
|
|
|
- this.$message.success('链接已复制到剪贴板');
|
|
|
- });
|
|
|
- } else {
|
|
|
- // document.execCommand('copy') 向剪贴板写文本
|
|
|
- let input = document.createElement('input')
|
|
|
- input.style.position = 'fixed'
|
|
|
- input.style.top = '-10000px'
|
|
|
- input.style.zIndex = '-999'
|
|
|
- document.body.appendChild(input)
|
|
|
- input.value = link
|
|
|
- input.focus()
|
|
|
- input.select()
|
|
|
- try {
|
|
|
- let result = document.execCommand('copy')
|
|
|
- document.body.removeChild(input)
|
|
|
- if (!result || result === 'unsuccessful') {
|
|
|
- this.$message.error('复制失败');
|
|
|
- console.log('复制失败')
|
|
|
- } else {
|
|
|
- this.$message.success('链接已复制到剪贴板');
|
|
|
- console.log('复制成功')
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- document.body.removeChild(input)
|
|
|
- alert('当前浏览器不支持复制功能,请检查更新或更换其他浏览器操作')
|
|
|
+
|
|
|
+ if (this.form.timeRange && this.form.timeRange.length === 2) {
|
|
|
+ this.form.viewStartTime = this.form.timeRange[0];
|
|
|
+ this.form.viewEndTime = this.form.timeRange[1];
|
|
|
+ }
|
|
|
+
|
|
|
+ if (this.form.duration == null) {
|
|
|
+ this.$message({
|
|
|
+ message: '未识别到视频时长请稍等。。。',
|
|
|
+ type: 'warning'
|
|
|
+ });
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.form.isProduct != null && this.form.isProduct == 1 && (this.form.courseProducts == null || this.form.courseProducts.length < 1)) {
|
|
|
+ this.$message({
|
|
|
+ message: '请选择关联商品',
|
|
|
+ type: 'warning'
|
|
|
+ });
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.form.questionBankList !== null) {
|
|
|
+ this.form.questionBankId = this.form.questionBankList.map(item => item.id).join(',');
|
|
|
+ }
|
|
|
+ if (this.packageList.length > 0) {
|
|
|
+ this.form.packageJson = JSON.stringify(this.packageList);
|
|
|
+ }
|
|
|
+ if (this.form.courseProducts != null) {
|
|
|
+ this.form.productId = this.form.courseProducts.map(item => item.id).join(',');
|
|
|
+ }
|
|
|
+ if(!!this.form.randomRedPacketRulesArr){
|
|
|
+ let rulesJson = JSON.stringify(this.form.randomRedPacketRulesArr);
|
|
|
+ this.form.randomRedPacketRules = rulesJson;
|
|
|
+ }
|
|
|
+ if (this.form.videoId != null) {
|
|
|
+ updateUserCourseVideo(this.form).then(response => {
|
|
|
+ this.msgSuccess("修改成功");
|
|
|
+ this.open = false;
|
|
|
+ this.getList();
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ addUserCourseVideo(this.form).then(response => {
|
|
|
+ this.msgSuccess("新增成功");
|
|
|
+ this.open = false;
|
|
|
+ this.getList();
|
|
|
+ });
|
|
|
}
|
|
|
}
|
|
|
- },
|
|
|
- formatDuration(seconds) {
|
|
|
- if (seconds === null || seconds === undefined) {
|
|
|
- return '未上传视频'; // 或者您可以根据具体需求返回其他默认值
|
|
|
+ });
|
|
|
+ },
|
|
|
+ openUpdates() {
|
|
|
+ this.updateBatchData.form = {};
|
|
|
+ this.updateBatchData.open = true;
|
|
|
+ },
|
|
|
+ /** 提交按钮 */
|
|
|
+ updateBatch() {
|
|
|
+ this.updateBatchData.form.ids = this.ids;
|
|
|
+ if (this.updateBatchData.form.timeRange != null && this.updateBatchData.form.timeRange.length === 2) {
|
|
|
+ this.updateBatchData.form.viewStartTime = this.updateBatchData.form.timeRange[0];
|
|
|
+ this.updateBatchData.form.viewEndTime = this.updateBatchData.form.timeRange[1];
|
|
|
+ }
|
|
|
+ updates(this.updateBatchData.form).then(response => {
|
|
|
+ this.msgSuccess("修改成功");
|
|
|
+ this.updateBatchData.open = false;
|
|
|
+ this.getList();
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 删除按钮操作 */
|
|
|
+ handleDelete(row) {
|
|
|
+ const videoIds = row.videoId || this.ids;
|
|
|
+ this.$confirm('是否确认删除视频编号为"' + videoIds + '"的数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(function () {
|
|
|
+ return delUserCourseVideo(videoIds);
|
|
|
+ }).then(() => {
|
|
|
+ this.getList();
|
|
|
+ this.msgSuccess("删除成功");
|
|
|
+ }).catch(() => {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 同步模板数据*/
|
|
|
+ handleSync() {
|
|
|
+ const courseId = this.courseId;
|
|
|
+ this.$confirm('是否同步课程数据至模板', "确认", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(function () {
|
|
|
+ return syncTemplate(courseId);
|
|
|
+ }).then(() => {
|
|
|
+ this.getList();
|
|
|
+ this.msgSuccess("正在同步模板中!!请稍后!");
|
|
|
+ }).catch(() => {
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ handleCourseSort() {
|
|
|
+
|
|
|
+ getVideoListByCourseIdAll(this.queryParams.courseId).then(response => {
|
|
|
+
|
|
|
+ response.rows.forEach((item) => item.newCourseSort = item.courseSort);
|
|
|
+ this.userCourseVideoSortList = response.rows.sort((a, b) => a.courseSort - b.courseSort);
|
|
|
+ if (this.userCourseVideoSortList == null || this.userCourseVideoSortList.length == 0) {
|
|
|
+ this.$message.error("暂无课节天数")
|
|
|
+ } else {
|
|
|
+ this.openVideoSort = true;
|
|
|
}
|
|
|
- const hours = Math.floor(seconds / 3600);
|
|
|
- const minutes = Math.floor((seconds % 3600) / 60);
|
|
|
- const remainingSeconds = seconds % 60;
|
|
|
+ })
|
|
|
|
|
|
- const formattedHours = hours > 0 ? hours.toString() + ':' : '';
|
|
|
- const formattedMinutes = minutes.toString().padStart(2, '0');
|
|
|
- const formattedSeconds = remainingSeconds.toString().padStart(2, '0');
|
|
|
|
|
|
- return `${formattedHours}${formattedMinutes}:${formattedSeconds}`;
|
|
|
- },
|
|
|
- getDetails(courseId,courseName) {
|
|
|
- this.courseName = courseName
|
|
|
- this.courseId = courseId;
|
|
|
- this.queryParams.courseId = courseId;
|
|
|
+ },
|
|
|
+
|
|
|
+ onDragEndDay() {
|
|
|
+ this.userCourseVideoSortList.forEach((item, index) => {
|
|
|
+ item.newCourseSort = index + 1;
|
|
|
+ })
|
|
|
+ this.$forceUpdate()
|
|
|
+ },
|
|
|
+
|
|
|
+ saveSorts() {
|
|
|
+ let list = this.userCourseVideoSortList.filter(e => e.courseSort != e.newCourseSort).map(e => {
|
|
|
+ return {courseSort: e.newCourseSort, videoId: e.videoId}
|
|
|
+ })
|
|
|
+ this.loading3 = true;
|
|
|
+ sortCourseVideo(list).then(e => {
|
|
|
this.getList();
|
|
|
- },
|
|
|
- getList() {
|
|
|
- this.loading = true;
|
|
|
- getVideoListByCourseId(this.queryParams).then(response => {
|
|
|
- this.userCourseVideoList = response.rows;
|
|
|
- this.total = response.total;
|
|
|
- this.loading = false;
|
|
|
+ }).finally(() => {
|
|
|
+ this.userCourseVideoSortList = [];
|
|
|
+ this.openVideoSort = false;
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ openAdds() {
|
|
|
+ this.addBatchData.open = true;
|
|
|
+ this.getRootTypeList();
|
|
|
+ this.addBatchData.form = {
|
|
|
+ courseId: this.courseId,
|
|
|
+ };
|
|
|
+ // 重置选择顺序数组
|
|
|
+ this.addBatchData.select = [];
|
|
|
+ this.resourceList();
|
|
|
+ },
|
|
|
+ openBatchWatchIntegralDialog() {
|
|
|
+ if (!this.ids || this.ids.length === 0) {
|
|
|
+ this.$message.warning('请先勾选要修改的课节');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.batchWatchIntegral.form = {
|
|
|
+ watchDurationMinutes: 0,
|
|
|
+ integralReward: 0
|
|
|
+ };
|
|
|
+ this.batchWatchIntegral.open = true;
|
|
|
+ },
|
|
|
+ submitBatchWatchIntegral() {
|
|
|
+ const w = this.batchWatchIntegral.form.watchDurationMinutes;
|
|
|
+ const i = this.batchWatchIntegral.form.integralReward;
|
|
|
+ if (w === null || w === undefined || i === null || i === undefined) {
|
|
|
+ this.$message.warning('请填写观看时长与积分奖励');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const videoIds = (this.ids || []).map(id => (typeof id === 'string' ? parseInt(id, 10) : id));
|
|
|
+ batchUpdateWatchIntegral({
|
|
|
+ courseId: this.courseId,
|
|
|
+ videoIds: videoIds,
|
|
|
+ watchDurationMinutes: w,
|
|
|
+ integralReward: i
|
|
|
+ }).then(response => {
|
|
|
+ if (response.code === 200) {
|
|
|
+ this.msgSuccess('修改成功');
|
|
|
+ this.batchWatchIntegral.open = false;
|
|
|
+ this.getList();
|
|
|
+ } else {
|
|
|
+ this.$message.error(response.msg || '修改失败');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ getRootTypeList() {
|
|
|
+ const req = this.usePublicVideoLibrary ? getPublicCatePidList() : getCatePidList()
|
|
|
+ req.then(response => {
|
|
|
+ this.addBatchData.typeOptions = response.data
|
|
|
+ });
|
|
|
+ },
|
|
|
+ async changeCateType(val) {
|
|
|
+ this.addBatchData.queryParams.typeSubId = null
|
|
|
+ this.addBatchData.typeSubOptions = []
|
|
|
+ if (!val) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const subReq = this.usePublicVideoLibrary ? getPublicCateListByPid(val) : getCateListByPid(val)
|
|
|
+ await subReq.then(response => {
|
|
|
+ this.addBatchData.typeSubOptions = response.data
|
|
|
+ })
|
|
|
+ },
|
|
|
+ resourceList() {
|
|
|
+ this.addBatchData.loading = true;
|
|
|
+ const api = this.usePublicVideoLibrary ? listPublicVideoResource : listVideoResource
|
|
|
+ api(this.addBatchData.queryParams).then(response => {
|
|
|
+ this.addBatchData.loading = false;
|
|
|
+ this.addBatchData.list = response.rows;
|
|
|
+ this.addBatchData.total = response.total;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ batchVideoSave() {
|
|
|
+ if (this.addBatchData.select.length === 0) {
|
|
|
+ this.$message({
|
|
|
+ message: '请选择视频!!',
|
|
|
+ type: 'warning'
|
|
|
});
|
|
|
- },
|
|
|
- // 取消按钮
|
|
|
- cancel() {
|
|
|
- this.open = false;
|
|
|
- this.reset();
|
|
|
- },
|
|
|
- updateMoney(row){
|
|
|
- this.redPacketMoneyForm.redPacketMoney=row.companyRedPacketMoney;
|
|
|
- this.redPacketMoneyForm.videoId=row.videoId;
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.addBatchData.form.ids = this.addBatchData.select; // 按用户选择顺序提交
|
|
|
+ batchSaveVideo(this.addBatchData.form).then(response => {
|
|
|
+ this.addBatchData.open = false;
|
|
|
+ this.getList();
|
|
|
+ })
|
|
|
+ },
|
|
|
+ updateRedPageckeOpen() {
|
|
|
+ this.redData.open = true;
|
|
|
+ this.redData.loading = true;
|
|
|
+ this.redData.queryParams.courseId = this.courseId;
|
|
|
+ getVideoListByCourseId(this.redData.queryParams).then(response => {
|
|
|
+ if(!!response.rows && response.rows.length >0){
|
|
|
+ for(let i = 0; i < response.rows.length; i++){
|
|
|
+ if(!!response.rows[i].randomRedPacketRules){
|
|
|
+ this.$set(response.rows[i], 'randomRedPacketRulesArr', JSON.parse(response.rows[i].randomRedPacketRules)) ;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.redData.list = response.rows;
|
|
|
+ console.log(this.redData.list);
|
|
|
+ this.redData.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+ batchRedSave() {
|
|
|
+ batchUpdateRed(this.redData.list).then(response => {
|
|
|
+ this.redData.open = false;
|
|
|
+ this.getList();
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 查看评论按钮操作 */
|
|
|
+ handleComment(row) {
|
|
|
+ this.commentDialog.courseId = row.courseId || this.courseId;
|
|
|
+ this.commentDialog.videoId = row.videoId;
|
|
|
+ this.commentDialog.title = `查看评论 - ${row.title}`;
|
|
|
+ this.commentDialog.open = true;
|
|
|
+ },
|
|
|
+ // 实时过滤金额输入,只允许两位小数
|
|
|
+ handleAmountInput(rule, field) {
|
|
|
+ let value = rule[field];
|
|
|
+ if (value === null || value === undefined) return;
|
|
|
|
|
|
- this.moneyOpen=true;
|
|
|
- },
|
|
|
- submitForm(){
|
|
|
+ // 转换为字符串处理
|
|
|
+ let str = value.toString();
|
|
|
|
|
|
- updatePacketMoney(this.redPacketMoneyForm).then(response => {
|
|
|
- this.msgSuccess("修改成功");
|
|
|
- this.moneyOpen=false;
|
|
|
- this.getList()
|
|
|
- });
|
|
|
- },
|
|
|
- updateMoneycancel(){
|
|
|
- this.moneyOpen=false;
|
|
|
- },
|
|
|
+ // 移除除数字和小数点外的所有字符
|
|
|
+ str = str.replace(/[^0-9.]/g, '');
|
|
|
|
|
|
- // 表单重置
|
|
|
- reset() {
|
|
|
- this.form = {
|
|
|
- videoId: null,
|
|
|
- title: null,
|
|
|
- description: null,
|
|
|
- url: null,
|
|
|
- thumbnail: null,
|
|
|
- duration: null,
|
|
|
- createTime: null,
|
|
|
- uploadType:null,
|
|
|
- lineOne:null,
|
|
|
- lineTwo:null,
|
|
|
- lineThree:null,
|
|
|
- fileName:null,
|
|
|
- userId: null,
|
|
|
- cateId: null,
|
|
|
- courseId: null,
|
|
|
- likes: null,
|
|
|
- views: null,
|
|
|
- comments: null,
|
|
|
- status: 0,
|
|
|
- courseSort: 1,
|
|
|
- isHot: null,
|
|
|
- isShow: null,
|
|
|
- isAudit: null,
|
|
|
- auditBy: null,
|
|
|
- auditTime: null,
|
|
|
- updateTime: null,
|
|
|
- source: null,
|
|
|
- isDel: null,
|
|
|
- shares: null,
|
|
|
- tags: null,
|
|
|
- productId: null,
|
|
|
- productJson: null,
|
|
|
- questionBankId:null,
|
|
|
- questionBankList:[],
|
|
|
- };
|
|
|
- this.videoURL = '';
|
|
|
- this.progress=0;
|
|
|
- this.resetForm("form");
|
|
|
- },
|
|
|
- /** 搜索按钮操作 */
|
|
|
- handleQuery() {
|
|
|
- this.queryParams.pageNum = 1;
|
|
|
+ // 只保留一个小数点
|
|
|
+ const dotIndex = str.indexOf('.');
|
|
|
+ if (dotIndex !== -1) {
|
|
|
+ str = str.substring(0, dotIndex + 1) + str.substring(dotIndex + 1).replace(/\./g, '');
|
|
|
+ }
|
|
|
+
|
|
|
+ // 限制小数点后最多两位
|
|
|
+ if (dotIndex !== -1 && str.length > dotIndex + 3) {
|
|
|
+ str = str.substring(0, dotIndex + 3);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 转换回数字并更新
|
|
|
+ rule[field] = parseFloat(str) || 0;
|
|
|
+ },
|
|
|
+ deleteRule(index) {
|
|
|
+ this.$confirm("确定要删除这个区间吗?", "提示", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning",
|
|
|
+ }).then(() => {
|
|
|
+ this.form.randomRedPacketRulesArr.splice(index, 1);
|
|
|
+ this.$message({
|
|
|
+ type: "success",
|
|
|
+ message: "删除成功!",
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ addRule(index) {
|
|
|
+ // 在当前行的后面插入一个新行
|
|
|
+ this.form.randomRedPacketRulesArr.splice(index + 1, 0, {
|
|
|
+ minAmount: 0.01,
|
|
|
+ maxAmount: 0.01,
|
|
|
+ weight: 100,
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 自定义校验规则:确保最大金额大于最小金额
|
|
|
+ validateMinAmount(rule, value, callback) {
|
|
|
+ // debugger;
|
|
|
+ // const maxAmount = this.form29.rules[].maxAmount
|
|
|
+
|
|
|
+ const index = rule.index;
|
|
|
+ const maxAmount = this.form.randomRedPacketRulesArr[index].maxAmount;
|
|
|
+
|
|
|
+ if (value > maxAmount) {
|
|
|
+ callback(new Error("最小金额不能大于最大金额"));
|
|
|
+ } else {
|
|
|
+ callback();
|
|
|
+ }
|
|
|
+ },
|
|
|
+ validateRules() {
|
|
|
+ this.form.randomRedPacketRulesArr.forEach((rule) => {
|
|
|
+ if (rule.minAmount === undefined || rule.minAmount < 0.01) {
|
|
|
+ rule.minAmount = 0.01;
|
|
|
+ }
|
|
|
+ if (rule.maxAmount === undefined || rule.maxAmount < rule.minAmount) {
|
|
|
+ rule.maxAmount = rule.minAmount;
|
|
|
+ }
|
|
|
+ if (rule.weight === undefined || rule.weight < 1) {
|
|
|
+ rule.weight = 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 下架 **/
|
|
|
+ handleDown() {
|
|
|
+ const videoIds = this.ids;
|
|
|
+ this.$confirm('是否确认下架视频编号为"' + videoIds + '"的数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(function () {
|
|
|
+ return batchDownUserCourseVideo(videoIds);
|
|
|
+ }).then(() => {
|
|
|
this.getList();
|
|
|
- },
|
|
|
- /** 重置按钮操作 */
|
|
|
- resetQuery() {
|
|
|
- this.resetForm("queryForm");
|
|
|
- this.queryParams.title = null;
|
|
|
- this.handleQuery();
|
|
|
- },
|
|
|
- // 多选框选中数据
|
|
|
- handleSelectionChange(selection) {
|
|
|
- this.ids = selection.map(item => item.courseId)
|
|
|
- this.single = selection.length!==1
|
|
|
- this.multiple = !selection.length
|
|
|
- },
|
|
|
- /** 修改按钮操作 */
|
|
|
- handleDetails(row) {
|
|
|
- this.open=true;
|
|
|
- setTimeout(() => {
|
|
|
- this.$refs.userCourseVideoDetails.getDetails(row.videoId);
|
|
|
- }, 500);
|
|
|
+ this.msgSuccess("下架成功");
|
|
|
+ }).catch(() => {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 上架按钮操作 */
|
|
|
+ handleUp() {
|
|
|
+ const videoIds = this.ids;
|
|
|
+ this.$confirm('是否确认上架视频编号为"' + videoIds + '"的数据项?', "警告", {
|
|
|
+ confirmButtonText: "确定",
|
|
|
+ cancelButtonText: "取消",
|
|
|
+ type: "warning"
|
|
|
+ }).then(function () {
|
|
|
+ return batchUpUserCourseVideo(videoIds);
|
|
|
+ }).then(() => {
|
|
|
+ this.getList();
|
|
|
+ this.msgSuccess("上架成功");
|
|
|
+ }).catch(function () {
|
|
|
+ });
|
|
|
+ },
|
|
|
+ /** 修改封面 **/
|
|
|
+ handleEditCover() {
|
|
|
+ this.batchEditCoverDialog.form = {
|
|
|
+ thumbnail: null
|
|
|
+ }
|
|
|
+ this.batchEditCoverDialog.visible = true
|
|
|
+ },
|
|
|
+ handleCoverSuccess(res, file) {
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.batchEditCoverDialog.form.thumbnail = res.url;
|
|
|
+ this.$forceUpdate()
|
|
|
+ } else {
|
|
|
+ this.msgError(res.msg);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ submitEditCoverForm() {
|
|
|
+ this.$refs["batchEditCoverDialogForm"].validate(valid => {
|
|
|
+ if (!valid) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
|
|
|
+ const thumbnail = this.batchEditCoverDialog.form.thumbnail
|
|
|
+ const videoIds = this.ids
|
|
|
+
|
|
|
+ if (!thumbnail || thumbnail === '') {
|
|
|
+ this.$message({
|
|
|
+ message: '请上传封面!',
|
|
|
+ type: 'warning'
|
|
|
+ });
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!videoIds || videoIds.length === 0) {
|
|
|
+ this.$message({
|
|
|
+ message: '请选择小节!',
|
|
|
+ type: 'warning'
|
|
|
+ });
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const params = {
|
|
|
+ thumbnail: thumbnail,
|
|
|
+ videoIds: videoIds
|
|
|
+ }
|
|
|
+
|
|
|
+ batchEditCover(params).then(response => {
|
|
|
+ this.msgSuccess("修改成功")
|
|
|
+ this.batchEditCoverDialog.visible = false
|
|
|
+ this.getList();
|
|
|
+ });
|
|
|
+ });
|
|
|
+ },
|
|
|
+ cancelEditCoverForm() {
|
|
|
+ this.batchEditCoverDialog.visible = false
|
|
|
+ this.batchEditCoverDialog.form = {
|
|
|
+ thumbnail: null,
|
|
|
}
|
|
|
- }
|
|
|
+ },
|
|
|
+ // 复制销售易链接
|
|
|
+ openXsyDialog(row) {
|
|
|
+ // 构建JSON字符串
|
|
|
+ const courseData = {
|
|
|
+ videoId: row.videoId,
|
|
|
+ courseId: row.courseId,
|
|
|
+ companyId: 0
|
|
|
+ };
|
|
|
+
|
|
|
+ this.xsyParams = `pages_course/videoxsy?course=${JSON.stringify(courseData)}`;
|
|
|
+ this.xsyDialogVisible = true;
|
|
|
+ },
|
|
|
+ // 复制销售易参数
|
|
|
+ copyXsyParams() {
|
|
|
+ this.copyLink(this.xsyParams);
|
|
|
+ },
|
|
|
+ copyLink(url) {
|
|
|
+ const link = url;
|
|
|
+ // navigator clipboard 需要https等安全上下文
|
|
|
+ if (navigator.clipboard && window.isSecureContext) {
|
|
|
+ // navigator clipboard 向剪贴板写文本
|
|
|
+ navigator.clipboard.writeText(link).then(() => {
|
|
|
+ this.$message.success('链接已复制到剪贴板');
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ // document.execCommand('copy') 向剪贴板写文本
|
|
|
+ let input = document.createElement('input')
|
|
|
+ input.style.position = 'fixed'
|
|
|
+ input.style.top = '-10000px'
|
|
|
+ input.style.zIndex = '-999'
|
|
|
+ document.body.appendChild(input)
|
|
|
+ input.value = link
|
|
|
+ input.focus()
|
|
|
+ input.select()
|
|
|
+ try {
|
|
|
+ let result = document.execCommand('copy')
|
|
|
+ document.body.removeChild(input)
|
|
|
+ if (!result || result === 'unsuccessful') {
|
|
|
+ this.$message.error('复制失败');
|
|
|
+ console.log('复制失败')
|
|
|
+ } else {
|
|
|
+ this.$message.success('链接已复制到剪贴板');
|
|
|
+ console.log('复制成功')
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ document.body.removeChild(input)
|
|
|
+ alert('当前浏览器不支持复制功能,请检查更新或更换其他浏览器操作')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 课程介绍图片上传成功
|
|
|
+ handleCourseIntroSuccess(res) {
|
|
|
+ if (res.code == 200) {
|
|
|
+ this.form.courseIntroImg = res.url;
|
|
|
+ this.$forceUpdate();
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg || '上传失败');
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 课程介绍图片上传前校验(10MB限制)
|
|
|
+ beforeCourseIntroUpload(file) {
|
|
|
+ const isLt10M = file.size / 1024 / 1024 < 10;
|
|
|
+ if (!isLt10M) {
|
|
|
+ this.$message.error('课程介绍图片大小不能超过10MB!');
|
|
|
+ }
|
|
|
+ const isImage = file.type.startsWith('image/');
|
|
|
+ if (!isImage) {
|
|
|
+ this.$message.error('只能上传图片格式文件!');
|
|
|
+ }
|
|
|
+ return isLt10M && isImage;
|
|
|
+ },
|
|
|
+ // 打开精选留言导入弹窗
|
|
|
+ openUserCommentDialog() {
|
|
|
+ if (!this.form.courseId || !this.form.videoId) {
|
|
|
+ this.$message.warning('请先保存课节后再查看用户留言')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.userCommentDialog.courseId = this.form.courseId
|
|
|
+ this.userCommentDialog.videoId = this.form.videoId
|
|
|
+ this.userCommentDialog.title = `用户留言 - ${this.form.title || ''}`
|
|
|
+ this.userCommentDialog.open = true
|
|
|
+ },
|
|
|
+ onUserCommentDialogOpened() {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.userCourseSectionComment) {
|
|
|
+ this.$refs.userCourseSectionComment.handleQuery()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ openCommentImportDialog() {
|
|
|
+ this.commentImportDialog.visible = true;
|
|
|
+ this.commentImportDialog.file = null;
|
|
|
+ this.commentImportDialog.fileList = [];
|
|
|
+ this.commentImportDialog.courseId = this.form.courseId;
|
|
|
+ this.commentImportDialog.videoId = this.form.videoId;
|
|
|
+ // 加载历史留言
|
|
|
+ listFeaturedComments(this.form.courseId, this.form.videoId).then(res => {
|
|
|
+ this.commentImportDialog.historyList = res.rows || [];
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 选择导入文件
|
|
|
+ handleCommentFileChange(file) {
|
|
|
+ this.commentImportDialog.file = file.raw;
|
|
|
+ },
|
|
|
+ // 删除精选留言
|
|
|
+ handleDeleteComment(row) {
|
|
|
+ this.$confirm('确认删除该条精选留言?', '提示', {type: 'warning'}).then(() => {
|
|
|
+ delUserCourseComment(row.commentId).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success('删除成功');
|
|
|
+ // 刷新历史列表
|
|
|
+ listFeaturedComments(this.commentImportDialog.courseId, this.commentImportDialog.videoId).then(res2 => {
|
|
|
+ this.commentImportDialog.historyList = res2.rows || [];
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg || '删除失败');
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }).catch(() => {});
|
|
|
+ },
|
|
|
+ // 下载Word导入模板
|
|
|
+ handleDownloadTemplate() {
|
|
|
+ downloadCommentImportTemplate().then(res => {
|
|
|
+ const blob = new Blob([res], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'});
|
|
|
+ const url = window.URL.createObjectURL(blob);
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = url;
|
|
|
+ link.download = '精选留言导入模板.xlsx';
|
|
|
+ link.click();
|
|
|
+ window.URL.revokeObjectURL(url);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ // 确认导入精选留言
|
|
|
+ handleImportComments() {
|
|
|
+ if (!this.commentImportDialog.file) {
|
|
|
+ this.$message.warning('请先选择要导入的Excel文件');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ this.commentImportDialog.loading = true;
|
|
|
+ importComments(this.commentImportDialog.courseId, this.commentImportDialog.videoId, this.commentImportDialog.file).then(res => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ this.$message.success(res.msg);
|
|
|
+ // 刷新历史列表
|
|
|
+ listFeaturedComments(this.commentImportDialog.courseId, this.commentImportDialog.videoId).then(res2 => {
|
|
|
+ this.commentImportDialog.historyList = res2.rows || [];
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$message.error(res.msg);
|
|
|
+ }
|
|
|
+ }).finally(() => {
|
|
|
+ this.commentImportDialog.loading = false;
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
}
|
|
|
+}
|
|
|
</script>
|
|
|
+<style scoped>
|
|
|
+.form-unit {
|
|
|
+ margin-left: 8px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+.form-hint {
|
|
|
+ margin-left: 12px;
|
|
|
+ color: #909399;
|
|
|
+ font-size: 12px;
|
|
|
+}
|
|
|
+.batch-watch-tip {
|
|
|
+ margin: 0 0 16px 0;
|
|
|
+ color: #606266;
|
|
|
+ font-size: 13px;
|
|
|
+}
|
|
|
+.avatar-uploader-icon {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+.xsy-textarea >>> .el-textarea__inner {
|
|
|
+ background-color: #f5f5f5 !important;
|
|
|
+ resize: none !important;
|
|
|
+}
|
|
|
+</style>
|
|
|
<style>
|
|
|
- .avatar-uploader .el-upload {
|
|
|
- border: 1px dashed #d9d9d9;
|
|
|
- border-radius: 6px;
|
|
|
- cursor: pointer;
|
|
|
- position: relative;
|
|
|
- overflow: hidden;
|
|
|
- }
|
|
|
- .avatar-uploader .el-upload:hover {
|
|
|
- border-color: #409EFF;
|
|
|
- }
|
|
|
-
|
|
|
- .avatar-uploader-icon {
|
|
|
- font-size: 28px;
|
|
|
- color: #8c939d;
|
|
|
- width: 150px;
|
|
|
- height: 150px;
|
|
|
- line-height: 150px;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
+.avatar-uploader .el-upload {
|
|
|
+ border: 1px dashed #d9d9d9;
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ position: relative;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-uploader .el-upload:hover {
|
|
|
+ border-color: #409EFF;
|
|
|
+}
|
|
|
+
|
|
|
+.avatar-uploader-icon {
|
|
|
+ font-size: 28px;
|
|
|
+ color: #8c939d;
|
|
|
+ width: 150px;
|
|
|
+ height: 150px;
|
|
|
+ line-height: 150px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+.red:hover {
|
|
|
+ color: #dbdbdb !important;
|
|
|
+}
|
|
|
+
|
|
|
+.red {
|
|
|
+ background-color: #F56C6C !important;
|
|
|
+ color: #fff !important;
|
|
|
+}
|
|
|
|
|
|
</style>
|