onlineTrainingList.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. <style lang="scss" scoped>
  2. .search-box p {
  3. display: inline-block;
  4. border: 1px solid #f2f2f2;
  5. border-radius: 5px;
  6. margin-right: 10px;
  7. padding: 5px 10px;
  8. cursor: pointer;
  9. }
  10. #office-iframe {
  11. height: 800px;
  12. }
  13. </style>
  14. <template>
  15. <a-row :gutter="10">
  16. <a-col :sm="6" style="margin-bottom: 20px;z-index: 10">
  17. <a-card class="search-box" style="min-height:500px" title="在线视频培训列表">
  18. <a slot="extra" @click="addList">
  19. 新增培训视频
  20. </a>
  21. <a-directory-tree @select="onSelect" @expand="onExpand" :loadData="onLoadData"
  22. :treeData="treeData">
  23. </a-directory-tree>
  24. </a-card>
  25. </a-col>
  26. <a-col :sm="18" style="margin-bottom: 20px;z-index: 10">
  27. <a-card class="search-box">
  28. <!-- <div @click="openFile">打开文件</div> -->
  29. <div v-if="course">
  30. <a-breadcrumb>
  31. <a-breadcrumb-item>{{ course.media }}</a-breadcrumb-item>
  32. <a-breadcrumb-item>{{ course.title }}</a-breadcrumb-item>
  33. <a-breadcrumb-item>{{ course.topic }}</a-breadcrumb-item>
  34. </a-breadcrumb>
  35. <h3 style="text-align:center">{{ course.name }}</h3>
  36. <p v-if="!startList">请使用谷歌浏览器进行视频播放,并开启flash(开启方法:浏览器右上角三个小点-设置-网站设置-flash-每次进行询问勾选打开即可)</p>
  37. <br>
  38. <p v-if="!startList">flash下载链接:https://www.flash.cn/cdm/latest/flashplayerpp_install_cn.exe</p>
  39. <br>
  40. <p style="text-align:center" v-if="course.creator">作者:{{ course.creator }}</p>
  41. <br />
  42. <p>{{ course.intro }}</p>
  43. </div>
  44. <div id="iframeData" v-show="startList" style="height:800px"></div>
  45. <div id="videoPlay" style="height:800px" v-show="!startList"></div>
  46. </a-card>
  47. </a-col>
  48. <a-modal :width="800" title="培训视频上传" @cancel="closeImage" @afterClose="closeImage" v-model="addImageVisible">
  49. <template slot="footer">
  50. <a-button key="back" @click="closeImage">取消</a-button>
  51. <a-button key="submit" type="primary" @click="handleOkImage" :loading="loadingImage" :disabled="fileUrl==''">
  52. 确定
  53. </a-button>
  54. </template>
  55. <a-form :form="form">
  56. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="培训上传方式">
  57. <a-radio-group buttonStyle="solid" v-model="typeUpload" @change="clear">
  58. <a-radio-button value="1">原有目录上传</a-radio-button>
  59. <a-radio-button value="2" :disabled="roleName!='admin'">新建目录上传</a-radio-button>
  60. </a-radio-group>
  61. </a-form-item>
  62. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="一级目录选择">
  63. <a-select
  64. v-decorator="['media', { rules: [{ required: true, message: '请选择一级目录' }], initialValue: '汇创视频培训' }]"
  65. showSearch allowClear placeholder="选择模板" optionFilterProp="children" :filterOption="filterOption" disabled>
  66. <a-select-option value="汇创视频培训">
  67. 汇创视频培训
  68. </a-select-option>
  69. </a-select>
  70. </a-form-item>
  71. <div v-if="typeUpload == '1'">
  72. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="二级目录选择">
  73. <a-select v-decorator="['title', { rules: [{ required: true, message: '请选择二级目录' }] }]" style="width: 100%"
  74. placeholder="请选择二级目录" @change="getTopic">
  75. <a-select-option v-for="(item,index) in titleList" :key="index" :value="item.value">
  76. {{item.label}}
  77. </a-select-option>
  78. </a-select>
  79. </a-form-item>
  80. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="三级目录选择">
  81. <a-select v-decorator="['topic', { rules: [{ required: true, message: '请选择三级目录' }] }]" style="width: 100%"
  82. placeholder="请选择三级目录" :disabled="!getData('title')" @change="setOssDir">
  83. <a-select-option v-for="(item,index) in topicList" :key="index" :value="item.value">
  84. {{item.label}}
  85. </a-select-option>
  86. </a-select>
  87. </a-form-item>
  88. </div>
  89. <div v-else>
  90. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="二级目录">
  91. <!-- <a-input placeholder="请填写二级目录"
  92. v-decorator="['titleAll', { rules: [{ required: true, message: '二级目录必填' }] }]" /> -->
  93. <a-select mode="tags" v-model="oneList" placeholder="请填写二级目录" @change="handleChange" autoClearSearchValue>
  94. <a-select-option v-for="(item,index) in titleList" :key="index" :value="item.value">
  95. {{item.label}}
  96. </a-select-option>
  97. </a-select>
  98. </a-form-item>
  99. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="三级目录">
  100. <a-input placeholder="请填写三级目录"
  101. v-decorator="['topicAll', { rules: [{ required: true, message: '三级目录必填' }] }]" />
  102. </a-form-item>
  103. </div>
  104. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="培训视频名称">
  105. <a-input placeholder="请填写培训视频名称"
  106. v-decorator="['name', { rules: [{ required: true,message:'培训视频名称不能为空'}] }]" />
  107. </a-form-item>
  108. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="培训视频简介">
  109. <a-input placeholder="请填写培训视频简介" v-decorator="['intro']" />
  110. </a-form-item>
  111. <a-form-item :label-col="labelCol" :wrapper-col="wrapperCol" label="文件上传"
  112. v-show="(getData('title') && getData('topic'))||(oneList.length>0 && getData('topicAll'))">
  113. <uploadFile :value.sync="fileUrl" :multiple='false':checkFile="file" :fileCount="1"
  114. uploadType="video" />
  115. <!-- <upload-to-ali v-model="fileUrl" :customDomain="customDomain" preview :region="region" :bucket="bucket"
  116. :accept="acceptVideo" :max="10" :size="1024000" :accessKeyId="accessKeyId"
  117. :accessKeySecret="accessKeySecret" :before-upload="file" :dir="dirVideo" @loaded="overUpload">
  118. </upload-to-ali> -->
  119. </a-form-item>
  120. </a-form>
  121. </a-modal>
  122. </a-row>
  123. </template>
  124. <script>
  125. import {
  126. getAction,
  127. postAction
  128. } from '@/api/manage'
  129. import {
  130. JeecgListMixin
  131. } from '@/mixins/JeecgListMixin'
  132. import moment from 'moment'
  133. import $ from 'jquery'
  134. import qs from 'qs'
  135. import UploadToAli from '@femessage/upload-to-ali'
  136. import uploadFile from '@/components/uploadFile.vue'
  137. // document.write(textDes('https://ctop-media.oss-cn-beijing.aliyuncs.com/video/2020-03-20/20网服-1584693978588.mp4'))
  138. // document.write('<br>' + desDecrypt('s4HMPbmUfZ0=', 'ckplayerDesKey'))
  139. function textDes(str) {
  140. var keyCode = 'ckplayerDesKey'
  141. var newText = encodeURI(desEncrypt(str, keyCode))
  142. newText = (keyCode == 'ckplayerDesKey' ? 'CK:' : 'CE:') + newText
  143. return newText
  144. }
  145. function desEncrypt(word, keyCode) {
  146. var key = CryptoJS.enc.Utf8.parse(keyCode)
  147. var iv = CryptoJS.enc.Utf8.parse(keyCode)
  148. var srcs = CryptoJS.enc.Utf8.parse(word)
  149. var encrypted = CryptoJS.DES.encrypt(srcs, key, {
  150. iv: iv,
  151. mode: CryptoJS.mode.ECB
  152. })
  153. return encrypted.toString()
  154. }
  155. function desDecrypt(word, keyCode) {
  156. var key = CryptoJS.enc.Utf8.parse(keyCode)
  157. var iv = CryptoJS.enc.Utf8.parse(keyCode)
  158. var decrypt = CryptoJS.DES.decrypt(word, key, {
  159. iv: iv,
  160. mode: CryptoJS.mode.ECB
  161. })
  162. return CryptoJS.enc.Utf8.stringify(decrypt).toString()
  163. }
  164. export default {
  165. name: 'online-training-list',
  166. mixins: [JeecgListMixin],
  167. data() {
  168. return {
  169. typeUpload: '1',
  170. titleList: [],
  171. topicList: [],
  172. oneList: [],
  173. fileUrl: '',
  174. customDomain: '',
  175. region: 'oss-cn-beijing',
  176. bucket: 'ctop-media',
  177. acceptVideo: 'video/mpeg,video/mp4',
  178. accessKeyId: 'LTAIbNbqWzSOklQV',
  179. accessKeySecret: '1rkPz7JNoXk8sJevPaeYHWqfkQXBGh',
  180. labelCol: {
  181. xs: {
  182. span: 24
  183. },
  184. sm: {
  185. span: 5
  186. }
  187. },
  188. wrapperCol: {
  189. xs: {
  190. span: 24
  191. },
  192. sm: {
  193. span: 12
  194. }
  195. },
  196. visibleDetail: false,
  197. srcList: '',
  198. loadingImage: false,
  199. addImageVisible: false,
  200. form: this.$form.createForm(this),
  201. treeData: [{
  202. title: '巨量引擎',
  203. key: '巨量引擎'
  204. },
  205. {
  206. title: '快手大学',
  207. key: '快手大学'
  208. },
  209. {
  210. title: '汇创视频培训',
  211. key: '汇创视频培训'
  212. }
  213. ],
  214. videoObject: {
  215. width: '20%', // 宽度,也可以支持百分比(不过父元素宽度要有)
  216. height: 180, // 高度,也可以支持百分比
  217. container: '#videoPlay', //“#”代表容器的ID,“.”或“”代表容器的class
  218. variable: 'player', //该属性必需设置,值等于下面的new chplayer()的对象
  219. autoplay: false, //自动播放
  220. flashplayer: true, //强制使用flashplayer
  221. live: false,
  222. debug: true,
  223. loadNext: 10,
  224. usehardwareeecoder: true, //硬件加速
  225. video: textDes() //视频地址(必填)
  226. },
  227. videoObjectNot: {
  228. container: '#videoPlay', //“#”代表容器的ID,“.”或“”代表容器的class
  229. variable: 'player', //该属性必需设置,值等于下面的new chplayer()的对象
  230. autoplay: false,
  231. html5m3u8: true,
  232. debug: true,
  233. video: "" //视频地址
  234. },
  235. active: 1,
  236. url: {
  237. list: '/ctop/materialInfo/list'
  238. },
  239. startList: true,
  240. simpleMode: false,
  241. course: null,
  242. dirVideo: "online/",
  243. roleName: localStorage.getItem('roleCode')
  244. }
  245. },
  246. components: {
  247. UploadToAli,
  248. uploadFile
  249. },
  250. methods: {
  251. clear() {
  252. this.form.setFieldsValue({
  253. topic: '',
  254. title: ''
  255. })
  256. },
  257. filterOption(input, option) {
  258. return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
  259. },
  260. getTopic(e) {
  261. // e.target.value
  262. console.log(e)
  263. this.topicList = []
  264. this.form.setFieldsValue({
  265. topic: ''
  266. })
  267. getAction('/ctop/edu/system/topic', {
  268. title: e
  269. }).then(res => {
  270. if (res.success) {
  271. this.topicList = res.result.map(item => {
  272. return {
  273. value: item,
  274. label: item
  275. }
  276. })
  277. }
  278. })
  279. },
  280. setOssDir(e) {
  281. this.dirVideo = 'online/' + this.getData('title') + '/' + this.getData('topic')
  282. },
  283. setOssDirElse() {
  284. this.dirVideo = 'online/' + this.oneList[0] + '/' + this.getData('topicAll')
  285. },
  286. addList() {
  287. this.addImageVisible = true
  288. this.loadingImage = false
  289. this.typeUpload = '1'
  290. getAction("/ctop/edu/system/lesson").then(res => {
  291. console.log(res)
  292. if (res.success) {
  293. this.titleList = res.result.map(item => {
  294. return {
  295. value: item,
  296. label: item
  297. }
  298. })
  299. }
  300. })
  301. },
  302. handleChange(value) {
  303. console.log(value)
  304. if (value.length == 2) {
  305. this.oneList = [value.pop()]
  306. }
  307. },
  308. handleOkImage(e) {
  309. this.loadingImage = true
  310. this.form.validateFieldsAndScroll((err, values) => {
  311. if (err) {
  312. // 这里做逻辑处理
  313. } else {
  314. var params = {}
  315. if (this.typeUpload == '1') {
  316. params = {
  317. ...values,
  318. ossFileUrl: 'https:' + this.fileUrl,
  319. fileType: 1
  320. }
  321. } else {
  322. params = {
  323. ...values,
  324. ossFileUrl: 'https:' + this.fileUrl,
  325. fileType: 1,
  326. title: this.oneList[0],
  327. topic: values.topicAll
  328. }
  329. }
  330. postAction('/ctop/edu/lesson/upload', params).then(res => {
  331. if (res.success) {
  332. this.loadingImage = false
  333. this.closeImage()
  334. getAction("/ctop/edu/system/lesson").then(res => {
  335. })
  336. }
  337. })
  338. }
  339. })
  340. },
  341. closeImage() {
  342. this.addImageVisible = false
  343. this.form.resetFields()
  344. this.fileUrl = ""
  345. this.oneList = []
  346. },
  347. file(file) {
  348. if (this.typeUpload == '1') {
  349. this.dirVideo = 'online/' + this.getData('title') + '/' + this.getData('topic')
  350. } else {
  351. this.dirVideo = 'online/' + this.oneList[0] + '/' + this.getData('topicAll')
  352. }
  353. var that = this
  354. console.log(this.dirVideo)
  355. return new Promise(function (resolve, reject) {
  356. if (that.dirVideo.split('/').length == 3) {
  357. resolve()
  358. } else {
  359. reject()
  360. }
  361. })
  362. },
  363. overUpload() {
  364. },
  365. onLoadData(treeNode) {
  366. console.log(treeNode)
  367. return new Promise(resolve => {
  368. if (treeNode.eventKey == '巨量引擎') {
  369. getAction('/ctop/edu/ocean/lesson').then(res => {
  370. if (res.success) {
  371. treeNode.dataRef.children = res.result.map(item => {
  372. if (item) {
  373. return {
  374. title: item,
  375. key: item + '@juliang'
  376. }
  377. }
  378. })
  379. resolve()
  380. this.treeData = [...this.treeData]
  381. }
  382. })
  383. } else if (treeNode.eventKey == '快手大学') {
  384. getAction('/ctop/edu/kuaishou/lesson').then(res => {
  385. if (res.success) {
  386. treeNode.dataRef.children = res.result.map(item => {
  387. if (item) {
  388. return {
  389. title: item,
  390. key: item + '@kuaishou'
  391. }
  392. }
  393. })
  394. resolve()
  395. this.treeData = [...this.treeData]
  396. }
  397. })
  398. } else if (treeNode.eventKey == '汇创视频培训') {
  399. getAction('/ctop/edu/system/lesson').then(res => {
  400. if (res.success) {
  401. treeNode.dataRef.children = res.result.map(item => {
  402. if (item) {
  403. return {
  404. title: item,
  405. key: item + '@system'
  406. }
  407. }
  408. })
  409. resolve()
  410. this.treeData = [...this.treeData]
  411. }
  412. })
  413. return
  414. } else if (treeNode.eventKey.split('@').length == 2) {
  415. var data = treeNode.eventKey.split('@')
  416. if (data[1] == 'juliang') {
  417. getAction('/ctop/edu/ocean/topic', {
  418. title: data[0]
  419. }).then(res => {
  420. if (res.success) {
  421. treeNode.dataRef.children = res.result.map(item => {
  422. return {
  423. title: item,
  424. key: item + '@juliang@' + data[0]
  425. }
  426. })
  427. resolve()
  428. this.treeData = [...this.treeData]
  429. }
  430. })
  431. } else if (data[1] == 'kuaishou') {
  432. getAction('/ctop/edu/kuaishou/topic', {
  433. title: data[0]
  434. }).then(res => {
  435. if (res.success) {
  436. treeNode.dataRef.children = res.result.map(item => {
  437. return {
  438. title: item,
  439. key: item + '@kuaishou@' + data[0]
  440. }
  441. })
  442. resolve()
  443. this.treeData = [...this.treeData]
  444. }
  445. })
  446. } else if (data[1] == 'system') {
  447. getAction('/ctop/edu/system/topic', {
  448. title: data[0]
  449. }).then(res => {
  450. if (res.success) {
  451. treeNode.dataRef.children = res.result.map(item => {
  452. return {
  453. title: item,
  454. key: item + '@system@' + data[0]
  455. }
  456. })
  457. resolve()
  458. this.treeData = [...this.treeData]
  459. }
  460. })
  461. }
  462. } else if (treeNode.eventKey.split('@').length == 3) {
  463. var data = treeNode.eventKey.split('@')
  464. getAction('/ctop/edu/lesson/list', {
  465. media: data[1] == 'juliang' ? '巨量引擎' : data[1] == 'kuaishou' ? '快手大学' : '汇创视频培训',
  466. title: data[2],
  467. topic: data[0]
  468. }).then(res => {
  469. console.log(res)
  470. if (res.success) {
  471. treeNode.dataRef.children = res.result.map(item => {
  472. return {
  473. title: item.name,
  474. key: item.id,
  475. isLeaf: true
  476. }
  477. })
  478. resolve()
  479. this.treeData = [...this.treeData]
  480. }
  481. })
  482. }
  483. })
  484. },
  485. onSelect(keys, event) {
  486. console.log(keys)
  487. if (event.node.isLeaf) {
  488. getAction('/ctop/edu/detail', {
  489. id: keys[0]
  490. }).then(res => {
  491. console.log(res)
  492. if (res.success) {
  493. this.course = res.result
  494. if (res.result.fileType == 1) {
  495. this.startList = false
  496. // var videoObject = null
  497. // var isChrome = window.navigator.userAgent.indexOf('Chrome') !== -1 //不同的浏览器显示方式不一样, 不是chrome的浏览器需要使用hls.js这个文件
  498. // if (isChrome) {
  499. // videoObject = this.videoObject
  500. // } else {
  501. // videoObject = this.videoObjectNot
  502. // }
  503. if (res.result.fileId) {
  504. this.videoObject.video = textDes('https://aweme.snssdk.com/aweme/v1/playwm/?video_id=' + res
  505. .result.fileId + '&line=0')
  506. } else {
  507. if (res.result.fileUrl) {
  508. this.videoObject.video = textDes(res.result.fileUrl)
  509. } else {
  510. this.videoObject.video = textDes(res.result.ossFileUrl)
  511. }
  512. }
  513. console.log(this.videoObject.video)
  514. let player = new ckplayer(this.videoObject)
  515. console.log(player)
  516. } else {
  517. this.startList = true
  518. getAction('http://www.ljserver.cn:8088/v1/api/file/getViewUrlWebPath', {
  519. fileUrl: decodeURI(res.result.ossFileUrl)
  520. }).then(resF => {
  521. console.log(resF)
  522. let r = resF.data
  523. sessionStorage.wpsUrl = r.wpsUrl
  524. sessionStorage.token = r.token
  525. this.openWps(r.wpsUrl, r.token, res.result.fileType)
  526. })
  527. }
  528. }
  529. })
  530. } else {
  531. return
  532. }
  533. },
  534. openWps(url, token, type) {
  535. let _this = this
  536. console.log(url)
  537. const wps = WebOfficeSDK.config({
  538. mode: _this.simpleMode ? 'simple' : 'normal',
  539. mount: document.querySelector('#iframeData'),
  540. wpsUrl: url,
  541. commonOptions: {
  542. isShowTopArea: false // 隐藏顶部区域(头部和工具栏)
  543. }
  544. })
  545. // 2:pdf
  546. // 3:ppt
  547. wps.setToken({
  548. token: token
  549. })
  550. if (type == 2) {
  551. wps.PPTApplication
  552. } else if (type == 3) {
  553. wps.PDFApplication
  554. } else {
  555. wps.Application
  556. }
  557. wps.iframe.height = '800px'
  558. },
  559. onExpand() {
  560. console.log('Trigger Expand')
  561. },
  562. getDataSource(page, pageSize) {
  563. this.ipagination.current = page
  564. this.loadData()
  565. },
  566. getData(className) {
  567. return this.form.getFieldValue(className)
  568. },
  569. getAdd(checked) {
  570. this.active = checked
  571. if (checked == 5) {
  572. this.data = []
  573. } else {
  574. this.data = [{
  575. title: 'Title 1'
  576. },
  577. {
  578. title: 'Title 2'
  579. },
  580. {
  581. title: 'Title 3'
  582. },
  583. {
  584. title: 'Title 4'
  585. }
  586. ]
  587. }
  588. },
  589. lookDetail(item) {
  590. this.visibleDetail = true
  591. },
  592. openFile() {
  593. getAction('http://www.ljserver.cn:8088/v1/api/file/getViewUrlWebPath', {
  594. fileUrl: 'https://ctop-media.oss-cn-beijing.aliyuncs.com/zixingche.docx'
  595. }).then(res => {
  596. console.log(res.data.wpsUrl)
  597. window.open(res.data.wpsUrl, '_blank')
  598. })
  599. },
  600. getDirectory() {
  601. getAction('/ctop/edu/kuaishou/lesson').then(res => {
  602. console.log(res)
  603. })
  604. getAction('/ctop/edu/kuaishou/topic', {
  605. title: '新代理入门培训'
  606. }).then(res => {
  607. console.log(res)
  608. })
  609. getAction('/ctop/edu/ocean/lesson').then(res => {
  610. console.log(res)
  611. })
  612. getAction('/ctop/edu/ocean/topic', {
  613. title: '初级认证I类课程'
  614. }).then(res => {
  615. console.log(res)
  616. })
  617. getAction('/ctop/edu/lesson/list', {
  618. media: '快手大学',
  619. title: '新代理入门培训',
  620. topic: '入门培训'
  621. }).then(
  622. res => {
  623. console.log(res)
  624. }
  625. )
  626. }
  627. },
  628. mounted() {
  629. this.$nextTick(() => {
  630. this.videoObject.video =
  631. " CK:2OoC8kA6lhNFqCi2uVquDPpnuq9VcRji9nGXe5nqadA6Jey7YFFEP8pE99j58UBbLyb7YN7cpkw="
  632. let player = new ckplayer(this.videoObject)
  633. })
  634. },
  635. created() {
  636. // console.log(player)
  637. // /modules/onlineTraining/onlineTrainingList
  638. }
  639. }
  640. </script>