playerList.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. <template>
  2. <div class="playerList">
  3. <!-- <div class="top">
  4. <div class="playBody">
  5. <div class="box">
  6. <div
  7. class="byted-card byted-card-inner-line byted-card-bordered css-deu8f5"
  8. v-for="item in playerList"
  9. :key="item.id"
  10. >
  11. <div class="byted-card-body">
  12. <div class="media">
  13. <div class="main_img">
  14. <img
  15. src="https://sf3-ttcdn-tos.pstatp.com/obj/union-fe/tmpl/file/2020082420341062812025.png"
  16. alt="图片加载失败"
  17. />
  18. </div>
  19. <div class="hoverBody">
  20. <div class="blackBG">
  21. <a-button type="primary" @click="preview(item)" style="margin-bottom: 30px">弹窗预览</a-button>
  22. <a-button type="primary" @click="previewVisible=true">使用模板</a-button>
  23. </div>
  24. </div>
  25. </div>
  26. <div>
  27. <h5 class="css-1lrzuem">
  28. <span class="tip">{{ item.product }}</span>
  29. {{ item.type }}
  30. </h5>
  31. <div class="css-vfnok7"></div>
  32. </div>
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. </div> -->
  38. <a-card :bordered="false">
  39. <a-button @click="addModules" style="margin: 0 0 15px 0" type="primary">新增模板</a-button>
  40. <div>
  41. <a-table
  42. ref="table"
  43. size="middle"
  44. bordered
  45. rowKey="id"
  46. :columns="columns"
  47. :dataSource="dataSource"
  48. :loading="loading"
  49. >
  50. <span slot="action" slot-scope="text, record">
  51. <a @click="downloadZip(record)">导出</a>
  52. <a-divider type="vertical" />
  53. <a @click="changeView(record)">替换素材</a>
  54. <a-divider type="vertical" />
  55. <a @click="preview(record)">预览</a>
  56. <a-divider type="vertical" />
  57. <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
  58. <a>删除</a>
  59. </a-popconfirm>
  60. </span>
  61. </a-table>
  62. </div>
  63. <!-- table区域-end -->
  64. </a-card>
  65. <div class="previewBody" v-if="previewBody">
  66. <div class="content">
  67. <div class="content-inner">
  68. <div class="phone">
  69. <iframe :src="playerSrc" width="274" height="487" frameborder="0"></iframe>
  70. </div>
  71. <a-button type="default" @click="closePreview" size="large" class="closePreviewBtn">关闭预览</a-button>
  72. </div>
  73. </div>
  74. </div>
  75. <a-modal
  76. title="模板上传"
  77. :visible="previewVisible"
  78. @cancel="handleCancel"
  79. :width="1000"
  80. @ok="saveFile"
  81. :confirm-loading="confirmLoading"
  82. >
  83. <a-form :form="form">
  84. <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="模板所属账户">
  85. <Treeselect :appId.sync="appId" :multiple="false" request="1,3" ref="treeSelect" style="width: 100%" />
  86. </a-form-item>
  87. <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="模板类型">
  88. <a-input
  89. placeholder="请输入模板类型"
  90. v-decorator.trim="['fileType', { rules: [{ required: true, message: '请输入模板类型' }] }]"
  91. />
  92. </a-form-item>
  93. <a-form-item :labelCol="labelCol" :wrapperCol="wrapperCol" label="模板文件">
  94. <a-upload
  95. name="file"
  96. action="http://192.168.1.251/jeecg-boot"
  97. :customRequest="customRequest"
  98. :fileList="defaultFileList"
  99. >
  100. <a-button> <a-icon type="upload" /> Click to Upload </a-button>
  101. </a-upload>
  102. <!-- <input type="file" @change="customRequest"> -->
  103. </a-form-item>
  104. </a-form>
  105. </a-modal>
  106. <a-modal
  107. title="替换素材"
  108. :visible="changeVisible"
  109. @cancel="changeVisible = false"
  110. :width="1000"
  111. @ok="changeFile"
  112. :confirm-loading="changeLoading"
  113. >
  114. <a-list class="demo-loadmore-list" :loading="loading" item-layout="horizontal" :data-source="dataList">
  115. <!-- <a-list-item slot="renderItem" slot-scope="item, index"> -->
  116. <a-list-item-meta style="margin-bottom: 10px">
  117. <a slot="title">是否重新生成</a>
  118. <div slot="description">
  119. <a-radio-group v-model="create" button-style="solid">
  120. <a-radio-button value="1"> 是 </a-radio-button>
  121. <a-radio-button value="2"> 否 </a-radio-button>
  122. </a-radio-group>
  123. </div>
  124. </a-list-item-meta>
  125. <a-list-item-meta v-if="create == '1'">
  126. <a slot="title">请输入试玩名称(不填默认拼接时间)</a>
  127. <div slot="description">
  128. <a-input placeholder="请输入试玩名称" v-model="fileName" />
  129. </div>
  130. </a-list-item-meta>
  131. <!-- </a-list-item> -->
  132. <a-list-item slot="renderItem" slot-scope="item, index">
  133. <a-upload
  134. name="file"
  135. action="http://192.168.1.251/jeecg-boot"
  136. :customRequest="customRequestChange"
  137. :beforeUpload="beforeUpload"
  138. :fileList="defaultFileList"
  139. slot="actions"
  140. v-if="item.fileSuffix == 'png' || item.fileSuffix == 'jpg' || item.fileSuffix == 'gif'"
  141. >
  142. <a @click="getIndex(item, index)">替换素材</a>
  143. </a-upload>
  144. <a-list-item-meta v-if="item.fileSuffix == 'png' || item.fileSuffix == 'jpg' || item.fileSuffix == 'gif'">
  145. <a slot="title"
  146. >{{ item.fileName }} (请上传大小为{{ item.width + '*' + item.height }}的图片,格式为{{
  147. item.fileSuffix
  148. }})</a
  149. >
  150. <div
  151. slot="description"
  152. style="width: 300px; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center"
  153. >
  154. <img :src="item.fileUrl" alt="" style="width: 50%; heihgt: auto; margin: 0 auto" />
  155. <img
  156. :src="item.imgPviewsUrl"
  157. v-if="item.imgPviewsUrl"
  158. alt=""
  159. style="width: 50%; heihgt: auto; margin: 0 auto"
  160. />
  161. </div>
  162. </a-list-item-meta>
  163. <!-- <a-list-item-meta v-else-if="item.fileSuffix == 'mp3'">
  164. <a slot="title">{{ item.fileName }}</a>
  165. <div
  166. slot="description"
  167. style="width: 200px; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center"
  168. >
  169. <audio
  170. loop
  171. muted
  172. :src="item.fileUrl"
  173. controls=""
  174. style="width: 100%; height: 20px; margin: 5px auto"
  175. ></audio>
  176. </div>
  177. </a-list-item-meta>
  178. <a-list-item-meta v-else-if="item.fileSuffix == 'mp4'">
  179. <a slot="title">{{ item.fileName }}</a>
  180. <div
  181. slot="description"
  182. style="width: 200px; background: rgba(0, 0, 0, 0.5); display: flex; justify-content: center"
  183. >
  184. <video :src="item.fileUrl" controls="controls" style="width: 50%; heihgt: auto; margin: 0 auto">
  185. 您的浏览器不支持 video 标签。
  186. </video>
  187. </div>
  188. </a-list-item-meta> -->
  189. <!-- <div>content</div> -->
  190. </a-list-item>
  191. </a-list>
  192. </a-modal>
  193. </div>
  194. </template>
  195. <script>
  196. import { getAction, postAction, uploadAction } from '../../api/manage'
  197. import playerList from './playerData'
  198. import { mapGetters } from 'vuex'
  199. import Treeselect from '@/views/modules/Statistics/components/Treeselect.vue'
  200. import qs from 'qs'
  201. export default {
  202. components: {
  203. Treeselect,
  204. },
  205. data() {
  206. return {
  207. confirmLoading: false,
  208. labelCol: {
  209. xs: { span: 24 },
  210. sm: { span: 5 },
  211. },
  212. wrapperCol: {
  213. xs: { span: 24 },
  214. sm: { span: 16 },
  215. },
  216. headers: {
  217. 'Content-Type': 'multipart/form-data',
  218. },
  219. thisItem: null,
  220. thisIndex: null,
  221. defaultFileList: [],
  222. fileAll: null,
  223. playerList,
  224. previewBody: false,
  225. playerSrc: '',
  226. previewVisible: false,
  227. changeVisible: false,
  228. changeLoading: false,
  229. loading: false,
  230. dataSource: [],
  231. dataList: [],
  232. form: this.$form.createForm(this),
  233. appId: '',
  234. fileName: '',
  235. create: '1',
  236. zipName: null,
  237. columns: [
  238. {
  239. title: '试玩名称',
  240. align: 'center',
  241. dataIndex: 'fileName',
  242. },
  243. {
  244. title: '试玩分类',
  245. align: 'center',
  246. dataIndex: 'fileType',
  247. },
  248. {
  249. title: '上传时间',
  250. align: 'center',
  251. dataIndex: 'createTime',
  252. },
  253. {
  254. title: '操作',
  255. dataIndex: 'action',
  256. align: 'center',
  257. scopedSlots: {
  258. customRender: 'action',
  259. },
  260. },
  261. ],
  262. }
  263. },
  264. methods: {
  265. downloadZip(item) {
  266. let eleLink = document.createElement('a')
  267. eleLink.download = item.fileName
  268. eleLink.href = item.fileUrl
  269. eleLink.click()
  270. eleLink.remove()
  271. },
  272. beforeUpload(file, fileList) {
  273. let that = this
  274. return new Promise(function (resolve, reject) {
  275. var imgInfo = {}
  276. let fileReader = new FileReader()
  277. fileReader.readAsDataURL(file) //根据图片路径读取图片
  278. fileReader.onload = function (e) {
  279. let base64 = this.result
  280. let img = new Image()
  281. img.src = base64
  282. img.onload = function () {
  283. imgInfo = {
  284. width: img.naturalWidth,
  285. height: img.naturalHeight,
  286. }
  287. console.log(imgInfo)
  288. if (imgInfo.width != that.thisItem.width || imgInfo.height != that.thisItem.height) {
  289. alert(`请选择${that.thisItem.width}*${that.thisItem.height}大小的文件!`)
  290. reject()
  291. } else {
  292. resolve()
  293. }
  294. }
  295. }
  296. })
  297. // const fileOvesize = (file.size > this.size * oneKB)
  298. },
  299. getIndex(item, index) {
  300. console.log(item, index)
  301. this.thisItem = item
  302. this.thisIndex = index
  303. },
  304. customRequest(data) {
  305. var dataAll = {
  306. uid: '1',
  307. name: data.file.name,
  308. status: 'done',
  309. }
  310. this.defaultFileList = [dataAll]
  311. this.fileAll = data.file
  312. // this.saveFile(data.file)
  313. },
  314. customRequestChange(data) {
  315. console.log(data)
  316. var dataAll = {
  317. uid: '1',
  318. name: data.file.name,
  319. status: 'done',
  320. }
  321. // this.defaultFileList = []
  322. if (data.file) {
  323. var that = this
  324. that.thisItem.newFile = data.file
  325. var fr = new FileReader()
  326. fr.onload = function () {
  327. that.thisItem.imgPviewsUrl = this.result
  328. }
  329. fr.readAsDataURL(data.file)
  330. }
  331. // this.saveFile(data.file)
  332. },
  333. changeFile(e) {
  334. this.changeLoading = true
  335. var dataArr = this.dataList.filter((i) => {
  336. return i.newFile != null
  337. })
  338. console.log(this.dataList, dataArr)
  339. let formData = new FormData()
  340. formData.append('file', dataArr[0].newFile)
  341. formData.append('userId', this.userInfo().id)
  342. formData.append('updateName', dataArr[0].fileName)
  343. formData.append('id', dataArr[0].parentId)
  344. formData.append('fileType', dataArr[0].fileType)
  345. if (dataArr[0].accountId) {
  346. formData.append('accountId', dataArr[0].accountId)
  347. }
  348. formData.append('isCreate', this.create == '1' ? 1 : null)
  349. formData.append('newFileName', this.fileName == '' ? this.zipName : this.fileName+'.zip')
  350. postAction('/shiwan/shiwanFileUpload/createNewZipFile', formData).then((res) => {
  351. if (res.success) {
  352. this.changeLoading = false
  353. this.changeVisible = false
  354. this.getPlayableList()
  355. this.fileName = ''
  356. }
  357. })
  358. // for (let i = 0; i < dataArr.length; i++) {
  359. // if (i == 0) {
  360. // }
  361. // }
  362. },
  363. saveFile(e) {
  364. this.confirmLoading = true
  365. this.form.validateFields((err, values) => {
  366. if (!err) {
  367. let that = this
  368. let formData = new FormData()
  369. console.log(this.defaultFileList)
  370. formData.append('file', this.fileAll)
  371. formData.append('userId', this.userInfo().id)
  372. formData.append('fileType', values.fileType)
  373. uploadAction('/shiwan/shiwanFileUpload/saveOrUpdateFile', formData).then((res) => {
  374. if (res.success) {
  375. this.confirmLoading = false
  376. this.defaultFileList = []
  377. this.fileAll = null
  378. this.form.resetFields()
  379. this.previewVisible = false
  380. this.getPlayableList()
  381. } else {
  382. this.confirmLoading = false
  383. this.$message.error(res.message)
  384. this.defaultFileList = []
  385. this.fileAll = null
  386. }
  387. })
  388. }
  389. })
  390. },
  391. ...mapGetters(['nickname', 'avatar', 'userInfo']),
  392. changeView(item) {
  393. getAction('/shiwan/shiwanFileUpload/selectListByParentId', { id: item.id }).then((res) => {
  394. if (res.success) {
  395. var data = []
  396. data = res.result.filter((i) => {
  397. if (i.fileSuffix == 'png' || i.fileSuffix == 'jpg' || i.fileSuffix == 'gif') {
  398. return i
  399. }
  400. })
  401. this.dataList = data.map((i) => {
  402. return {
  403. ...i,
  404. width: null,
  405. height: null,
  406. imgPviewsUrl: '',
  407. newFile: null,
  408. }
  409. })
  410. for (let i = 0; i < this.dataList.length; i++) {
  411. this.getImgWidth(this.dataList[i])
  412. }
  413. this.changeVisible = true
  414. this.zipName = item.fileName
  415. }
  416. })
  417. },
  418. preview(item) {
  419. console.log(item)
  420. getAction('/shiwan/shiwanFileUpload/selectListByParentId', { id: item.id }).then((res) => {
  421. if (res.success) {
  422. this.previewBody = true
  423. this.playerSrc = res.result.filter((i) => {
  424. return i.fileSuffix == 'html'
  425. })[0].fileUrl
  426. }
  427. })
  428. },
  429. closePreview() {
  430. this.previewBody = false
  431. },
  432. handleCancel() {
  433. this.previewVisible = false
  434. },
  435. addModules() {
  436. this.previewVisible = true
  437. },
  438. handleDelete(item) {
  439. postAction('/shiwan/shiwanFileUpload/edit', { id: item, fileStatus: '0' }).then((res) => {
  440. if (res.success) {
  441. this.getPlayableList()
  442. }
  443. })
  444. },
  445. getPlayableList() {
  446. getAction('/shiwan/shiwanFileUpload/list', {
  447. pageNo: 1,
  448. pageSize: 1000,
  449. }).then((res) => {
  450. if (res.success) {
  451. this.dataSource = res.result.records
  452. }
  453. })
  454. },
  455. getImgWidth(item) {
  456. // this.$nextTick(() => {
  457. // 记录当前时间戳
  458. var start_time = new Date().getTime()
  459. // 图片地址
  460. var img_url = item.fileUrl
  461. // 创建对象
  462. var img = new Image()
  463. // 改变图片的src
  464. img.src = img_url
  465. // 定时执行获取宽高
  466. var checkAll = ''
  467. var that = this
  468. var check = function () {
  469. // 只要任何一方大于0
  470. // 表示已经服务器已经返回宽高
  471. if (img.width > 0 || img.height > 0) {
  472. var diff = new Date().getTime() - start_time
  473. item.width = img.width
  474. item.height = img.height
  475. that.$set(item, 'width', img.width)
  476. that.$set(item, 'height', img.height)
  477. clearInterval(set)
  478. }
  479. }
  480. var set = setInterval(check, 40)
  481. // 加载完成获取宽高
  482. img.onload = function () {
  483. var diff = new Date().getTime() - start_time
  484. item.width = img.width
  485. item.height = img.height
  486. that.$set(item, 'width', img.width)
  487. that.$set(item, 'height', img.height)
  488. // console.log(item.width, item.height)
  489. }
  490. // })
  491. },
  492. },
  493. mounted() {
  494. this.getPlayableList()
  495. },
  496. }
  497. </script>
  498. <style lang="scss" scoped>
  499. .playerList {
  500. position: relative;
  501. .top {
  502. width: calc(100% - 160px);
  503. margin: 0px auto;
  504. }
  505. .playBody {
  506. width: 100%;
  507. padding: 20px;
  508. .box {
  509. width: 100%;
  510. height: 100%;
  511. display: flex;
  512. flex-wrap: wrap;
  513. -webkit-box-pack: center;
  514. justify-content: flex-start;
  515. .css-deu8f5 {
  516. width: 224px;
  517. margin: 10px !important;
  518. }
  519. .byted-card-inner-line {
  520. padding: 0;
  521. }
  522. .byted-card-bordered {
  523. border: 1px solid #e0e0e0;
  524. box-shadow: none;
  525. }
  526. .byted-card {
  527. font-size: 14px;
  528. line-height: 22px;
  529. position: relative;
  530. color: #333;
  531. background: #fff;
  532. box-sizing: border-box;
  533. border-radius: 4px;
  534. box-shadow: 0 1px 6px 0 rgba(0, 0, 0, 0.05);
  535. border: 1px solid transparent;
  536. }
  537. .byted-card > .byted-card-body {
  538. box-shadow: rgb(204, 204, 204) 0px 0px 10px;
  539. padding: 0px !important;
  540. }
  541. .byted-card > .byted-card-body .media {
  542. height: 392px;
  543. width: 100%;
  544. position: relative;
  545. cursor: pointer;
  546. overflow: hidden;
  547. border-bottom: 1px solid rgb(204, 204, 204);
  548. }
  549. .byted-card > .byted-card-body .media .main_img {
  550. width: 100%;
  551. height: 100%;
  552. display: flex;
  553. -webkit-box-align: center;
  554. align-items: center;
  555. position: absolute;
  556. }
  557. .byted-card > .byted-card-body .media .main_img img:last-child {
  558. width: 100%;
  559. position: absolute;
  560. }
  561. .byted-card > .byted-card-body .media .main_img img:first-child {
  562. width: 100%;
  563. height: 100%;
  564. // filter: blur(10px);
  565. position: absolute;
  566. }
  567. .css-1lrzuem {
  568. display: flex;
  569. -webkit-box-align: center;
  570. align-items: center;
  571. font-size: 14px;
  572. font-weight: 600;
  573. color: rgb(51, 51, 51);
  574. line-height: 20px;
  575. text-shadow: rgba(0, 0, 0, 0.08) 0px 2px 8px;
  576. word-break: keep-all;
  577. text-overflow: ellipsis;
  578. white-space: nowrap;
  579. margin: 16px 16px 0px;
  580. overflow: hidden;
  581. }
  582. .css-vfnok7 {
  583. height: 40px;
  584. display: flex;
  585. flex-direction: row-reverse;
  586. -webkit-box-align: center;
  587. align-items: center;
  588. }
  589. .hoverBody {
  590. display: none;
  591. position: absolute;
  592. top: 0px;
  593. left: 0px;
  594. width: 100%;
  595. height: 100%;
  596. }
  597. .blackBG {
  598. position: absolute;
  599. top: 0px;
  600. left: 0px;
  601. width: 100%;
  602. height: 100%;
  603. display: flex;
  604. -webkit-box-align: center;
  605. align-items: center;
  606. -webkit-box-pack: center;
  607. justify-content: center;
  608. background-color: rgba(0, 0, 0, 0.5);
  609. flex-flow: column;
  610. }
  611. .byted-card:hover {
  612. box-shadow: rgb(153, 153, 153) 0px 0px 20px;
  613. }
  614. .byted-card:hover .hoverBody {
  615. display: block;
  616. }
  617. .tip {
  618. display: inline-block;
  619. margin-right: 15px;
  620. background: #ff6633;
  621. width: 80px;
  622. padding: 2px 10px;
  623. text-align: center;
  624. border-radius: 10px;
  625. }
  626. }
  627. }
  628. .previewBody {
  629. background: rgba(0, 0, 0, 0.5);
  630. position: absolute;
  631. top: 0;
  632. left: 0;
  633. padding: 20px 80px;
  634. width: 100%;
  635. height: 100%;
  636. .content {
  637. display: flex;
  638. justify-content: center;
  639. align-items: center;
  640. height: 100%;
  641. }
  642. .content-inner {
  643. font-size: 14px;
  644. line-height: 22px;
  645. padding: 0 24px 8px;
  646. color: #666;
  647. text-align: center;
  648. position: fixed;
  649. top: 200px;
  650. }
  651. .phone {
  652. background-color: rgb(255, 255, 255);
  653. position: relative;
  654. padding: 9px 8px 7px;
  655. border-radius: 24px;
  656. }
  657. .phone iframe {
  658. border-radius: 18px;
  659. }
  660. .closePreviewBtn {
  661. margin-top: 30px;
  662. }
  663. }
  664. }
  665. </style>