邃芒官网、邃芒慧影、口播(H5) https://m.metavatar.cc
Du kannst nicht mehr als 25 Themen auswählen Themen müssen entweder mit einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.
 
 
 
 

1528 Zeilen
44 KiB

  1. <template>
  2. <div :class="inPage ? 'page active' : 'page'">
  3. <div id="top"></div>
  4. <HeadTop />
  5. <!-- 中间内容区 -->
  6. <div class="vantLoadingBox" style="height: 550px" v-show="contentLoading">
  7. <van-loading type="spinner" color="#52d4e5" class="vantLoading" />
  8. </div>
  9. <div v-show="!contentLoading" class="content">
  10. <!-- 展示图片 -->
  11. <div class="shouModelImg">
  12. <div id="editPosition" class="editPosition" :class="videoType == 2 ? 'verticalmodel' : ''">
  13. <EditPosition ref="EditPosition" :proportion="proportion" :imgUrl="imgUrl" :materialList="materialList" :videoType="videoType"></EditPosition>
  14. </div>
  15. <!-- <img :src="imgUrl" alt="" /> -->
  16. <!-- 字幕 -->
  17. <!-- <div
  18. v-html="textareaContent"
  19. v-show="showSubtitle"
  20. class="shouModelImg-subtitle"
  21. ></div> -->
  22. </div>
  23. <!-- 文字 -->
  24. <div class="addText">
  25. <div class="addText-title">
  26. <img src="../../assets/icon/icon-text.png" alt="" />
  27. 添加文案
  28. </div>
  29. <div class="desalinate">
  30. <span>已录入{{ textareaContent.length }}字</span>
  31. &nbsp;&nbsp;
  32. <!-- <span>视频时长:&nbsp;00:16</span> -->
  33. </div>
  34. </div>
  35. <!-- 标题框 -->
  36. <div class="textInput">
  37. <div class="textInput-in">
  38. <!-- 标题 -->
  39. <el-input v-model="inputTitle" placeholder="请输入标题">
  40. <template slot="append">
  41. <img src="../../assets/icon/icon-pencil.png" alt="" />
  42. </template>
  43. </el-input>
  44. <div class="divider" />
  45. <!-- 语音内容 -->
  46. <el-input placeholder="请输入文案" @change="loadVoice" rows="4" type="textarea" v-model="textareaContent"></el-input>
  47. </div>
  48. </div>
  49. <!-- 播报声音 -->
  50. <div class="addText">
  51. <div class="addText-title">
  52. <img src="../../assets/icon/icon-sound.png" alt="" />
  53. 选择播报声音
  54. <!-- <span class="redWord">(必选)</span> -->
  55. </div>
  56. <!-- 只有一级没有二级时 soundChoose.subTitle-->
  57. <div v-if="soundChoose.speakTypeStr && !soundChoose2">{{ soundChoose.title }} — {{ soundChoose.speakTypeStr }}</div>
  58. <!-- 有二级时 -->
  59. <div v-if="soundChoose2.speakTypeStr">{{ soundChoose2.title }} — {{ soundChoose2.speakTypeStr }}</div>
  60. </div>
  61. <button class="chooseSound" @click="clickBottomTab(1)">
  62. <img class="img" src="../../assets/icon/icon-microphone.png" alt="" />
  63. <span>选择声音</span>
  64. </button>
  65. <!-- 合成按钮 -->
  66. <div class="makeVideo" @click="submit(1)">立即制作</div>
  67. <!-- 上移下移 -->
  68. <div class="upAndBottomBtn">
  69. <div class="moveLayer" :class="videoType == 2 ? 'moveLayer1' : ''">
  70. <div class="btnContent" @click="$refs.EditPosition.controlImg(3)">
  71. <!-- <img src="https://lanhu.oss-cn-beijing.aliyuncs.com/SketchPngf9bff6080bf29c6886ad614d479aebfb5fc41429c11c0bea78ca695a0f0e7388" alt="" /> -->
  72. <img src="../../assets/icon/icon-up.png" alt="" />
  73. 上移一层
  74. </div>
  75. </div>
  76. <div class="moveLayer below" :class="videoType == 2 ? 'below1' : ''">
  77. <div class="btnContent" @click="$refs.EditPosition.controlImg(4)">
  78. <!-- <img src="https://lanhu.oss-cn-beijing.aliyuncs.com/SketchPngde1a7c84fc47b26095186ff9ee7ec07d7fe7bcd2cde90f3178f4edb8cdb08bcd" alt="" /> -->
  79. <img src="../../assets/icon/icon-down.png" alt="" />
  80. 下移一层
  81. </div>
  82. </div>
  83. </div>
  84. </div>
  85. <!-- 底部导航栏 -->
  86. <div v-show="!contentLoading" class="bottom">
  87. <van-tabbar class="bottom-tab">
  88. <!-- <van-tabbar-item @click="clickBottomTab(1)">
  89. <span>选择声音</span>
  90. <template #icon="props">
  91. <img src="../../assets/icon/icon-microphone.png" />
  92. </template>
  93. </van-tabbar-item> -->
  94. <van-tabbar-item @click="clickBottomTab(2)">
  95. <span>更改背景</span>
  96. <template #icon="props">
  97. <img src="../../assets/icon/icon-background.png" />
  98. </template>
  99. </van-tabbar-item>
  100. <van-tabbar-item @click="clickBottomTab(3)">
  101. <span>添加素材</span>
  102. <template #icon="props">
  103. <img src="../../assets/icon/icon-material.png" />
  104. </template>
  105. </van-tabbar-item>
  106. <!-- <van-tabbar-item @click="clickBottomTab(4)" disabled>
  107. <span v-show="showSubtitle">取消字幕</span>
  108. <span v-show="!showSubtitle">添加字幕</span>
  109. <template #icon="props">
  110. <img src="../../assets/icon/icon-subtitle.png" />
  111. </template>
  112. </van-tabbar-item> -->
  113. </van-tabbar>
  114. </div>
  115. <!-- 合成视频进度条 -->
  116. <div v-if="showSynthesisDialog" class="synthesisDialog" @touchmove.prevent="noScroll">
  117. <div class="synthesisDialog-in">
  118. <van-progress :percentage="percentageData" color="#7264F5" define-back-color="#f0effe" stroke-width="12" class="progress" />
  119. <div class="synthesisDialog-text">正在生成视频,请耐心等待!</div>
  120. <van-button type="default" @click="$router.push('/myPage')">回到主页</van-button>
  121. </div>
  122. </div>
  123. <!-- 点击tab栏弹出框 -->
  124. <van-action-sheet class="tabSheet" v-model="showTabSheet">
  125. <!-- 声音 -->
  126. <div v-show="bottomTabActive == 1">
  127. <!-- 顶部文字 -->
  128. <div class="tabSheet-title">
  129. <div>
  130. <img class="img" src="../../assets/icon/icon-microphone.png" alt="" />
  131. <span v-show="!showSoundList2">选择声音</span>
  132. <span v-show="showSoundList2">选择情绪</span>
  133. </div>
  134. <div @click="showTabSheet = !showTabSheet" v-show="showSoundList2">
  135. <img class="yesImg" src="../../assets/icon/icon-yes.png" alt="" />
  136. </div>
  137. </div>
  138. <!-- 主要内容 -->
  139. <div class="tabSheet-content">
  140. <!-- tab栏 -->
  141. <van-tabs v-if="!showSoundList2" color="#7264F5" line-width="46" line-height="6" title-inactive-color="#666" title-active-color="#333" v-model="soundListAction" swipeable>
  142. <van-tab v-for="(item, index) in soundTabList" :title="item" :key="index">
  143. <!-- 展示页 -->
  144. <div class="vantLoadingBox" style="height: 150px" v-show="soundLoading1">
  145. <van-loading type="spinner" color="#52d4e5" class="vantLoading" />
  146. </div>
  147. <div class="list" v-show="!soundLoading1">
  148. <div v-if="textareaContent.length == 0">输入文案后才可以选择声音哦~ ~</div>
  149. <div v-if="soundItemList.length == 0 && textareaContent.length != 0">{{ soundTips ? soundTips : '试试输入长一点的句子吧~ ~' }}</div>
  150. <template v-if="soundItemList.length != 0">
  151. <div @click="clickSoundItem(index, item)" class="listItem" :class="{ active: soundItemListAction == index }" v-for="(item, index) in soundItemList" :key="index">
  152. <img src="../../assets/icon/icon-earphone.png" alt="" />
  153. <div>
  154. {{ item.subTitle }}-{{ item.title }}
  155. <br />
  156. {{ item.ageTypeStr }}
  157. </div>
  158. </div>
  159. </template>
  160. </div>
  161. </van-tab>
  162. </van-tabs>
  163. <!-- 二级列表显示 -->
  164. <div v-if="showSoundList2" class="SoundList2">
  165. <div class="vantLoadingBox" style="height: 150px" v-show="soundLoading2">
  166. <van-loading type="spinner" color="#52d4e5" class="vantLoading" />
  167. </div>
  168. <div class="list" v-show="!soundLoading2">
  169. <div v-if="soundItemList2.length == 0">暂无数据</div>
  170. <template v-if="soundItemList.length != 0">
  171. <div @click="clickSoundItem2(index, item)" class="listItem" :class="{ active: soundItemListAction2 == index }" v-for="(item, index) in soundItemList2" :key="index">
  172. <img src="../../assets/icon/icon-earphone.png" alt="" />
  173. <div>{{ item.title }}-{{ item.speakTypeStr }}</div>
  174. </div>
  175. </template>
  176. </div>
  177. </div>
  178. </div>
  179. </div>
  180. <!-- 背景 -->
  181. <div v-show="bottomTabActive == 2">
  182. <!-- 顶部文字 -->
  183. <div class="tabSheet-title">
  184. <div>
  185. <img class="img" src="../../assets/icon/icon-background.png" alt="" />
  186. 更改背景
  187. </div>
  188. <div @click="sureImg">
  189. <img class="yesImg" src="../../assets/icon/icon-yes.png" alt="" />
  190. </div>
  191. </div>
  192. <!-- 主要内容 -->
  193. <div class="tabSheet-content">
  194. <!-- tab栏 -->
  195. <div class="myTab">
  196. <div @click="changeShowBGIList(0)" class="myTab-item" :class="{ active: bjAction == 0 }">
  197. <img src="../../assets/icon/icon-folder@2x.png" alt="" />
  198. 背景库
  199. </div>
  200. <div @click="changeShowBGIList(1)" class="myTab-item" :class="{ active: bjAction == 1 }">
  201. <img src="../../assets/icon/icon-upload@2x.png" alt="" />
  202. 我上传的
  203. </div>
  204. </div>
  205. <!-- 展示 -->
  206. <!-- <div v-if="systemBGIList.length == 0">暂无数据</div> -->
  207. <div class="myTab-show">
  208. <div class="myTab-show-title">
  209. 图片
  210. <i></i>
  211. </div>
  212. <!-- <div class="vantLoadingBox" style="height: 50px" v-show="bjLoading1">
  213. <van-loading type="spinner" color="#52d4e5" class="vantLoading" />
  214. </div> -->
  215. <div class="myTab-show-list">
  216. <!-- 上传 -->
  217. <div v-if="bjAction == 1" class="myTab-show-list-upload">
  218. <img src="../../assets/icon/icon-upload@2x.png" alt="" />
  219. <!-- 上传背景组件 -->
  220. <CutImg @getMyBGIListApi="getMyBGIListApi" class="CutImg" :type="4" :videoType="videoType"></CutImg>
  221. </div>
  222. <!-- 图片列表 -->
  223. <div @click="chooseImg(index, 'bj')" class="myTab-show-list-item" v-for="(item, index) in showBGIList" :key="index">
  224. <div :class="{ 'myTab-show-list-active': bjImgAction == index }">
  225. <div class="whiteBox"></div>
  226. </div>
  227. <!-- 删除上传素材 -->
  228. <div @click="delImg(item.id)" class="icon-error" v-if="bjAction == 1 && bjImgAction == index">×</div>
  229. <!-- 中间图片 -->
  230. <img :src="item.material" alt="" />
  231. </div>
  232. </div>
  233. </div>
  234. </div>
  235. </div>
  236. <!-- 素材 -->
  237. <div v-show="bottomTabActive == 3">
  238. <!-- 顶部文字 -->
  239. <div class="tabSheet-title">
  240. <div>
  241. <img class="img" src="../../assets/icon/icon-material.png" alt="" />
  242. 添加素材
  243. </div>
  244. <div @click="sureImg">
  245. <img class="yesImg" src="../../assets/icon/icon-yes.png" alt="" />
  246. </div>
  247. </div>
  248. <!-- 主要内容 -->
  249. <div class="tabSheet-content">
  250. <!-- tab栏 -->
  251. <div class="myTab">
  252. <div @click="changeShowBGIList(2)" class="myTab-item" :class="{ active: scAction == 0 }">
  253. <img src="../../assets/icon/icon-folder@2x.png" alt="" />
  254. 素材库
  255. </div>
  256. <div @click="changeShowBGIList(3)" class="myTab-item" :class="{ active: scAction == 1 }">
  257. <img src="../../assets/icon/icon-upload@2x.png" alt="" />
  258. 我上传的
  259. </div>
  260. </div>
  261. <!-- 展示 -->
  262. <!-- <div v-if="showScList.length == 0">暂无数据</div> -->
  263. <div class="myTab-show">
  264. <div class="myTab-show-title">
  265. 图片
  266. <i></i>
  267. </div>
  268. <div class="myTab-show-list">
  269. <!-- 上传 -->
  270. <div v-if="scAction == 1" class="myTab-show-list-upload">
  271. <img src="../../assets/icon/icon-upload@2x.png" alt="" />
  272. <!-- 上传图片组件 -->
  273. <CutImg class="CutImg" :type="5" @getMyScListApi="getMyScListApi"></CutImg>
  274. </div>
  275. <!-- 图片列表 -->
  276. <div @click="chooseImg(index, 'sc')" class="myTab-show-list-item" v-for="(item, index) in showScList" :key="index">
  277. <div :class="{ 'myTab-show-list-active': scImgAction == index }">
  278. <div class="whiteBox"></div>
  279. </div>
  280. <!-- 删除上传素材 -->
  281. <div @click="delImg(item.id)" class="icon-error" v-if="scAction == 1 && scImgAction == index">×</div>
  282. <!-- 中间图片 -->
  283. <img :src="item.material" alt="" />
  284. </div>
  285. </div>
  286. </div>
  287. </div>
  288. </div>
  289. </van-action-sheet>
  290. <!-- 试听的mp3 -->
  291. <audio autoplay :src="audioUrl"></audio>
  292. <!-- 切图 -->
  293. <!-- <CutImg
  294. ref="CutImgBg"
  295. id="CutImgBg"
  296. @getMyBGIListApi="getMyBGIListApi"
  297. class="CutImg"
  298. :type="4"
  299. :videoType="videoType"
  300. ></CutImg> -->
  301. </div>
  302. </template>
  303. <script>
  304. // 组件
  305. import Vue from 'vue';
  306. import { Toast, Dialog } from 'vant';
  307. import { mapState, mapActions } from 'vuex';
  308. import HeadTop from './../../components/common/head.vue';
  309. import CutImg from '../../components/CutImg.vue';
  310. import EditPosition from '../../components/editPosition.vue';
  311. // 工具
  312. import { scrollToID } from '../../utils';
  313. // 语言检测插件
  314. import { franc } from 'franc';
  315. // 接口
  316. import {
  317. doCreateVideo,
  318. doFindVideoById,
  319. getVoiceList, // 获取声音列表,废弃
  320. getBackGroundList,
  321. doFindInviteCode,
  322. saveOrUpdateUserVideo
  323. } from '@/api/generateVideo';
  324. import { videoDetial, voiceList, voiceList2Api, systemBGIListApi, myBGIListApi, systemScListApi, myScListApi, delImgApi } from '@/api/editModel';
  325. import { getModelDetailById } from '../../api/getPaper.js';
  326. Vue.use(-Toast);
  327. export default {
  328. components: {
  329. HeadTop,
  330. CutImg,
  331. EditPosition
  332. },
  333. data() {
  334. return {
  335. contentLoading: true,
  336. soundLoading1: true,
  337. soundLoading2: true,
  338. bjLoading1: true,
  339. bjLoading2: true,
  340. scLoading1: true,
  341. scLoading2: true,
  342. soundTips: '',
  343. timer: null,
  344. id: null,
  345. timeOuter: null,
  346. percentageData: 1, // 进度条的值
  347. pageNum: 1,
  348. pageSize: 20,
  349. proportion: null, //编辑页面的比例
  350. videoType: null, //判断横屏2还是竖屏1
  351. audioUrl: null, // 声音试听
  352. inPage: false,
  353. imgUrl: false, // 背景图
  354. materialList: {
  355. BGI: {},
  356. scList: [],
  357. virtual: {}
  358. }, // 传给组件的素材,背景,数字人数据
  359. personMouldId: null, //选择数字人id
  360. mouldSmId: null,
  361. saveID: null, // 作品id
  362. inputTitle: '您的新数字人', // 作品标题
  363. textareaContent: '', // 输入框内容
  364. //底部
  365. bottomTabActive: 2, // 底部导航高亮
  366. showSubtitle: false, // 是否展示字幕
  367. showSynthesisDialog: false, //合成进度条窗口显示隐藏
  368. showTabSheet: false, //tab栏弹出框显隐
  369. showSoundList2: false, //声音的二级显隐
  370. soundTabList: ['全部'], // 声音tab栏标题
  371. soundListAction: -1, //声音tab栏标题高亮
  372. soundItemList: [], // 声音展示一级列表
  373. soundItemList2: [], // 声音展示二级列表
  374. soundItemListAction: -1, // 声音展示列表高亮
  375. soundItemListAction2: -1, // 声音展示列表高亮二级
  376. soundChoose: {}, //选中的音频
  377. soundChoose2: {}, //选中的音频二级
  378. //编辑
  379. bjAction: 0, // 背景:素材库和上传高亮
  380. bjImgAction: -1, // 选中背景图高亮
  381. scAction: 0, // 素材:素材库和上传高亮
  382. scImgAction: -1, // 选中素材图高亮
  383. showBGIList: [], // 渲染时代替下面2个列表
  384. systemBGIList: [], // 背景库列表
  385. myBGIList: [], // 我上传的背景库列表
  386. showScList: [], // 渲染时代替下面2个列表
  387. systemScList: [], // 素材库列表
  388. myScList: [] // 我上传的素材库列表
  389. };
  390. },
  391. computed: {
  392. ...mapState({
  393. characters: state => state.publicObj.characters
  394. })
  395. },
  396. methods: {
  397. ...mapActions(['setCharacters']),
  398. // aaa() {
  399. // console.log('aaa')
  400. // this.$nextTick(() => {
  401. // // document.getDetailById
  402. // // this.$refs.CutImgBg.$refs.uploader.clickUpload()
  403. // this.$refs.CutImgBg.$refs.uploader.beforeRead()
  404. // })
  405. // },
  406. // 禁止滚动
  407. noScroll(e) {
  408. e.preventDefault();
  409. },
  410. // 点击底部tab栏
  411. clickBottomTab(index) {
  412. if (index == 1) {
  413. if (this.textareaContent == 0) {
  414. Toast.fail('输入文案后才可以选择声音哦~~');
  415. return;
  416. }
  417. this.showSoundList2 = false;
  418. }
  419. if (index != 4) {
  420. this.bottomTabActive = index;
  421. if (this.textareaContent.length == 0) {
  422. this.soundItemList = []; //清空处理
  423. this.soundItemList2 = []; //清空处理
  424. }
  425. console.log(this.bottomTabActive);
  426. this.showTabSheet = !this.showTabSheet;
  427. } else {
  428. //字幕切换
  429. this.showSubtitle = !this.showSubtitle;
  430. }
  431. },
  432. // 获取声音列表
  433. async loadVoice() {
  434. this.soundTips = '';
  435. if (this.textareaContent.length != 0) {
  436. const language = franc(this.textareaContent);
  437. console.log(language, '语种');
  438. const data = {
  439. personMouldId: this.personMouldId,
  440. paperwork: this.textareaContent
  441. };
  442. try {
  443. this.soundLoading1 = true;
  444. const res = await voiceList(data);
  445. console.log(res, '获取声音列表');
  446. this.soundItemList = res.data.list;
  447. this.soundLoading1 = false;
  448. } catch (error) {
  449. this.soundItemList = [];
  450. if (error.message == '暂不支持该语种') {
  451. this.soundTips = error.message;
  452. }
  453. this.soundLoading1 = false;
  454. console.log(error, 'error');
  455. Toast.fail(error.message);
  456. }
  457. } else {
  458. Toast('您还没有输入文案');
  459. }
  460. },
  461. // 点击声音列表中的某一项
  462. async clickSoundItem(index, item) {
  463. if (this.soundItemListAction != index) {
  464. this.soundItemListAction = index; //高亮
  465. this.soundChoose = item;
  466. this.showSoundList2 = true;
  467. this.soundLoading2 = true;
  468. const res = await voiceList2Api(item.id);
  469. let list = res.data.subVoiceMould ? res.data.subVoiceMould : [];
  470. console.log(list);
  471. let obj = JSON.parse(JSON.stringify(res));
  472. delete obj.data.subVoiceMould;
  473. let list2 = [{ ...obj.data }, ...list];
  474. this.soundItemList2 = list2 || [];
  475. this.soundLoading2 = false;
  476. // console.log(this.soundItemList2)
  477. // this.audioUrl = res.data.videoUrl
  478. } else {
  479. this.soundItemListAction = -1;
  480. this.soundChoose = {};
  481. }
  482. },
  483. // 点击声音列表中的某一项2级
  484. async clickSoundItem2(index, item) {
  485. if (this.soundItemListAction2 != index) {
  486. this.soundItemListAction2 = index; //高亮
  487. this.soundChoose2 = item;
  488. // 得到试听文件
  489. const res = await videoDetial(item.exampleVideoId);
  490. this.audioUrl = res.data.videoUrl;
  491. } else {
  492. this.soundItemListAction2 = -1;
  493. this.soundChoose2 = {};
  494. }
  495. },
  496. // 提交合成视频
  497. submit(type) {
  498. // type代表时保存还是点击生成视频按钮
  499. // 组装参数
  500. console.log(this.soundChoose.id);
  501. // 素材列表处理
  502. const scList = this.materialList.scList.map(item => {
  503. return {
  504. id: item.id,
  505. type: 5,
  506. material: item.material,
  507. x: item.x,
  508. y: item.y,
  509. z: item.z,
  510. w: item.w,
  511. h: item.h
  512. };
  513. });
  514. // 数字人处理
  515. const shuziren = {
  516. id: this.materialList.virtual.id,
  517. type: 1,
  518. material: this.materialList.virtual.material,
  519. x: this.materialList.virtual.x,
  520. y: this.materialList.virtual.y,
  521. z: this.materialList.virtual.z,
  522. w: this.materialList.virtual.w,
  523. h: this.materialList.virtual.h
  524. };
  525. const data = {
  526. id: this.id,
  527. videoType: this.videoType, //横屏竖屏
  528. personMouldId: this.materialList.virtual.id, //数字人id
  529. voiceMouldIds: [this.soundChoose2.id ? this.soundChoose2.id : this.soundChoose.id], //声音id
  530. title: this.inputTitle, //标题
  531. paperwork: this.textareaContent, //语音内容
  532. backgroundId: this.materialList.BGI.id + '', //背景id
  533. personJson: JSON.stringify(shuziren), // 数字人
  534. materialAllJson: JSON.stringify([...scList]) // 素材
  535. };
  536. console.log(data, '最终提交的参数');
  537. if (type == 1) {
  538. Toast.loading({
  539. duration: 5000,
  540. message: '加载中...',
  541. forbidClick: true
  542. });
  543. if (!this.textareaContent) {
  544. Toast.fail('请输入文案内容!');
  545. return;
  546. }
  547. // 当没有选择声音参数时
  548. if (!this.soundChoose.id) {
  549. Toast.fail('请选择声音!');
  550. return;
  551. }
  552. // 当没有选择声音参数时
  553. // if (!this.soundChoose2.id) {
  554. // Toast.fail('请选择声音!');
  555. // return;
  556. // }
  557. // if (!this.inputTitle) {
  558. // Toast.fail('请输入文案标题!')
  559. // return
  560. // }
  561. }
  562. // 先保存草稿,里面再调生成视频的接口
  563. this.saveOrUpdate(data, type);
  564. },
  565. /**
  566. * @description:保存或修改用户作品
  567. */
  568. async saveOrUpdate(data, type) {
  569. console.log(data);
  570. try {
  571. const res = await saveOrUpdateUserVideo(data);
  572. console.log(res, '保存或修改用户作品');
  573. // this.createVideo({ id: this.saveID })
  574. if (type == 1) {
  575. this.createVideo({ id: this.$route.query.id });
  576. }
  577. } catch (error) {
  578. if (error.message != '视频生成中') {
  579. console.log(error, 'error');
  580. Toast.fail(error.message);
  581. }
  582. }
  583. },
  584. /**
  585. * @description:生成视频
  586. */
  587. async createVideo(data) {
  588. let that = this;
  589. try {
  590. const res = await doCreateVideo(data);
  591. console.log(res, '生成视频');
  592. Toast.success('提交成功!');
  593. // *#06#
  594. that.showSynthesisDialog = true; //显示进度条
  595. this.timeOuter = setTimeout(() => {
  596. this.isShowCover = true;
  597. }, 2000);
  598. that.timer = setInterval(() => {
  599. if (that.percentageData < 98) {
  600. that.percentageData += 1;
  601. } else {
  602. that.percentageData == 98;
  603. }
  604. // 重复调取此接口直到videoStatus == 2 || 3
  605. this.getVideo(that.$route.query.id);
  606. // if (this.timerOver) {
  607. // clearInterval(timer)
  608. // this.isShowCover = false
  609. // }
  610. }, 1000);
  611. } catch (error) {
  612. console.log(error, 'error');
  613. Toast.fail(error.message);
  614. }
  615. },
  616. /**
  617. * @description:通过id获取视频
  618. */
  619. async getVideo(id) {
  620. try {
  621. const res = await doFindVideoById(id);
  622. console.log(res, '通过id获取视频');
  623. if (res.data.videoStatus == 2) {
  624. this.percentageData == 99;
  625. this.showSynthesisDialog = false; //隐藏进度条
  626. this.percentageData = 0;
  627. clearInterval(this.timer);
  628. this.timer = null;
  629. this.isShowCover = false;
  630. clearTimeout(this.timeOuter);
  631. Toast.success('视频生成成功!');
  632. const url = res.data.videoPathUri + res.data.videoPath;
  633. console.log(url, 'url');
  634. this.$router.push({
  635. // path: '/downloadVideo',
  636. path: '/videoDownload',
  637. query: {
  638. id: this.$route.query.id,
  639. videoId: res.data.videoId,
  640. videoUrl: url
  641. }
  642. });
  643. // this.timerOver = true
  644. return;
  645. } else if (res.data.videoStatus == 3) {
  646. console.log(res.data.videoStatus, '看看id是不是3');
  647. this.showSynthesisDialog = false; //隐藏进度条
  648. this.percentageData = 0;
  649. Toast.fail(`视频生成失败!失败原因:${res.data.videoMsg}`);
  650. // this.timerOver = true
  651. clearTimeout(this.timer);
  652. this.timer = null;
  653. // clearTimeout(this.timeOuter)
  654. this.isShowCover = false;
  655. return;
  656. }
  657. } catch (error) {
  658. console.log(error, 'error');
  659. Toast.fail(error.message);
  660. }
  661. },
  662. // 根据作品ID获取信息
  663. async getDetailById(id) {
  664. try {
  665. this.contentLoading = true;
  666. const res = await getModelDetailById(id);
  667. // console.log(JSON.parse(res.data.personMouldSm))
  668. console.log();
  669. this.materialList.BGI = JSON.parse(res.data.backgroundSm) || {};
  670. // this.materialList.BGI.id = JSON.parse(res.data.backgroundSm).id + '';
  671. this.materialList.BGI.id = res.data.backgroundId + '';
  672. this.materialList.scList = res.data.materialAllJson ? JSON.parse(res.data.materialAllJson) : [];
  673. this.materialList.virtual = JSON.parse(res.data.personJson) || {};
  674. if (!this.materialList.virtual.w) {
  675. this.materialList.virtual = {
  676. ...this.materialList.virtual,
  677. x: 100,
  678. y: 0,
  679. z: 0,
  680. w: 1,
  681. h: 1
  682. };
  683. }
  684. this.videoType = res.data.videoType;
  685. this.id = res.data.id;
  686. // this.imgUrl = res.data.personMould.coverImg
  687. this.personMouldId = res.data.personMouldId;
  688. this.mouldSmId = res.data.personMouldSmId;
  689. this.inputTitle = res.data.title ? res.data.title : '您的新数字人';
  690. this.textareaContent = res.data.paperwork || '';
  691. this.soundChoose.id = res.data.voiceMouldId;
  692. this.soundChoose.mouldSmId = res.data.voiceMouldSmId;
  693. // console.log(res.data.voiceMouldSm, 111111111111111);
  694. this.soundChoose.title = res.data.voiceMouldSm ? JSON.parse(res.data.voiceMouldSm).title : '';
  695. this.soundChoose2.subTitle = res.data.voiceMouldSm ? JSON.parse(res.data.voiceMouldSm).subTitle : '';
  696. this.soundChoose2.title = res.data.voiceMouldSm ? JSON.parse(res.data.voiceMouldSm).title : '';
  697. this.soundChoose2.speakTypeStr = res.data.voiceMouldSm ? JSON.parse(res.data.voiceMouldSm).speakTypeStr : '';
  698. this.soundChoose2.id = res.data.voiceMouldSm ? JSON.parse(res.data.voiceMouldSm).id : '';
  699. // console.log(this.soundChoose.title, this.soundChoose2.speakTypeStr, '112233');
  700. if (this.textareaContent.length != 0) {
  701. await this.loadVoice(); // 获取音频列表
  702. }
  703. this.soundItemListAction = this.soundItemList.findIndex(item => {
  704. return item.id == this.soundChoose.id;
  705. }); //高亮处理
  706. this.contentLoading = false;
  707. // backgroundMouldId: '', // 背景id
  708. // backgroundMouldSmId: '', //背景标识
  709. // 如果视频生成了
  710. // if ([2, 4, 5, 6].includes(res.data.videoStatus)) {
  711. // this.$router.push({
  712. // // path: '/downloadVideo',
  713. // path: '/videoDownload',
  714. // query: {
  715. // id: this.$route.query.id
  716. // }
  717. // });
  718. // return;
  719. // }
  720. // if ([1].includes(res.data.videoStatus)) {
  721. // this.$router.push('/myPage');
  722. // return;
  723. // }
  724. } catch (error) {
  725. console.log(error, 'error');
  726. Toast.fail(error.message);
  727. }
  728. },
  729. // 点击选中背景图或者素材
  730. chooseImg(index, type) {
  731. if (type == 'bj') {
  732. if (this.bjImgAction == -1 || this.bjImgAction != index) {
  733. this.bjImgAction = index;
  734. } else if (this.bjImgAction == index) {
  735. this.bjImgAction = -1;
  736. }
  737. }
  738. if (type == 'sc') {
  739. if (this.scmgAction == -1 || this.scImgAction != index) {
  740. this.scImgAction = index;
  741. } else if (this.scImgAction == index) {
  742. this.scImgAction = -1;
  743. }
  744. }
  745. },
  746. // 点击对钩确定背景或者素材图
  747. sureImg() {
  748. let that = this;
  749. // 背景
  750. if (this.bottomTabActive == 2 && this.bjImgAction != -1) {
  751. // Dialog.confirm({
  752. // // title: '退出登录',
  753. // message: '您确定要用这张背景图吗?'
  754. // })
  755. // .then(() => {
  756. if (that.bjAction == 0) {
  757. that.materialList.BGI = that.systemBGIList.find((item, index) => {
  758. return index == that.bjImgAction;
  759. });
  760. } else if (that.bjAction == 1) {
  761. that.materialList.BGI = that.myBGIList.find((item, index) => {
  762. return index == that.bjImgAction;
  763. });
  764. }
  765. this.showTabSheet = false;
  766. // })
  767. // .catch(() => {
  768. // console.log('false')
  769. // this.showTabSheet = false
  770. // return
  771. // })
  772. }
  773. // 素材
  774. else if (this.bottomTabActive == 3 && this.scImgAction != -1) {
  775. // Dialog.confirm({
  776. // // title: '退出登录',
  777. // message: '您确定要用这张素材图吗?'
  778. // })
  779. // .then(() => {
  780. if (that.scAction == 0) {
  781. let scItem = that.systemScList.find((item, index) => {
  782. return index == that.scImgAction;
  783. });
  784. that.materialList.scList.push({
  785. ...scItem,
  786. x: 0,
  787. y: 0,
  788. z: 0,
  789. w: 1,
  790. h: 1
  791. });
  792. } else if (that.scAction == 1) {
  793. let scItem = that.myScList.find((item, index) => {
  794. return index == that.scImgAction;
  795. });
  796. that.materialList.scList.push({
  797. ...scItem,
  798. x: 0,
  799. y: 0,
  800. z: 0,
  801. w: 1,
  802. h: 1
  803. });
  804. }
  805. this.showTabSheet = false;
  806. // })
  807. // .catch(() => {
  808. // console.log('false')
  809. // this.showTabSheet = false
  810. // return
  811. // })
  812. }
  813. // 啥没选
  814. else {
  815. this.showTabSheet = false;
  816. }
  817. },
  818. // 切换背景图/素材图的展示列表
  819. changeShowBGIList(type) {
  820. if (type == 0) {
  821. this.bjAction = 0;
  822. this.bjImgAction = -1;
  823. this.showBGIList = this.systemBGIList;
  824. }
  825. if (type == 1) {
  826. this.bjAction = 1;
  827. this.bjImgAction = -1;
  828. this.showBGIList = this.myBGIList;
  829. }
  830. if (type == 2) {
  831. this.scAction = 0;
  832. this.scImgAction = -1;
  833. this.showScList = this.systemScList;
  834. }
  835. if (type == 3) {
  836. this.scAction = 1;
  837. this.scImgAction = -1;
  838. this.showScList = this.myScList;
  839. }
  840. },
  841. /**
  842. * @description:获取系统背景图
  843. */
  844. async getSystemBGIList() {
  845. try {
  846. this.bjLoading1 = true;
  847. const res = await systemBGIListApi(this.pageNum, this.pageSize, this.videoType);
  848. this.systemBGIList = res.data.list;
  849. this.showBGIList = this.systemBGIList;
  850. this.bjLoading1 = false;
  851. } catch (error) {
  852. console.log(error);
  853. this.bjLoading1 = false;
  854. }
  855. },
  856. /**
  857. * @description:获取我上传的背景图
  858. */
  859. async getMyBGIListApi() {
  860. try {
  861. this.bjLoading2 = true;
  862. const res = await myBGIListApi(this.pageNum, this.pageSize, this.videoType);
  863. this.myBGIList = res.data.list;
  864. this.bjLoading2 = false;
  865. } catch (error) {
  866. console.log(error);
  867. this.bjLoading2 = false;
  868. }
  869. },
  870. /**
  871. * @description:获取系统素材
  872. */
  873. async getSystemScList() {
  874. try {
  875. this.scLoading1 = true;
  876. const res = await systemScListApi(this.pageNum, this.pageSize);
  877. this.systemScList = res.data.list;
  878. this.showScList = this.systemScList;
  879. this.scLoading1 = false;
  880. } catch (error) {
  881. console.log(error);
  882. this.scLoading1 = false;
  883. }
  884. },
  885. /**
  886. * @description:获取我上传的素材
  887. */
  888. async getMyScListApi() {
  889. try {
  890. this.scLoading2 = true;
  891. const res = await myScListApi(this.pageNum, this.pageSize);
  892. this.myScList = res.data.list;
  893. this.scLoading2 = false;
  894. } catch (error) {
  895. console.log(error);
  896. this.scLoading2 = false;
  897. }
  898. },
  899. /**
  900. * @description:删除上传的背景或素材
  901. */
  902. async delImg(id) {
  903. Dialog.confirm({
  904. message: '确认删除吗?'
  905. })
  906. .then(async () => {
  907. const res = await delImgApi(id);
  908. if (this.bottomTabActive == 2) {
  909. await this.getMyBGIListApi();
  910. this.changeShowBGIList(1);
  911. }
  912. if (this.bottomTabActive == 3) {
  913. await this.getMyScListApi();
  914. this.changeShowBGIList(3);
  915. }
  916. })
  917. .catch(() => {});
  918. },
  919. go(url) {
  920. this.$router.push(url);
  921. }
  922. },
  923. created() {},
  924. async mounted() {
  925. this.inPage = true;
  926. scrollToID('top');
  927. await this.getDetailById(this.$route.query.id);
  928. this.getSystemBGIList();
  929. this.getMyBGIListApi();
  930. this.getSystemScList();
  931. this.getMyScListApi();
  932. const elementWidth = document.getElementById('editPosition').clientWidth;
  933. console.log(elementWidth);
  934. // 根据横竖屏来确定比例 1竖2横
  935. if (this.videoType == 1) {
  936. this.proportion = 1080 / elementWidth;
  937. console.log(this.proportion);
  938. } else if (this.videoType == 2) {
  939. this.proportion = 1920 / elementWidth;
  940. console.log(this.proportion);
  941. }
  942. },
  943. async beforeDestroy() {
  944. this.timeOuter = null; // 清除定时器
  945. clearInterval(this.timer);
  946. this.timer = null; // 清除定时器
  947. await this.submit(2); // 保存草稿
  948. console.log('保存了');
  949. }
  950. };
  951. </script>
  952. <style lang="scss" scoped>
  953. .chooseSound {
  954. position: absolute;
  955. left: 50%;
  956. transform: translateX(-50%);
  957. margin-top: 10px;
  958. width: 225px;
  959. height: 50px;
  960. text-align: center;
  961. font-size: 20px;
  962. line-height: 50px;
  963. border: 1px solid #85a5f9;
  964. .img {
  965. margin-top: -3px;
  966. margin-right: 3px;
  967. width: 16px;
  968. height: 16px;
  969. }
  970. }
  971. .editPosition {
  972. position: relative;
  973. // transform: scale(0.2);
  974. width: 216px;
  975. height: 384px;
  976. // width: 1080px;
  977. // height: 1920px;
  978. border-radius: 12px;
  979. overflow: hidden;
  980. background-color: pink;
  981. }
  982. .verticalmodel {
  983. width: 384px !important;
  984. height: 216px !important;
  985. // width: 1920px !important;
  986. // height: 1080px !important;
  987. margin-bottom: 50px;
  988. }
  989. .CutImg {
  990. position: absolute;
  991. top: 0;
  992. left: 0;
  993. width: 100%;
  994. height: 100%;
  995. }
  996. .page {
  997. // transform会导致其子元素固定定位失效
  998. // transform: translateX(30%);
  999. opacity: 0;
  1000. transition: all 0.5s; // global-transition
  1001. &.active {
  1002. opacity: 1;
  1003. // transform: translateX(0);
  1004. }
  1005. }
  1006. .content {
  1007. position: relative;
  1008. margin-top: 10px;
  1009. padding: 0 10px;
  1010. padding-bottom: 190px;
  1011. .shouModelImg {
  1012. display: flex;
  1013. position: relative;
  1014. justify-content: center;
  1015. width: 100%;
  1016. img {
  1017. width: 200px;
  1018. height: 351px;
  1019. border-radius: 12px;
  1020. }
  1021. &-subtitle {
  1022. position: absolute;
  1023. top: 220px;
  1024. left: 50%;
  1025. transform: translateX(-50%);
  1026. padding: 2px 6px;
  1027. width: 160px;
  1028. height: 24px;
  1029. line-height: 20px;
  1030. background: rgba(0, 0, 0, 0.5);
  1031. font-size: 14px;
  1032. color: #fff;
  1033. border-radius: 3px;
  1034. }
  1035. }
  1036. .addText {
  1037. display: flex;
  1038. justify-content: space-between;
  1039. margin-top: 20px;
  1040. &-title {
  1041. font-size: 16px;
  1042. font-weight: 600;
  1043. color: #000;
  1044. img {
  1045. width: 24px;
  1046. height: 24px;
  1047. margin-right: 5px;
  1048. }
  1049. }
  1050. }
  1051. .textInput {
  1052. margin-top: 10px;
  1053. padding: 1px;
  1054. width: 100%;
  1055. background: linear-gradient(225deg, rgba(81, 217, 202, 1), rgba(114, 100, 245, 1));
  1056. border-radius: 6px;
  1057. &-in {
  1058. width: 100%;
  1059. height: 100%;
  1060. background: #fff;
  1061. border-radius: 6px;
  1062. ::v-deep .el-input-group__append {
  1063. padding: 0;
  1064. }
  1065. img {
  1066. float: right;
  1067. width: 16px;
  1068. height: 16px;
  1069. margin: 10px;
  1070. }
  1071. }
  1072. .divider {
  1073. transform: scaleY (0.25);
  1074. width: 100%;
  1075. height: 1px;
  1076. border-top: 1px solid;
  1077. border-image: linear-gradient(225deg, rgba(81, 217, 202, 1), rgba(114, 100, 245, 1)) 1 1;
  1078. }
  1079. ::v-deep .el-input__inner {
  1080. border: none;
  1081. background-color: #faf9fe;
  1082. }
  1083. ::v-deep .el-textarea__inner {
  1084. border: none;
  1085. background-color: #faf9fe;
  1086. }
  1087. }
  1088. .makeVideo {
  1089. position: fixed;
  1090. bottom: 70px;
  1091. left: 50%;
  1092. transform: translateX(-50%);
  1093. // margin: 15px 20px 0;
  1094. width: 325px;
  1095. height: 50px;
  1096. text-align: center;
  1097. font-size: 20px;
  1098. line-height: 50px;
  1099. color: #fff;
  1100. background: linear-gradient(316deg, #6ee4d7 0%, #37c4f1 32%, #a49afc 100%);
  1101. border-radius: 25px;
  1102. }
  1103. .upAndBottomBtn {
  1104. .moveLayer {
  1105. position: absolute;
  1106. display: flex;
  1107. align-items: center;
  1108. justify-content: center;
  1109. top: 20%;
  1110. right: 5px;
  1111. // padding-left: 10px;
  1112. width: 70px;
  1113. height: 22px;
  1114. font-size: 10px;
  1115. line-height: 28px;
  1116. text-align: center;
  1117. box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
  1118. background-color: rgba(255, 255, 255, 1);
  1119. border-radius: 11px;
  1120. }
  1121. .moveLayer1 {
  1122. top: 35% !important;
  1123. left: 20% !important;
  1124. }
  1125. img {
  1126. vertical-align: middle;
  1127. width: 10px;
  1128. height: 11px;
  1129. margin: 1px 0 2px 0;
  1130. }
  1131. .below {
  1132. top: 25%;
  1133. }
  1134. .below1 {
  1135. top: 35% !important;
  1136. left: 60% !important;
  1137. }
  1138. .active {
  1139. // opacity: 0.5;
  1140. }
  1141. }
  1142. }
  1143. .bottom {
  1144. ::v-deep .van-tabbar-item {
  1145. color: rgba(51, 51, 51, 1) !important;
  1146. font-size: 10px !important;
  1147. }
  1148. }
  1149. .synthesisDialog {
  1150. position: fixed;
  1151. top: 0;
  1152. left: 0;
  1153. // width: 100vw;
  1154. // height: 110vh;
  1155. width: 100%;
  1156. height: 100%;
  1157. z-index: 99999;
  1158. color: #333;
  1159. background: rgba(0, 0, 0, 0.5);
  1160. overflow: hidden;
  1161. ::v-deep .el-progress-bar {
  1162. }
  1163. &-in {
  1164. position: absolute;
  1165. top: 40%;
  1166. left: 50%;
  1167. transform: translate(-50%);
  1168. padding: 0 15px;
  1169. padding-top: 40px;
  1170. width: 315px;
  1171. height: 145px;
  1172. background-color: #fff;
  1173. border-radius: 12px;
  1174. ::v-deep .van-button {
  1175. float: right;
  1176. height: 40px;
  1177. color: #fff;
  1178. border-radius: 40px;
  1179. background: linear-gradient(316deg, #6ee4d7 0%, #37c4f1 32%, #a49afc 100%);
  1180. }
  1181. .progress {
  1182. width: 280px;
  1183. ::v-deep .el-progress__text {
  1184. margin-left: 15px;
  1185. }
  1186. }
  1187. }
  1188. &-text {
  1189. margin-top: 10px;
  1190. font-size: 12px;
  1191. }
  1192. }
  1193. .tabSheet {
  1194. height: 280px;
  1195. padding-bottom: 0px;
  1196. background-color: #f9f9f9;
  1197. &-title {
  1198. display: flex;
  1199. justify-content: space-between;
  1200. padding: 0 10px;
  1201. height: 40px;
  1202. font-size: 13px;
  1203. line-height: 40px;
  1204. background-color: #fff;
  1205. .img {
  1206. margin-top: -3px;
  1207. margin-right: 3px;
  1208. width: 16px;
  1209. height: 16px;
  1210. }
  1211. .yesImg {
  1212. margin-top: -3px;
  1213. width: 24px;
  1214. height: 16px;
  1215. }
  1216. }
  1217. &-content {
  1218. height: 220px;
  1219. padding: 0 10px;
  1220. background-color: #f9f9f9;
  1221. ::v-deep .van-tab {
  1222. background-color: #f9f9f9;
  1223. }
  1224. ::v-deep .van-tab--active {
  1225. font-size: 17px;
  1226. font-weight: 700;
  1227. }
  1228. .list {
  1229. height: 170px;
  1230. overflow-y: scroll;
  1231. // scrollbar-width: none;
  1232. // -ms-overflow-style: none;
  1233. display: flex;
  1234. justify-content: space-between;
  1235. flex-wrap: wrap;
  1236. margin-top: 10px;
  1237. .listItem {
  1238. display: flex;
  1239. justify-content: space-between;
  1240. padding: 12px;
  1241. margin-bottom: 10px;
  1242. width: 170px;
  1243. height: 50px;
  1244. overflow: hidden;
  1245. background: rgba(186, 186, 189, 0.5);
  1246. border-radius: 24px;
  1247. color: #fff;
  1248. img {
  1249. width: 32px;
  1250. }
  1251. > div {
  1252. flex: 1;
  1253. margin-left: 12px;
  1254. }
  1255. }
  1256. .active {
  1257. background: #7264f5;
  1258. }
  1259. }
  1260. .list::-webkit-scrollbar {
  1261. width: 0;
  1262. }
  1263. }
  1264. .SoundList2 {
  1265. overflow: hidden;
  1266. height: 240px;
  1267. // padding: 10px 10px 10px;
  1268. padding-top: 10px;
  1269. &-title {
  1270. display: flex;
  1271. justify-content: space-between;
  1272. margin-bottom: 10px;
  1273. width: 100%;
  1274. .img {
  1275. width: 16px;
  1276. height: 16px;
  1277. }
  1278. .yesImg {
  1279. float: right;
  1280. margin-top: -3px;
  1281. margin-right: 3px;
  1282. width: 16px;
  1283. height: 16px;
  1284. margin-top: -3px;
  1285. width: 24px;
  1286. height: 16px;
  1287. }
  1288. }
  1289. .list {
  1290. height: 240px;
  1291. margin-top: 0px;
  1292. }
  1293. .list::-webkit-scrollbar {
  1294. width: 0;
  1295. display: none;
  1296. }
  1297. }
  1298. .SoundList2::-webkit-scrollbar {
  1299. width: 0;
  1300. display: none;
  1301. }
  1302. .myTab {
  1303. display: flex;
  1304. margin: 10px 0;
  1305. padding: 5px;
  1306. width: 100%;
  1307. height: 40px;
  1308. background-color: #eeeeee;
  1309. border-radius: 6px;
  1310. &-item {
  1311. width: 50%;
  1312. height: 30px;
  1313. font-size: 14px;
  1314. line-height: 30px;
  1315. text-align: center;
  1316. background-color: #eeeeee;
  1317. border-radius: 6px;
  1318. img {
  1319. width: 20px;
  1320. height: 16px;
  1321. margin-right: 8px;
  1322. }
  1323. }
  1324. .active {
  1325. background-color: #fff;
  1326. }
  1327. &-show {
  1328. width: 100%;
  1329. height: 170px;
  1330. &-title {
  1331. font-size: 16px;
  1332. i {
  1333. display: block;
  1334. margin-top: 4px;
  1335. margin-left: 3px;
  1336. width: 23px;
  1337. height: 3px;
  1338. background: #7264f5;
  1339. border-radius: 2px;
  1340. }
  1341. }
  1342. &-list {
  1343. height: 145px;
  1344. padding-left: 4px;
  1345. overflow-y: scroll;
  1346. display: flex;
  1347. justify-content: start;
  1348. flex-wrap: wrap;
  1349. &-item {
  1350. display: flex;
  1351. align-items: center;
  1352. position: relative;
  1353. margin-right: 6px;
  1354. margin-top: 10px;
  1355. width: 80px;
  1356. height: 142px;
  1357. z-index: 9;
  1358. background-color: #fff;
  1359. border-radius: 10px;
  1360. img {
  1361. // background: red;
  1362. width: 100%;
  1363. // width: 80px;
  1364. max-height: 142px;
  1365. border-radius: 12px;
  1366. }
  1367. .icon-error {
  1368. float: left;
  1369. position: absolute;
  1370. top: 5px;
  1371. right: 5px;
  1372. z-index: 99999;
  1373. display: block !important;
  1374. float: right;
  1375. width: 12px;
  1376. height: 12px;
  1377. line-height: 12px;
  1378. text-align: center;
  1379. color: #fff;
  1380. background: #666666;
  1381. border-radius: 6px;
  1382. }
  1383. &:nth-child(4n) {
  1384. // margin-right: 0px !important;
  1385. }
  1386. }
  1387. &-active {
  1388. position: absolute;
  1389. top: -3px;
  1390. left: -3px;
  1391. padding: 1px;
  1392. z-index: -1;
  1393. width: 86px;
  1394. height: 148px;
  1395. border-radius: 12px;
  1396. background: linear-gradient(225deg, rgba(81, 217, 202, 1), rgba(114, 100, 245, 1));
  1397. .whiteBox {
  1398. transition: all 0.5s;
  1399. width: 100%;
  1400. height: 100%;
  1401. background-color: #fff;
  1402. border-radius: 12px;
  1403. }
  1404. }
  1405. &-upload {
  1406. position: relative;
  1407. margin-right: 10px;
  1408. margin-top: 10px;
  1409. width: 80px;
  1410. height: 142px;
  1411. background: #ddd;
  1412. border-radius: 10px;
  1413. overflow: hidden;
  1414. img {
  1415. background-color: #fff;
  1416. position: absolute;
  1417. top: 50%;
  1418. left: 50%;
  1419. transform: translate(-50%, -50%);
  1420. }
  1421. input {
  1422. width: 100%;
  1423. height: 100%;
  1424. opacity: 0;
  1425. }
  1426. }
  1427. }
  1428. }
  1429. }
  1430. // 隐藏滚动条
  1431. .myTab-show-list::-webkit-scrollbar {
  1432. display: none;
  1433. }
  1434. }
  1435. </style>