addSection.vue 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406
  1. <template>
  2. <div id="addSection">
  3. <el-dialog
  4. :visible.sync="dialogVisible"
  5. width="900px"
  6. :show-close="false"
  7. :close-on-click-modal="false"
  8. >
  9. <div slot="title" class="hearders">
  10. <div class="leftTitle">添加节</div>
  11. <div class="rightBoxs">
  12. <img
  13. src="@/assets/images/Close@2x.png"
  14. alt=""
  15. @click="dialogVisible = false"
  16. />
  17. </div>
  18. </div>
  19. <div>
  20. <p>
  21. <el-button :size="size" type="primary" @click="addChapterList"
  22. >添加</el-button
  23. >
  24. </p>
  25. <div class="heightMax">
  26. <div v-for="(item, index) in list" :key="index">
  27. <el-form
  28. label-width="130px"
  29. class="elform_style"
  30. :ref="`listRulesList${index}`"
  31. :model="list[index]"
  32. :rules="rules"
  33. >
  34. <div class="left_box">
  35. <el-form-item label="标题前缀">
  36. <el-input v-model="item.prefixName"></el-input>
  37. <p class="p_style">注:便于检索、归类,以及区分一样的标题</p>
  38. </el-form-item>
  39. <el-form-item label="节标题" prop="name">
  40. <el-input v-model="item.name"></el-input>
  41. <p class="p_style">
  42. 注:请尽量规范易懂,方便在课程目录表呈现给学员
  43. </p>
  44. </el-form-item>
  45. <el-form-item label="节类型" prop="sectionType">
  46. <el-select
  47. clearable
  48. v-model="item.sectionType"
  49. placeholder="请选择节类型"
  50. @change="changesType(index, $event)"
  51. >
  52. <el-option
  53. v-for="(items, indexs) in sectionTypeOptions"
  54. :key="indexs"
  55. :label="items.label"
  56. :value="items.value"
  57. >
  58. </el-option>
  59. </el-select>
  60. </el-form-item>
  61. <el-form-item
  62. v-if="item.sectionType"
  63. :label="item.sectionType === 1 ? 'URL地址' : '频道号'"
  64. prop="url"
  65. >
  66. <el-input
  67. v-model="item.url"
  68. @blur="
  69. item.sectionType === 1 ? getUrlTime(index, $event) : ''
  70. "
  71. ><el-button :disabled="item.url.length <= 0" slot="append" @click="seeTheVideoFunc(item)">预览</el-button></el-input>
  72. </el-form-item>
  73. <div v-if="item.sectionType === 1">
  74. <el-form-item label="节时长" prop="durationTime">
  75. <el-time-picker
  76. value-format="HH:mm:ss"
  77. range-separator=":"
  78. v-model="item.durationTime"
  79. placeholder="请填入节时长"
  80. :disabled="item.disabled"
  81. >
  82. </el-time-picker>
  83. </el-form-item>
  84. </div>
  85. <div v-if="item.sectionType === 2">
  86. <el-form-item label="直播开始时间" prop="liveStartTime">
  87. <el-date-picker
  88. v-model="item.liveStartTime"
  89. type="datetime"
  90. placeholder="请选择直播开始时间"
  91. value-format="timestamp"
  92. @change="changeStartTime(index, $event)"
  93. >
  94. </el-date-picker>
  95. </el-form-item>
  96. <el-form-item label="直播结束时间" prop="liveEndTime">
  97. <el-date-picker
  98. v-model="item.liveEndTime"
  99. type="datetime"
  100. placeholder="请选择直播结束时间"
  101. value-format="timestamp"
  102. @change="changeEndTime(index, $event)"
  103. >
  104. </el-date-picker>
  105. </el-form-item>
  106. <el-form-item
  107. label="直播时长"
  108. v-if="item.liveStartTime && item.liveEndTime"
  109. >
  110. {{ compTimeOUT(item.liveStartTime, item.liveEndTime) }}
  111. </el-form-item>
  112. </div>
  113. <el-form-item
  114. label="讲师"
  115. prop="teacherId"
  116. :rules="[
  117. {
  118. required: item.sectionType === 2 ? true : false,
  119. message: '请选择讲师',
  120. trigger: 'change',
  121. },
  122. ]"
  123. >
  124. <el-select
  125. clearable
  126. v-model="item.teacherId"
  127. placeholder="请选择讲师"
  128. >
  129. <el-option
  130. v-for="(items, indexs) in teacherList"
  131. :key="indexs"
  132. :label="items.teacherName"
  133. :value="items.teacherId"
  134. >
  135. </el-option>
  136. </el-select>
  137. </el-form-item>
  138. </div>
  139. <div class="clear_style">
  140. <el-button :size="size" @click="list.splice(index, 1)"
  141. >删除</el-button
  142. >
  143. </div></el-form
  144. >
  145. </div>
  146. </div>
  147. </div>
  148. <span slot="footer" class="dialog-footer">
  149. <el-button @click="dialogVisible = false">取 消</el-button>
  150. <el-button type="primary" @click="submitForm" :disabled="!list.length"
  151. >确 定</el-button
  152. >
  153. </span>
  154. </el-dialog>
  155. </div>
  156. </template>
  157. <script>
  158. export default {
  159. data() {
  160. return {
  161. size: "small",
  162. dialogVisible: false,
  163. list: [],
  164. rules: {
  165. prefixName: [
  166. { required: true, message: "请输入标题前缀", trigger: "blur" },
  167. ],
  168. name: [{ required: true, message: "请输入节标题", trigger: "blur" }],
  169. sectionType: [
  170. { required: true, message: "请选择节类型", trigger: "change" },
  171. ],
  172. url: [
  173. { required: true, message: "请输入URL地址/频道号", trigger: "blur" },
  174. ],
  175. durationTime: [
  176. { required: true, message: "请选择节时长", trigger: "change" },
  177. ],
  178. liveStartTime: [
  179. { required: true, message: "请选择直播开始时间", trigger: "change" },
  180. ],
  181. liveEndTime: [
  182. { required: true, message: "请选择直播结束时间", trigger: "change" },
  183. ],
  184. },
  185. sectionTypeOptions: [
  186. {
  187. label: "录播",
  188. value: 1,
  189. },
  190. {
  191. label: "直播",
  192. value: 2,
  193. },
  194. ],
  195. };
  196. },
  197. mounted() {
  198. this.$api.inquiresystemteacherlist({ status: 1 }).then((res) => {
  199. this.teacherList = res.rows;
  200. });
  201. },
  202. computed: {
  203. /**
  204. * 自动计算直播时长
  205. */
  206. compTimeOUT: function () {
  207. return function (start, end) {
  208. if (start && end) {
  209. if (end < start) {
  210. return "请检查开始与结束的时间范围";
  211. }
  212. const asTimes = end / 1000 - start / 1000;
  213. return this.$methodsTools.secondToDate(asTimes, false);
  214. } else {
  215. return "未检测到直播开始时间结束时间,无法计算!";
  216. }
  217. };
  218. },
  219. },
  220. methods: {
  221. /**
  222. * 查找节时长
  223. */
  224. getUrlTime(index, value) {
  225. var self = this;
  226. let val = value.target.value;
  227. const valueUrl = val.replace(/\s/g, "");
  228. if (valueUrl && valueUrl.length > 30) {
  229. this.$api
  230. .inquirepolyvvideo(valueUrl)
  231. .then((res) => {
  232. if (res.data.duration) {
  233. this.$set(this.list[index], "durationTime", res.data.duration);
  234. this.$set(this.list[index], "disabled", true);
  235. this.$message.success("已自动录入节时长");
  236. } else {
  237. this.$set(this.list[index], "disabled", false);
  238. this.$message.error("查找不到该节时长,请手动输入节时长");
  239. }
  240. })
  241. .catch((err) => {
  242. this.$set(this.list[index], "disabled", false);
  243. });
  244. }
  245. },
  246. /**
  247. * 直播开始逻辑处理
  248. */
  249. changeStartTime(index, time) {
  250. if (this.list[index].liveEndTime && this.list[index].liveEndTime < time) {
  251. this.$set(this.list[index], "liveEndTime", "");
  252. this.$message.warning("直播开始时间不能大于直播结束时间");
  253. return;
  254. }
  255. },
  256. /**
  257. * 直播结束逻辑处理
  258. */
  259. changeEndTime(index, time) {
  260. if (
  261. this.list[index].liveStartTime &&
  262. this.list[index].liveStartTime > time
  263. ) {
  264. this.$set(this.list[index], "liveEndTime", "");
  265. this.$message.warning("直播结束时间不能小于直播开始时间");
  266. return;
  267. }
  268. },
  269. /**
  270. * 修改节类型需要处理的逻辑
  271. */
  272. changesType(index, val) {
  273. let ary = ["url", "durationTime", "liveStartTime", "liveEndTime"];
  274. for (let i = 0; i < ary.length; i++) {
  275. this.$set(this.list[index], ary[i], "");
  276. }
  277. },
  278. /**
  279. * 添加节
  280. */
  281. addChapterList() {
  282. this.list.push({ disabled: false });
  283. },
  284. /**
  285. * 打开页面触发函数
  286. */
  287. openBoxs(arr) {
  288. this.businList = JSON.parse(JSON.stringify(arr));
  289. this.list = [{}];
  290. this.dialogVisible = true;
  291. },
  292. /**
  293. * 表单校验
  294. */
  295. submitForm() {
  296. //用Promise.all进行全部form表单的验证
  297. Promise.all([
  298. //数组部分的表单,用map返回验证函数的调用
  299. ...this.list.map((item, index) =>
  300. this.validateForm(`listRulesList${index}`)
  301. ),
  302. ])
  303. .then((res) => {
  304. if (res) {
  305. // 全部表单验证通过
  306. this.submitForms();
  307. }
  308. })
  309. .catch(() => {
  310. this.$message.error("请检查必填项是否填写规范");
  311. });
  312. },
  313. validateForm(refs) {
  314. //获取到form表单的dom,如果是对象直接拿到,如果是数组,就拿第一个
  315. //elementui对循环的form包装成了数组
  316. let valiForm = this.$refs?.[refs].validate
  317. ? this.$refs?.[refs]
  318. : this.$refs?.[refs][0];
  319. return new Promise((resolve, reject) => {
  320. //在Promise里进行验证,如果通过就resolve()
  321. valiForm.validate((res) => {
  322. if (res) resolve();
  323. else reject();
  324. });
  325. });
  326. },
  327. /**
  328. * 通过验证提交逻辑
  329. */
  330. submitForms() {
  331. let ary = JSON.parse(JSON.stringify(this.list));
  332. ary.forEach((item) => {
  333. if (item.sectionType === 1) {
  334. item.recordingUrl = item.url;
  335. item.durationTime = this.$methodsTools.secondFormDate(
  336. item.durationTime
  337. );
  338. delete item.url;
  339. }
  340. if (item.sectionType === 2) {
  341. item.liveUrl = item.url;
  342. delete item.url;
  343. item.liveStartTime = this.$methodsTools.time10to13(
  344. item.liveStartTime,
  345. 1
  346. );
  347. item.liveEndTime = this.$methodsTools.time10to13(item.liveEndTime, 1);
  348. item.durationTime = item.liveEndTime - item.liveStartTime;
  349. }
  350. item.businessList = this.businList;
  351. item.status = 1;
  352. item.publishStatus = 1;
  353. item.coverUrl = "oss/images/avatar/20211013/1634097664410_1397766697";
  354. delete item.disabled;
  355. });
  356. this.$api.drCourseSectionaddMore(ary.reverse()).then((res) => {
  357. this.dialogVisible = false;
  358. console.log(res.data, "data");
  359. this.$emit("backData", res.data);
  360. });
  361. },
  362. /**
  363. * 预览
  364. */
  365. seeTheVideoFunc(item) {
  366. let jsonstr = JSON.parse(JSON.stringify(item));
  367. if(jsonstr.sectionType === 1){
  368. jsonstr.recordingUrl = item.url;
  369. }
  370. if(jsonstr.sectionType === 2){
  371. jsonstr.liveUrl = item.url
  372. }
  373. this.$parent.$refs.preview.diavosFun(jsonstr);
  374. },
  375. },
  376. };
  377. </script>
  378. <style lang="less" scoped>
  379. .elform_style {
  380. background-color: #eee;
  381. padding: 10px 10px 0px;
  382. display: flex;
  383. margin-bottom: 16px;
  384. .left_box {
  385. flex: 1;
  386. }
  387. .clear_style {
  388. flex-shrink: 0;
  389. width: 80px;
  390. vertical-align: top;
  391. text-align: center;
  392. }
  393. }
  394. .p_style {
  395. font-size: 12px;
  396. color: #a4a4a4;
  397. margin: 0;
  398. }
  399. .heightMax {
  400. max-height: 600px;
  401. overflow: auto;
  402. }
  403. </style>