index.vue 38 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345
  1. <template>
  2. <div id="festivalEdit">
  3. <div class="boxWidth">
  4. <el-form
  5. label-position="right"
  6. label-width="120px"
  7. :model="listData"
  8. :rules="rules"
  9. ref="listData"
  10. >
  11. <el-form-item label="适用业务层级" required>
  12. <el-select
  13. v-model="eduType"
  14. placeholder="请选择教育类型"
  15. @change="changeEduType"
  16. >
  17. <el-option
  18. v-for="(item, index) in eduTypeOptions"
  19. :key="index"
  20. :label="item.educationName"
  21. :value="item.id"
  22. >
  23. </el-option>
  24. </el-select>
  25. <el-select
  26. v-model="courType"
  27. placeholder="请选择业务层次"
  28. @change="changecourseType"
  29. >
  30. <el-option
  31. v-for="(item, index) in newCourTypeOptions"
  32. :key="index"
  33. :label="item.projectName + '-' + item.businessName"
  34. :value="item.id"
  35. >
  36. </el-option>
  37. </el-select>
  38. <el-popover
  39. ref="popovers"
  40. placement="bottom"
  41. trigger="click"
  42. @show="showHandle"
  43. @hide="hideHandle"
  44. :disabled="courType ? false : true"
  45. >
  46. <el-checkbox
  47. v-model="checkAll"
  48. @change="handleCheckAllChange"
  49. :indeterminate="isIndeterminate"
  50. >全选</el-checkbox
  51. >
  52. <el-checkbox-group
  53. v-model="sujectArray"
  54. class="checkboxSty"
  55. @change="handleCheckedCitiesChange"
  56. >
  57. <el-checkbox
  58. v-for="(item, index) in newSujectOption"
  59. :label="item.newId"
  60. :key="index"
  61. >{{ item.subjectName }}</el-checkbox
  62. >
  63. </el-checkbox-group>
  64. <div style="display: block; text-align: center; margin-top: 10px">
  65. <el-button size="mini" type="primary" @click="submitSujectArray"
  66. >确定</el-button
  67. >
  68. </div>
  69. <el-button
  70. slot="reference"
  71. style="margin-left: 12px"
  72. @click="getMessage"
  73. >请选择科目</el-button
  74. >
  75. </el-popover>
  76. <span style="margin-left: 10px">注:可多选</span>
  77. </el-form-item>
  78. <el-form-item label="">
  79. <div :class="changeHeight ? 'ach' : 'clh'">
  80. <div
  81. v-for="(item, index) in newSujectApis"
  82. :key="index"
  83. class="listBoxStys"
  84. >
  85. {{
  86. item.educationName +
  87. " - " +
  88. item.projectName +
  89. " - " +
  90. item.businessName +
  91. " - " +
  92. item.subjectName
  93. }}
  94. <i class="el-icon-error closeIcons" @click="closeType(index)"></i>
  95. </div>
  96. </div>
  97. <el-button
  98. size="mini"
  99. v-if="newSujectApis.length > 1"
  100. @click="changeType"
  101. >{{ changeHeight ? "展开" : "关闭" }}</el-button
  102. ><el-button
  103. size="mini"
  104. v-if="newSujectApis.length > 0"
  105. @click="sujectApis = []"
  106. >清空</el-button
  107. >
  108. <!-- <span v-if="newSujectApis.length === 0">未选项目类型</span> -->
  109. </el-form-item>
  110. <el-form-item label="标题前缀">
  111. <el-input v-model="listData.prefixName"></el-input>
  112. <div style="color: #999">注:便于检索、归类,以及区分一样的标题</div>
  113. </el-form-item>
  114. <el-form-item label="节标题" prop="name">
  115. <el-input v-model="listData.name"></el-input>
  116. <div style="color: #999">
  117. 注:请尽量规范易懂,方便在课程目录表呈现给学员
  118. </div>
  119. </el-form-item>
  120. <el-form-item label="节类型">
  121. <el-select
  122. clearable
  123. :disabled="typeSection == 1 || typeSection == 3"
  124. v-model="listData.sectionType"
  125. placeholder="请选择节类型"
  126. @change="changeTypeSection"
  127. >
  128. <el-option
  129. v-for="(item, index) in sectionTypeOptions"
  130. :key="index"
  131. :disabled="item.value == 1"
  132. :label="item.label"
  133. :value="item.value"
  134. >
  135. </el-option>
  136. </el-select>
  137. </el-form-item>
  138. <el-form-item
  139. label="频道号"
  140. v-if="listData.sectionType === 2"
  141. prop="liveUrl"
  142. >
  143. <el-input
  144. style="width: 300px"
  145. v-model="listData.liveUrl"
  146. placeholder="请输入频道号"
  147. ></el-input>
  148. <el-select
  149. v-model="newActiveLiveUrl"
  150. placeholder="快捷选中频道号"
  151. @change="changeLiveUrl"
  152. >
  153. <el-option
  154. v-for="(item, index) in newLiveUrl"
  155. :key="index"
  156. :label="item.streamingName"
  157. :value="item.id"
  158. >
  159. </el-option>
  160. </el-select>
  161. <div v-if="listData.liveUrl" style="margin-top: 10px">
  162. <el-button
  163. size="small"
  164. type="warning"
  165. @click="watchZbVideo(listData.liveUrl)"
  166. >直播预览</el-button
  167. >
  168. </div>
  169. </el-form-item>
  170. <el-form-item
  171. label="直播开始时间"
  172. prop="liveStartTime"
  173. v-if="listData.sectionType === 2"
  174. >
  175. <el-date-picker
  176. v-model="listData.liveStartTime"
  177. type="datetime"
  178. placeholder="请选择直播开始时间"
  179. value-format="timestamp"
  180. >
  181. </el-date-picker>
  182. </el-form-item>
  183. <el-form-item
  184. label="直播结束时间"
  185. prop="liveEndTime"
  186. v-if="listData.sectionType === 2"
  187. >
  188. <el-date-picker
  189. v-model="listData.liveEndTime"
  190. type="datetime"
  191. placeholder="请选择直播结束时间"
  192. value-format="timestamp"
  193. >
  194. </el-date-picker>
  195. </el-form-item>
  196. <el-form-item
  197. label="直播时长"
  198. v-if="
  199. listData.sectionType === 2 &&
  200. listData.liveStartTime &&
  201. listData.liveEndTime
  202. "
  203. >
  204. {{ compTimeOUT(listData.liveStartTime, listData.liveEndTime) }}
  205. </el-form-item>
  206. <el-form-item
  207. label="URL地址"
  208. v-if="listData.sectionType === 1 || listData.sectionType === 3"
  209. prop="recordingUrl"
  210. >
  211. <el-input
  212. style="width: 300px"
  213. v-model="listData.recordingUrl"
  214. placeholder="请输入URL地址"
  215. @change="getApiTime(listData.recordingUrl)"
  216. ></el-input>
  217. <label
  218. for="mobles"
  219. class="el-button el-button--primary"
  220. style="margin: 0px 6px; padding: 10px 20px"
  221. >上传</label
  222. ><input
  223. style="display: none"
  224. type="file"
  225. id="mobles"
  226. @change="importMoble"
  227. />
  228. <el-select
  229. v-if="listData.sectionType === 1"
  230. v-model="newActiveRecordingUrl1"
  231. placeholder="快捷选中录播URL地址"
  232. filterable
  233. @change="changeRecordingUrl1"
  234. >
  235. <el-option
  236. v-for="(item, index) in newSteamUrl1"
  237. :key="index"
  238. :label="item.streamingName"
  239. :value="item.id"
  240. >
  241. </el-option>
  242. </el-select>
  243. <el-select
  244. v-if="listData.sectionType === 3"
  245. v-model="newActiveRecordingUrl2"
  246. placeholder="快捷选中回放URL地址"
  247. filterable
  248. @change="changeRecordingUrl2"
  249. >
  250. <el-option
  251. v-for="(item, index) in newSteamUrl2"
  252. :key="index"
  253. :label="item.streamingName"
  254. :value="item.id"
  255. >
  256. </el-option>
  257. </el-select>
  258. <div v-if="listData.recordingUrl" style="margin-top: 10px">
  259. <el-button
  260. size="small"
  261. type="warning"
  262. @click="watchVideo(listData.recordingUrl)"
  263. >视频预览</el-button
  264. >
  265. </div>
  266. </el-form-item>
  267. <el-form-item
  268. label="节时长"
  269. v-if="listData.sectionType === 1 || listData.sectionType === 3"
  270. prop="durationTime"
  271. >
  272. <el-time-picker
  273. :disabled="disabloutime"
  274. value-format="HH:mm:ss"
  275. range-separator=":"
  276. v-model="listData.durationTime"
  277. placeholder="请填入节时长"
  278. >
  279. </el-time-picker>
  280. </el-form-item>
  281. <el-form-item
  282. label="讲师"
  283. :prop="listData.sectionType === 2 ? 'teacherId' : ''"
  284. >
  285. <el-select
  286. v-model="listData.teacherId"
  287. placeholder="请选择讲师"
  288. filterable
  289. >
  290. <el-option
  291. v-for="(item, index) in teacherList"
  292. :key="index"
  293. :label="item.teacherName"
  294. :value="item.teacherId"
  295. >
  296. </el-option>
  297. </el-select>
  298. </el-form-item>
  299. <el-form-item label="节封面" prop="coverUrl">
  300. <el-row :gutter="10" style="margin-bottom: 10px">
  301. <el-col :span="12">
  302. <div
  303. style="
  304. width: 100%;
  305. height: 150px;
  306. border: 2px dashed #999;
  307. border-radius: 28px;
  308. line-height: 150px;
  309. text-align: center;
  310. "
  311. v-if="!listData.coverUrl"
  312. >
  313. <label for="uplose">
  314. <i class="el-icon-circle-plus-outline iconStsz"></i
  315. ></label>
  316. <input
  317. ref="file"
  318. type="file"
  319. style="display: none"
  320. id="uplose"
  321. @change="getImgFile"
  322. />
  323. </div>
  324. <el-image
  325. v-else
  326. style="width: 100%"
  327. :src="$methodsTools.splitImgHost(listData.coverUrl)"
  328. :preview-src-list="[
  329. $methodsTools.splitImgHost(listData.coverUrl),
  330. ]"
  331. >
  332. </el-image>
  333. </el-col>
  334. <el-col :span="11">
  335. <span style="color: #999; font-size: 14px"
  336. >注:请上传小于300kb,尺寸为750*440的图片,支持gif、jpg、jpeg、png等类型</span
  337. >
  338. </el-col>
  339. </el-row>
  340. <el-button
  341. v-if="listData.coverUrl"
  342. type="danger"
  343. size="mini"
  344. class="margin-top: 20px;"
  345. @click="clearImgs"
  346. >删除</el-button
  347. >
  348. </el-form-item>
  349. <el-form-item label="是否发布" prop="publishStatus">
  350. <el-radio-group v-model="listData.publishStatus">
  351. <el-radio :label="1">是</el-radio>
  352. <el-radio :label="0">否</el-radio>
  353. </el-radio-group>
  354. </el-form-item>
  355. <el-form-item>
  356. <el-button @click="backPage">取消</el-button>
  357. <el-button
  358. type="primary"
  359. @click="submit('listData')"
  360. :disabled="listData.sectionType === 1 ? !noStudent : false"
  361. :loading="disabledBtn"
  362. >确定</el-button
  363. >
  364. </el-form-item>
  365. </el-form>
  366. </div>
  367. <el-dialog
  368. :visible.sync="diavos"
  369. width="840px"
  370. @opened="isOkBf"
  371. :show-close="false"
  372. :close-on-click-modal="false"
  373. >
  374. <div slot="title" class="hearders">
  375. <div class="leftTitle">视频预览</div>
  376. <div class="rightBoxs">
  377. <img src="@/assets/images/Close@2x.png" alt="" @click="clears" />
  378. </div>
  379. </div>
  380. <div>
  381. <div id="player"></div>
  382. </div>
  383. <span slot="footer" class="dialog-footer">
  384. <el-button @click="clears">取 消</el-button>
  385. </span>
  386. </el-dialog>
  387. <el-dialog
  388. :visible.sync="diavoszb"
  389. width="840px"
  390. @opened="isOkBfzb"
  391. :show-close="false"
  392. :close-on-click-modal="false"
  393. >
  394. <div slot="title" class="hearders">
  395. <div class="leftTitle">直播预览</div>
  396. <div class="rightBoxs">
  397. <img src="@/assets/images/Close@2x.png" alt="" @click="clearszb" />
  398. </div>
  399. </div>
  400. <div>
  401. <div id="playerzb"></div>
  402. </div>
  403. <span slot="footer" class="dialog-footer">
  404. <el-button @click="clearszb">取 消</el-button>
  405. </span>
  406. </el-dialog>
  407. </div>
  408. </template>
  409. <script>
  410. import { returnTitle } from "@/utils/polyvError.js";
  411. import { uploadFile } from "@/utils/uopladFile.js";
  412. export default {
  413. name: "FestivalEdit",
  414. data() {
  415. return {
  416. disabledBtn: false,
  417. isIndeterminate: false,
  418. checkAll: false,
  419. vodPlayerJs: "https://player.polyv.net/script/player.js",
  420. vid: "",
  421. playerJs:
  422. "https://player.polyv.net/resp/live-h5-player/latest/liveplayer.min.js",
  423. uidzb: "egsxlptzdq",
  424. vidzb: "",
  425. diavos: false,
  426. diavoszb: false,
  427. fileSetting: {
  428. desc: "i am desc", // 描述
  429. cataid: "1639399775001", // 分类ID 可以后端传递 也可以不写 或写死
  430. tag: "i am tag", // 标签
  431. luping: 0, // 是否开启视频课件优化处理,对于上传录屏类视频清晰度有所优化:0为不开启,1为开启
  432. keepsource: 1, // 是否源文件播放(不对视频进行编码):0为编码,1为不编码
  433. },
  434. sectionTypeOptions: [
  435. {
  436. label: "录播",
  437. value: 1,
  438. },
  439. {
  440. label: "直播",
  441. value: 2,
  442. },
  443. {
  444. label: "回放",
  445. value: 3,
  446. },
  447. ],
  448. // 弹窗数据
  449. changeHeight: true,
  450. bfImg: "oss/images/avatar/20211013/1634097664410_1397766697",
  451. listData: {
  452. recordingUrl: "",
  453. liveUrl: "",
  454. coverUrl: "oss/images/avatar/20211013/1634097664410_1397766697",
  455. },
  456. newActiveLiveUrl: "",
  457. newLiveUrl: [], //直播地址
  458. newActiveRecordingUrl1: "",
  459. newSteamUrl1: [], //录播流地址
  460. newActiveRecordingUrl2: "",
  461. newSteamUrl2: [], //回放流地址
  462. eduTypeOptions: [], //教育类型数据
  463. projectTypeOptions: [], //项目类型数据
  464. courTypeOptions: [], //业务层次数据
  465. newCourTypeOptions: [], //当前业务层次数据
  466. sujectOption: [], //科目数据
  467. newSujectOption: [], //当前科目数据数据
  468. eduType: "", //当前选中教育类型
  469. courType: "", //当前选中业务层次
  470. sujectApis: [], //当前存在的科目
  471. newSujectApis: [],
  472. sujectArray: [], //选中的科目
  473. teacherList: [], //教师列表
  474. noStudent: true,
  475. disabloutime: false,
  476. typeSection: "", //备份节类型
  477. //表单验证
  478. rules: {
  479. prefixName: [
  480. { required: true, message: "请输入标题前缀", trigger: "blur" },
  481. ],
  482. name: [{ required: true, message: "请输入节标题", trigger: "blur" }],
  483. // liveDuration: [
  484. // { required: true, message: "节时长不能为空" },
  485. // { type: "number", message: "节时长必须为数字值" },
  486. // ],
  487. recordingUrl: [
  488. {
  489. required: true,
  490. message: "请输入URL地址",
  491. trigger: ["blur", "change"],
  492. },
  493. ],
  494. durationTime: [
  495. { required: true, message: "请选择节时长", trigger: "change" },
  496. ],
  497. liveUrl: [
  498. {
  499. required: true,
  500. message: "请输入频道号",
  501. trigger: ["blur", "change"],
  502. },
  503. ],
  504. liveStartTime: [
  505. { required: true, message: "请选择直播开始时间", trigger: "change" },
  506. ],
  507. liveEndTime: [
  508. { required: true, message: "请选择直播结束时间", trigger: "change" },
  509. ],
  510. teacherId: [
  511. { required: true, message: "请选择讲师", trigger: "change" },
  512. ],
  513. publishStatus: [
  514. { required: true, message: "请选择是否发布", trigger: "change" },
  515. ],
  516. coverUrl: [
  517. { required: true, message: "请上传封面", trigger: "change" },
  518. ],
  519. },
  520. pageId: this.$route.query.id,
  521. };
  522. },
  523. watch: {
  524. sujectApis: {
  525. immediate: true,
  526. handler(newName, oldName) {
  527. this.changeTypes();
  528. },
  529. },
  530. },
  531. mounted() {
  532. this.$modal.loading("正在导入数据,请稍后...");
  533. this.$api.gradecheckGoodsChange({ sectionId: this.pageId }).then((res) => {
  534. if (res.data > 0) {
  535. // this.noStudent = false;
  536. }
  537. });
  538. this.getDict();
  539. },
  540. methods: {
  541. /**
  542. * 复选框点击触发
  543. */
  544. handleCheckedCitiesChange() {
  545. let nid = this.newSujectOption.map((item) => {
  546. return item.newId;
  547. });
  548. this.checkAll = this.sujectArray.length === nid.length;
  549. this.isIndeterminate =
  550. this.sujectArray.length > 0 && this.sujectArray.length < nid.length;
  551. },
  552. setFunc(arr) {
  553. var arrays = [];
  554. for (let i = 0; i < arr.length; i++) {
  555. if (!arrays.includes(arr[i])) {
  556. arrays.push(arr[i]);
  557. }
  558. }
  559. return arrays;
  560. },
  561. /**
  562. *
  563. * @param {Arrays} val 复选框数据
  564. * @remards 复选框全选触发
  565. */
  566. handleCheckAllChange(val) {
  567. if (val) {
  568. let nid = this.newSujectOption.map((item) => {
  569. return item.newId;
  570. });
  571. let arrays = this.sujectArray.concat(nid);
  572. this.sujectArray = this.setFunc(arrays);
  573. this.isIndeterminate = false;
  574. } else {
  575. let nid = this.newSujectOption.map((item) => {
  576. return item.newId;
  577. });
  578. let newArr = [];
  579. this.sujectArray.forEach((item) => {
  580. if (!nid.includes(item)) {
  581. newArr.push(item);
  582. }
  583. });
  584. this.sujectArray = newArr;
  585. this.isIndeterminate = false;
  586. }
  587. },
  588. /**
  589. * 自动计算直播时长
  590. */
  591. compTimeOUT(start, end) {
  592. if (start && end) {
  593. if (end < start) {
  594. return "请检查开始与结束的时间范围";
  595. }
  596. const asTimes = end / 1000 - start / 1000;
  597. return this.$methodsTools.secondToDate(asTimes, false);
  598. } else {
  599. return "未检测到直播开始时间结束时间,无法计算!";
  600. }
  601. },
  602. changeTypeSection(val) {
  603. if (val === 3) {
  604. this.listData.durationTime = "";
  605. this.disabloutime = false;
  606. }
  607. this.$nextTick(() => {
  608. this.$refs.listData.clearValidate();
  609. });
  610. },
  611. clearTimes(val) {
  612. if (!val) {
  613. this.listData.durationTime = "";
  614. this.disabloutime = false;
  615. return;
  616. }
  617. },
  618. getApiTime(val) {
  619. var self = this;
  620. this.clearTimes(val);
  621. const valueUrl = val.replace(/\s/g, "");
  622. if (valueUrl && valueUrl.length > 30) {
  623. this.$api
  624. .inquirepolyvvideo(valueUrl)
  625. .then((res) => {
  626. if (res.data.duration) {
  627. self.listData.durationTime = res.data.duration;
  628. self.disabloutime = true;
  629. } else {
  630. self.disabloutime = false;
  631. }
  632. })
  633. .catch((err) => {
  634. self.disabloutime = false;
  635. });
  636. }
  637. },
  638. loadPlayerScript(callback) {
  639. if (!window.polyvPlayer) {
  640. const myScript = document.createElement("script");
  641. myScript.setAttribute("src", this.vodPlayerJs);
  642. myScript.onload = callback;
  643. document.body.appendChild(myScript);
  644. } else {
  645. callback();
  646. this.player.on("serverError", (...params) => {
  647. this.$message.error(returnTitle(params[1]));
  648. });
  649. }
  650. },
  651. loadPlayer() {
  652. var self = this;
  653. const polyvPlayer = window.polyvPlayer;
  654. self.player = polyvPlayer({
  655. wrap: "#player",
  656. width: 800,
  657. height: 533,
  658. vid: self.vid,
  659. teaser_show: 0,
  660. playsafe: function (vid, next) {
  661. self.$api.obtainpolyvvideosign(vid).then((res) => {
  662. next(res.data);
  663. });
  664. },
  665. });
  666. },
  667. /**
  668. * @param {String} 关闭视频窗口-销毁实例
  669. */
  670. clears() {
  671. this.diavos = false;
  672. if (this.player) {
  673. this.player.destroy();
  674. }
  675. },
  676. /**
  677. * @param {String} 视频查看
  678. */
  679. watchVideo(url) {
  680. if (!url) {
  681. this.$message.warning("请检查URL地址是否输入完整");
  682. return;
  683. }
  684. this.vid = url;
  685. this.diavos = true;
  686. },
  687. isOkBf() {
  688. this.loadPlayerScript(this.loadPlayer);
  689. },
  690. /**
  691. * @param {String} 直播预览
  692. */
  693. watchZbVideo(url) {
  694. if (!url) {
  695. this.$message.warning("请检查直播流地址是否输入完整");
  696. return;
  697. }
  698. this.vidzb = url;
  699. this.diavoszb = true;
  700. },
  701. loadPlayerScriptzb(callback) {
  702. if (!window.polyvLivePlayer) {
  703. const myScript = document.createElement("script");
  704. myScript.setAttribute("src", this.playerJs);
  705. myScript.onload = callback;
  706. document.body.appendChild(myScript);
  707. } else {
  708. callback();
  709. }
  710. },
  711. loadPlayerzb() {
  712. const polyvLivePlayer = window.polyvLivePlayer;
  713. this.playerzb = polyvLivePlayer({
  714. wrap: "#playerzb",
  715. width: 800,
  716. height: 533,
  717. uid: this.uidzb,
  718. vid: this.vidzb,
  719. });
  720. },
  721. clearszb() {
  722. this.diavoszb = false;
  723. if (this.playerzb) {
  724. this.playerzb.destroy();
  725. }
  726. },
  727. isOkBfzb() {
  728. this.loadPlayerScriptzb(this.loadPlayerzb);
  729. },
  730. /**上传视频 */
  731. importMoble(event) {
  732. var file = event.target.files[0];
  733. if (!event.target.value) {
  734. this.$message.error("请选择您要上传的文件");
  735. return false;
  736. }
  737. /**
  738. * @param: event.target.files -> 传递的文件list
  739. * @param: this.fileSetting -> 常规配置 上面有备注
  740. * @param: 回调
  741. */
  742. uploadFile(file, this.fileSetting, (event) => {
  743. this.listData.recordingUrl = event.vid;
  744. this.listData.durationTime = "";
  745. this.getApiTime(event.vid);
  746. });
  747. },
  748. getMessage() {
  749. if (!this.courType) {
  750. this.$message.warning("请先选择业务层级");
  751. }
  752. },
  753. search() {
  754. this.$api
  755. .obtainCourseSection(this.pageId)
  756. .then((res) => {
  757. this.bfImg = res.data.coverUrl;
  758. if (res.data.sectionType === 2) {
  759. res.data.liveStartTime = this.$methodsTools.time10to13(
  760. res.data.liveStartTime,
  761. 2
  762. );
  763. res.data.liveEndTime = this.$methodsTools.time10to13(
  764. res.data.liveEndTime,
  765. 2
  766. );
  767. }
  768. res.data.durationTime = this.$methodsTools.secondToDate(
  769. res.data.durationTime,
  770. false
  771. );
  772. if (res.data.durationTime) {
  773. this.disabloutime = true;
  774. }
  775. this.typeSection = res.data.sectionType;
  776. this.listData = JSON.parse(JSON.stringify(res.data));
  777. this.$api.obtaincourseSectionbusiness(this.pageId).then((result) => {
  778. var arrays = [];
  779. result.data.map((item) => {
  780. arrays.push(item.businessId + "-" + item.subjectId);
  781. });
  782. this.sujectApis = arrays;
  783. });
  784. })
  785. .finally(() => {
  786. this.$modal.closeLoading();
  787. });
  788. },
  789. clearImgs() {
  790. this.listData.coverUrl = "";
  791. this.$refs.listData.validateField("coverUrl");
  792. },
  793. changeTypes() {
  794. var self = this;
  795. var arrays = [];
  796. this.sujectApis.map((item, index) => {
  797. this.courTypeOptions.map((items) => {
  798. if (items.id === item.split("-").map(Number)[0]) {
  799. var obj = {
  800. educationTypeId: items.educationId,
  801. educationName: items.educationName,
  802. projectId: items.projectId,
  803. projectName: items.projectName,
  804. businessId: items.id,
  805. businessName: items.businessName,
  806. };
  807. self.sujectOption.map((i) => {
  808. if (
  809. i.id === item.split("-").map(Number)[1] &&
  810. i.courseArrays.indexOf(items.projectId) !== -1
  811. ) {
  812. obj.subjectName = i.subjectName;
  813. obj.subjectId = i.id;
  814. }
  815. });
  816. arrays.push(obj);
  817. }
  818. });
  819. });
  820. this.newSujectApis = arrays;
  821. },
  822. changeType() {
  823. this.changeHeight = !this.changeHeight;
  824. },
  825. submitSujectArray() {
  826. var self = this;
  827. this.sujectApis = this.sujectApis.filter((item, index) => {
  828. return item.split("-").map(Number)[0] !== Number(self.courType);
  829. });
  830. for (let i = 0; i < this.sujectArray.length; i++) {
  831. this.sujectApis.push(this.sujectArray[i]);
  832. }
  833. this.$refs.popovers.doClose();
  834. this.$nextTick(() => {
  835. this.changeUrl();
  836. });
  837. },
  838. changeUrl() {
  839. var arr = this.newSujectApis.map((val) => val.businessId);
  840. const unique = [...new Set(arr)];
  841. var busId = "";
  842. if (unique.length) {
  843. busId = unique.toString();
  844. } else {
  845. busId = "";
  846. }
  847. this.$api.inquireCourseStreaming({ status: 1 }).then((res) => {
  848. var arraystt = [];
  849. var newarrays1tt = [];
  850. var newarrays2tt = [];
  851. res.rows.map((item) => {
  852. if (item.streamingType === 1) {
  853. arraystt.push(item);
  854. }
  855. if (item.streamingType === 2) {
  856. newarrays1tt.push(item);
  857. }
  858. if (item.streamingType === 3) {
  859. newarrays2tt.push(item);
  860. }
  861. });
  862. this.$api
  863. .inquireCourseStreaming({ status: 1, businessId: busId })
  864. .then((result) => {
  865. var arrays = [];
  866. var newarrays1 = [];
  867. var newarrays2 = [];
  868. result.rows.map((item) => {
  869. if (item.streamingType === 1) {
  870. arrays.push(item);
  871. }
  872. if (item.streamingType === 2) {
  873. newarrays1.push(item);
  874. }
  875. if (item.streamingType === 3) {
  876. newarrays2.push(item);
  877. }
  878. });
  879. if (arrays.length) {
  880. this.newLiveUrl = arrays;
  881. } else {
  882. this.newLiveUrl = arraystt;
  883. }
  884. if (newarrays1.length) {
  885. this.newSteamUrl1 = newarrays1;
  886. } else {
  887. this.newSteamUrl1 = newarrays1tt;
  888. }
  889. if (newarrays2.length) {
  890. this.newSteamUrl2 = newarrays2;
  891. } else {
  892. this.newSteamUrl2 = newarrays2tt;
  893. }
  894. });
  895. });
  896. },
  897. showHandle() {
  898. var array = [];
  899. for (let i = 0; i < this.sujectApis.length; i++) {
  900. if (
  901. this.sujectApis[i].split("-").map(Number)[0] === Number(this.courType)
  902. ) {
  903. array.push(this.sujectApis[i]);
  904. }
  905. }
  906. this.sujectArray = array;
  907. if (!this.newSujectOption.length) {
  908. this.$message.warning("该业务层次暂无关联科目");
  909. this.$refs.popovers.doClose();
  910. return;
  911. }
  912. this.newSujectOption.map((item) => {
  913. item.newId = this.courType + "-" + item.id;
  914. });
  915. this.handleCheckedCitiesChange();
  916. },
  917. hideHandle() {},
  918. async getDict() {
  919. await this.tearchApi();
  920. await this.eduTys();
  921. await this.courseTys();
  922. await this.businTys();
  923. await this.courseSubject();
  924. await this.Streaming();
  925. this.search();
  926. },
  927. tearchApi() {
  928. return new Promise((resolve, reject) => {
  929. this.$api.inquiresystemteacherlist({ status: 1 }).then((res) => {
  930. this.teacherList = res.rows;
  931. resolve();
  932. });
  933. });
  934. },
  935. eduTys() {
  936. return new Promise((resolve, reject) => {
  937. this.$api.inquireCourseEducationType({ status: 1 }).then((res) => {
  938. this.eduTypeOptions = res.rows;
  939. resolve();
  940. });
  941. });
  942. },
  943. courseTys() {
  944. return new Promise((resolve, reject) => {
  945. this.$api.inquireCourseProjectType({ status: 1 }).then((res) => {
  946. this.projectTypeOptions = res.rows;
  947. resolve();
  948. });
  949. });
  950. },
  951. businTys() {
  952. return new Promise((resolve, reject) => {
  953. this.$api.inquirebusinessList({ status: 1 }).then((res) => {
  954. this.courTypeOptions = res.rows;
  955. this.newCourTypeOptions = res.rows;
  956. resolve();
  957. });
  958. });
  959. },
  960. courseSubject() {
  961. return new Promise((resolve, reject) => {
  962. this.$api.inquireCourseSubject({ status: 1 }).then((res) => {
  963. res.rows.map((item, index) => {
  964. var array = [];
  965. item.courseProjectTypes.map((items, indexs) => {
  966. array.push(items.id);
  967. });
  968. item.courseArrays = array;
  969. });
  970. this.sujectOption = res.rows;
  971. resolve();
  972. });
  973. });
  974. },
  975. Streaming() {
  976. return new Promise((resolve, reject) => {
  977. this.$api.inquireCourseStreaming({ status: 1 }).then((res) => {
  978. var arrays = [];
  979. var newarrays1 = [];
  980. var newarrays2 = [];
  981. res.rows.map((item) => {
  982. if (item.streamingType === 1) {
  983. arrays.push(item);
  984. }
  985. if (item.streamingType === 2) {
  986. newarrays1.push(item);
  987. }
  988. if (item.streamingType === 3) {
  989. newarrays2.push(item);
  990. }
  991. });
  992. this.newLiveUrl = arrays;
  993. this.newSteamUrl1 = newarrays1;
  994. this.newSteamUrl2 = newarrays2;
  995. resolve();
  996. });
  997. });
  998. },
  999. changeEduType() {
  1000. if (!(this.courType === undefined || this.courType === "")) {
  1001. this.courType = "";
  1002. }
  1003. var arrays = [];
  1004. this.courTypeOptions.map((item) => {
  1005. if (item.educationId === this.eduType) {
  1006. arrays.push(item);
  1007. }
  1008. });
  1009. this.newCourTypeOptions = arrays;
  1010. },
  1011. changecourseType() {
  1012. this.newCourTypeOptions.map((item, index) => {
  1013. if (item.id === this.courType) {
  1014. this.eduType = item.educationId;
  1015. var array = [];
  1016. this.sujectOption.map((items, indexs) => {
  1017. if (items.courseArrays.indexOf(item.projectId) !== -1) {
  1018. array.push(items);
  1019. }
  1020. });
  1021. this.newSujectOption = array;
  1022. }
  1023. });
  1024. var arrays = [];
  1025. this.courTypeOptions.map((item) => {
  1026. if (item.educationId === this.eduType) {
  1027. arrays.push(item);
  1028. }
  1029. });
  1030. this.newCourTypeOptions = arrays;
  1031. this.$refs.popovers.doClose();
  1032. },
  1033. submit(formName) {
  1034. this.$refs[formName].validate((valid) => {
  1035. if (valid) {
  1036. if (!this.newSujectApis.length) {
  1037. this.$message.error("请选择适用业务层级");
  1038. return;
  1039. }
  1040. // if (
  1041. // this.listData.coverUrl === "" ||
  1042. // this.listData.coverUrl === null ||
  1043. // this.listData.coverUrl === undefined
  1044. // ) {
  1045. // this.$message.error("请上传节封面");
  1046. // return false;
  1047. // }
  1048. this.rulesTableSumbit();
  1049. } else {
  1050. return false;
  1051. }
  1052. });
  1053. },
  1054. async rulesTableSumbit() {
  1055. this.disabledBtn = true;
  1056. var dataInfos = {
  1057. status: 1,
  1058. sectionId: this.pageId,
  1059. businessList: this.newSujectApis,
  1060. coverUrl: this.listData.coverUrl,
  1061. name: this.listData.name,
  1062. prefixName: this.listData.prefixName,
  1063. publishStatus: this.listData.publishStatus,
  1064. teacherId: this.listData.teacherId,
  1065. };
  1066. if (this.listData.sectionType === 2) {
  1067. dataInfos.sectionType = 2;
  1068. dataInfos.liveUrl = this.listData.liveUrl;
  1069. dataInfos.liveStartTime = this.$methodsTools.time10to13(
  1070. this.listData.liveStartTime,
  1071. 1
  1072. );
  1073. dataInfos.liveEndTime = this.$methodsTools.time10to13(
  1074. this.listData.liveEndTime,
  1075. 1
  1076. );
  1077. if (
  1078. dataInfos.liveStartTime &&
  1079. dataInfos.liveEndTime &&
  1080. dataInfos.liveEndTime < dataInfos.liveStartTime
  1081. ) {
  1082. this.$message.warning("请检查直播开始与结束时间范围");
  1083. this.disabledBtn = false;
  1084. return;
  1085. }
  1086. dataInfos.durationTime =
  1087. dataInfos.liveEndTime - dataInfos.liveStartTime;
  1088. }
  1089. if (this.listData.sectionType === 1) {
  1090. dataInfos.sectionType = 1;
  1091. dataInfos.recordingUrl = this.listData.recordingUrl;
  1092. dataInfos.durationTime = this.$methodsTools.secondFormDate(
  1093. this.listData.durationTime
  1094. );
  1095. }
  1096. if (this.listData.sectionType === 3) {
  1097. dataInfos.sectionType = 3;
  1098. dataInfos.recordingUrl = this.listData.recordingUrl;
  1099. dataInfos.durationTime = this.$methodsTools.secondFormDate(
  1100. this.listData.durationTime
  1101. );
  1102. }
  1103. this.$api
  1104. .editCourseSection(dataInfos)
  1105. .then((res) => {
  1106. this.$message.success("修改成功");
  1107. setTimeout(() => {
  1108. this.$store
  1109. .dispatch("tagsView/exitView", this.$route)
  1110. .then((res) => {
  1111. if (this.$store.getters.festivalPage) {
  1112. this.$router.push({
  1113. path: this.$store.getters.festivalPage.name,
  1114. });
  1115. } else {
  1116. this.$router.push({
  1117. path: "festival",
  1118. });
  1119. }
  1120. });
  1121. }, 500);
  1122. })
  1123. .catch(() => {
  1124. this.disabledBtn = false;
  1125. });
  1126. },
  1127. backPage() {
  1128. this.$store.dispatch("tagsView/delView", this.$route).then((res) => {
  1129. if (this.$store.getters.festivalPage) {
  1130. this.$router.push({
  1131. path: this.$store.getters.festivalPage.name,
  1132. });
  1133. } else {
  1134. this.$router.push({
  1135. path: "festival",
  1136. });
  1137. }
  1138. });
  1139. },
  1140. closeType(index) {
  1141. this.sujectApis.splice(index, 1);
  1142. this.$nextTick(() => {
  1143. this.changeUrl();
  1144. });
  1145. },
  1146. changeLiveUrl() {
  1147. this.newLiveUrl.map((item) => {
  1148. if (item.id === this.newActiveLiveUrl) {
  1149. this.listData.liveUrl = item.liveUrl;
  1150. }
  1151. });
  1152. this.newActiveLiveUrl = "";
  1153. },
  1154. changeRecordingUrl1() {
  1155. this.newSteamUrl1.map((item) => {
  1156. if (item.id === this.newActiveRecordingUrl1) {
  1157. this.listData.recordingUrl = item.recordingVideoId;
  1158. this.getApiTime(item.recordingVideoId);
  1159. }
  1160. });
  1161. this.newActiveRecordingUrl1 = "";
  1162. },
  1163. changeRecordingUrl2() {
  1164. this.newSteamUrl2.map((item) => {
  1165. if (item.id === this.newActiveRecordingUrl2) {
  1166. this.listData.recordingUrl = item.playbackUrl;
  1167. this.getApiTime(item.recordingVideoId);
  1168. }
  1169. });
  1170. this.newActiveRecordingUrl2 = "";
  1171. },
  1172. getImgFile() {
  1173. var self = this;
  1174. var file = self.$refs.file.files[0];
  1175. if (file === undefined) {
  1176. self.$set(self.listData, "coverUrl", "");
  1177. return;
  1178. }
  1179. if (file.size > 0.3 * 1024 * 1024) {
  1180. self.$message.error("图片不得大于300kb");
  1181. return;
  1182. }
  1183. var type = self.$refs.file.value.toLowerCase().split(".").splice(-1);
  1184. if (
  1185. type[0] != "jpg" &&
  1186. type[0] != "png" &&
  1187. type[0] != "jpeg" &&
  1188. type[0] != "gif"
  1189. ) {
  1190. self.$message.error("上传格式需为:.jpg/.png/.jpeg/gif");
  1191. self.$refs.file.value = "";
  1192. return;
  1193. }
  1194. this.$upload.upload(file, 0).then((res) => {
  1195. self.listData.coverUrl = res;
  1196. self.$refs.listData.validateField("coverUrl");
  1197. });
  1198. },
  1199. },
  1200. };
  1201. </script>
  1202. <style lang="less" scoped>
  1203. /deep/.el-button {
  1204. border-radius: 8px;
  1205. }
  1206. /deep/.el-dialog {
  1207. border-radius: 8px;
  1208. .el-dialog__header {
  1209. padding: 0;
  1210. .hearders {
  1211. height: 40px;
  1212. display: flex;
  1213. align-items: center;
  1214. justify-content: space-between;
  1215. padding: 0px 18px 0px 20px;
  1216. border-bottom: 1px solid #e2e2e2;
  1217. .leftTitle {
  1218. font-size: 14px;
  1219. font-weight: bold;
  1220. color: #2f4378;
  1221. }
  1222. .rightBoxs {
  1223. display: flex;
  1224. align-items: center;
  1225. img {
  1226. width: 14px;
  1227. height: 14px;
  1228. margin-left: 13px;
  1229. cursor: pointer;
  1230. }
  1231. }
  1232. }
  1233. }
  1234. .el-dialog__footer {
  1235. padding: 0;
  1236. .dialog-footer {
  1237. padding: 0px 40px;
  1238. height: 70px;
  1239. border-top: 1px solid #e2e2e2;
  1240. display: flex;
  1241. align-items: center;
  1242. justify-content: flex-end;
  1243. }
  1244. }
  1245. }
  1246. .imgBox {
  1247. width: 100%;
  1248. // height: 210px;
  1249. border: 1px solid #e2e2e2;
  1250. border-radius: 8px;
  1251. padding: 8px 8px 3px;
  1252. display: flex;
  1253. flex-direction: column;
  1254. align-items: center;
  1255. .imgLabel {
  1256. flex: 1;
  1257. width: 100%;
  1258. border: 1px dotted #e2e2e2;
  1259. color: #999;
  1260. font-size: 14px;
  1261. cursor: pointer;
  1262. border-radius: 8px;
  1263. .msPhoto {
  1264. display: flex;
  1265. justify-content: center;
  1266. align-items: center;
  1267. max-width: 100%;
  1268. max-height: 270px;
  1269. img {
  1270. max-width: 100%;
  1271. max-height: 270px;
  1272. }
  1273. }
  1274. .imgbbx {
  1275. display: flex;
  1276. flex-direction: column;
  1277. align-items: center;
  1278. justify-content: center;
  1279. width: 100%;
  1280. height: 100%;
  1281. i {
  1282. font-weight: bold;
  1283. margin: 14px 0;
  1284. font-size: 24px;
  1285. }
  1286. }
  1287. }
  1288. p {
  1289. margin: 5px 0px;
  1290. }
  1291. }
  1292. .boxWidth {
  1293. width: 770px;
  1294. }
  1295. .numInputs {
  1296. width: 150px;
  1297. }
  1298. .checkboxSty {
  1299. max-height: 210px;
  1300. overflow: auto;
  1301. display: flex;
  1302. flex-direction: column;
  1303. }
  1304. .listBoxStys {
  1305. flex-shrink: 0;
  1306. padding: 0px 10px;
  1307. border-radius: 8px;
  1308. border: 1px solid #eee;
  1309. margin-right: 10px;
  1310. margin-bottom: 6px;
  1311. }
  1312. .closeIcons {
  1313. color: red;
  1314. cursor: pointer;
  1315. margin-left: 6px;
  1316. }
  1317. .ach {
  1318. display: flex;
  1319. align-items: center;
  1320. overflow: hidden;
  1321. }
  1322. .clh {
  1323. display: flex;
  1324. align-items: center;
  1325. flex-wrap: wrap;
  1326. }
  1327. .imgBoxins {
  1328. width: 375px;
  1329. height: 220px;
  1330. text-align: center;
  1331. img {
  1332. height: 100%;
  1333. }
  1334. }
  1335. .iconStsz {
  1336. font-size: 40px;
  1337. color: #67c23a;
  1338. cursor: pointer;
  1339. }
  1340. </style>