liveClassDetail.vue 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <template>
  2. <div class="m-container">
  3. <h2>
  4. <el-page-header @back="onCancel" content="直播详情"></el-page-header>
  5. </h2>
  6. <div class="m-core">
  7. <div class="titleWrap">
  8. <h2 class="squrtTitle">
  9. <div class="squrt"></div>
  10. 直播数据
  11. </h2>
  12. <el-row class="row">
  13. <p class="teacherName">
  14. 主讲人:<span>{{ detail.speakerName }}</span>
  15. </p>
  16. <p class="teacherName sub">
  17. 主题:<span>{{ detail.roomTitle }}</span>
  18. </p>
  19. <el-button
  20. type="text"
  21. class="fontBtn"
  22. @click="payVisible = true"
  23. v-if="videoList.length > 0"
  24. >直播回放 <i class="el-icon-video-play"></i
  25. ></el-button>
  26. </el-row>
  27. <p class="liveRemark">
  28. 直播内容:<span>{{ detail.liveRemark }}</span>
  29. </p>
  30. </div>
  31. <div class="infoWrap">
  32. <statistic class="statistic" :cols="0">
  33. <statistic-item>
  34. <span> 参与学员 </span>
  35. <span>{{ detail.totalLookNum }}</span>
  36. </statistic-item>
  37. <statistic-item>
  38. <span> 累计点赞 </span>
  39. <span>{{ detail.totalLikeNum }}</span>
  40. </statistic-item>
  41. <statistic-item>
  42. <span> 直播时长(分钟) </span>
  43. <span>{{ detail.totalLiveTime }}</span>
  44. </statistic-item>
  45. </statistic>
  46. </div>
  47. <save-form
  48. :inline="true"
  49. :model="searchForm"
  50. @submit="search"
  51. @reset="onReSet"
  52. ref="searchForm"
  53. >
  54. <el-form-item>
  55. <el-input
  56. v-model.trim="searchForm.search"
  57. clearable
  58. @keyup.enter.native="
  59. (e) => {
  60. e.target.blur();
  61. $refs.searchForm.save();
  62. search();
  63. }
  64. "
  65. placeholder="学员编号/姓名"
  66. ></el-input>
  67. </el-form-item>
  68. <el-form-item>
  69. <el-button native-type="submit" type="primary">搜索</el-button>
  70. <el-button native-type="reset" type="danger">重置</el-button>
  71. </el-form-item>
  72. </save-form>
  73. <div class="tableWrap">
  74. <el-table
  75. style="width: 100%"
  76. :header-cell-style="{ background: '#EDEEF0', color: '#444' }"
  77. :data="tableList"
  78. >
  79. <el-table-column
  80. align="center"
  81. prop="studentId"
  82. label="学员编号"
  83. ></el-table-column>
  84. <el-table-column
  85. align="center"
  86. prop="studentName"
  87. label="学员姓名"
  88. ></el-table-column>
  89. <el-table-column
  90. align="center"
  91. prop="phone"
  92. label="手机号"
  93. ></el-table-column>
  94. <el-table-column
  95. align="center"
  96. prop="subName"
  97. label="声部"
  98. ></el-table-column>
  99. <el-table-column
  100. align="center"
  101. prop="joinTime"
  102. label="进入时间"
  103. ></el-table-column>
  104. <el-table-column align="center" prop="totalViewTime" label="观看时长">
  105. <template slot-scope="scope">
  106. <div>{{ scope.row.totalViewTime }}分钟</div>
  107. </template>
  108. </el-table-column>
  109. </el-table>
  110. <pagination
  111. sync
  112. :total.sync="rules.total"
  113. :page.sync="rules.page"
  114. :limit.sync="rules.limit"
  115. :page-sizes="rules.page_size"
  116. @pagination="getList"
  117. />
  118. </div>
  119. </div>
  120. <el-dialog
  121. :visible.sync="payVisible"
  122. v-if="payVisible"
  123. width="500px"
  124. title="直播回放"
  125. >
  126. <div class="lineWrap">
  127. <div
  128. class="linkItem"
  129. v-for="(item, index) in videoList"
  130. :key="index"
  131. @click="opneVideo(item)"
  132. >
  133. <div class="linkItemWrap">
  134. <video width="110px" :src="item.url"></video>
  135. <i class="el-icon-video-play linkIcon"></i>
  136. </div>
  137. <p :underline="false" type="text" class="lineTitle">
  138. {{ item.endTime | dateForMinFormat }}
  139. </p>
  140. </div>
  141. </div>
  142. <div slot="footer" class="dialog-footer">
  143. <!-- <el-button @click="payVisible = false">取 消</el-button> -->
  144. <el-button type="primary" @click="payVisible = false">确 定</el-button>
  145. </div></el-dialog
  146. >
  147. <el-dialog
  148. :title="activeVideo.endTime | dateForMinFormat"
  149. width="680px"
  150. append-to-body
  151. :visible.sync="videoVisible"
  152. v-if="videoVisible"
  153. >
  154. <!-- activeUrl -->
  155. <div class="activeVideoWrap">
  156. <video
  157. v-if="activeVideo.os == 'mobile'"
  158. style="width: 320px"
  159. :src="activeVideo.url"
  160. ref="dialogVideo"
  161. controls="controls"
  162. >
  163. 您的浏览器不支持视频播放
  164. </video>
  165. <video
  166. v-else
  167. style="width: 640px"
  168. :src="activeVideo.url"
  169. ref="dialogVideo"
  170. controls="controls"
  171. >
  172. 您的浏览器不支持视频播放
  173. </video>
  174. </div>
  175. </el-dialog>
  176. </div>
  177. </template>
  178. <script>
  179. import pagination from "@/components/Pagination/index";
  180. import {
  181. getLiveBroadcastRoomDetail,
  182. getLiveBroadcastRoomDetailList,
  183. } from "./api";
  184. export default {
  185. components: { pagination },
  186. data() {
  187. return {
  188. searchForm: {
  189. search: "",
  190. },
  191. tableList: [],
  192. detail: {
  193. list: null,
  194. liveRemark: "",
  195. roomTitle: "",
  196. roomUid: "",
  197. speakerName: "",
  198. totalLikeNum: 0,
  199. totalLiveTime: 0,
  200. totalLookNum: 0,
  201. },
  202. rules: {
  203. // 分页规则
  204. limit: 10, // 限制显示条数
  205. page: 1, // 当前页
  206. total: 0, // 总条数
  207. page_size: [10, 20, 40, 50], // 选择限制显示条数
  208. },
  209. videoList: [],
  210. payVisible: false,
  211. videoVisible: false,
  212. activeVideo: { endTime: "" },
  213. };
  214. },
  215. mounted() {
  216. this.getDetail();
  217. this.getList();
  218. },
  219. methods: {
  220. onCancel() {
  221. this.$router.push("/liveClassManager");
  222. this.$store.dispatch("delVisitedViews", this.$route);
  223. },
  224. search() {
  225. this.rules.page = 1;
  226. this.getList();
  227. },
  228. onReSet() {
  229. this.searchForm.search = "";
  230. this.search();
  231. },
  232. async getList() {
  233. try {
  234. let obj = {
  235. rows: this.rules.limit,
  236. page: this.rules.page,
  237. roomUid: this.$route.query.roomUid,
  238. search: this.searchForm.search,
  239. };
  240. const res = await getLiveBroadcastRoomDetailList(obj);
  241. this.tableList = res.data.rows;
  242. this.rules.total = res.data.total;
  243. } catch (e) {
  244. console.log(e);
  245. }
  246. },
  247. async getDetail() {
  248. try {
  249. let obj = {
  250. roomUid: this.$route.query.roomUid,
  251. };
  252. const res = await getLiveBroadcastRoomDetail(obj);
  253. this.detail = { ...res.data };
  254. this.videoList = res.data.videoList;
  255. } catch (e) {
  256. console.log(e);
  257. }
  258. },
  259. opneVideo(row) {
  260. this.activeVideo = row;
  261. this.videoVisible = true;
  262. },
  263. },
  264. };
  265. </script>
  266. <style lang="scss" scoped>
  267. .infoWrap {
  268. // width: 500px;
  269. }
  270. .sub.teacherName {
  271. margin-right: 10px;
  272. }
  273. .fontBtn {
  274. font-size: 18px;
  275. }
  276. .teacherName,
  277. .liveRemark {
  278. font-size: 16px;
  279. color: #222325;
  280. line-height: 30px;
  281. font-weight: 600;
  282. margin-right: 60px;
  283. span {
  284. color: #666666;
  285. font-weight: 400;
  286. }
  287. }
  288. .titleWrap {
  289. position: relative;
  290. // display: flex;
  291. // flex-direction: row;
  292. // align-items: center;
  293. padding: 5px;
  294. h2 {
  295. margin-right: 10px;
  296. }
  297. .squrtTitle {
  298. position: relative;
  299. font-size: 18px;
  300. font-family: PingFangSC-Medium, PingFang SC;
  301. font-weight: 600;
  302. color: #222325;
  303. line-height: 25px;
  304. margin-bottom: 25px;
  305. .squrt {
  306. position: absolute;
  307. left: -12px;
  308. top: 5px;
  309. width: 3px;
  310. height: 16px;
  311. background-color: var(--color-primary);
  312. }
  313. }
  314. .row {
  315. display: flex;
  316. flex-direction: row;
  317. align-items: center;
  318. }
  319. }
  320. .statistic .statistic-content > span {
  321. font-size: 16px;
  322. }
  323. .lineWrap {
  324. display: flex;
  325. flex-direction: row;
  326. align-items: center;
  327. flex-wrap: wrap;
  328. .linkItem {
  329. display: flex;
  330. flex-direction: column;
  331. align-items: center;
  332. margin-right: 5px;
  333. cursor: pointer;
  334. position: relative;
  335. &:hover {
  336. color: var(--color-primary);
  337. .lineTitle {
  338. color: var(--color-primary);
  339. font-weight: bold;
  340. }
  341. }
  342. .linkItemWrap {
  343. position: relative;
  344. .linkIcon {
  345. font-size: 25px;
  346. position: absolute;
  347. top: 50%;
  348. margin-top: -13px;
  349. left: 50%;
  350. margin-left: -13px;
  351. color: #fff;
  352. }
  353. }
  354. }
  355. .lineTitle {
  356. height: 40px;
  357. line-height: 40px;
  358. color: rgba(102, 102, 102, 0.9);
  359. padding: 0 17px;
  360. overflow: hidden;
  361. margin-bottom: 10px;
  362. position: relative;
  363. border-radius: 4px;
  364. }
  365. }
  366. .activeVideoWrap {
  367. display: flex;
  368. flex-direction: column;
  369. align-items: center;
  370. }
  371. </style>