index.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. <template>
  2. <div
  3. ref="wrapper"
  4. v-loading.lock="loading"
  5. element-loading-background="rgba(0, 0, 0, 0.8)"
  6. class="c-viewer"
  7. >
  8. <audio
  9. v-if="bgmUrl"
  10. ref="audio"
  11. :src="bgmUrl"
  12. :muted.prop="muted"
  13. autoplay
  14. @ended="onAudioEnded"
  15. @error="onAudioError"
  16. />
  17. <div
  18. v-if="hasAudio"
  19. class="l-flex--row c-tool"
  20. >
  21. <el-tooltip
  22. class="c-tool__item"
  23. content="音效"
  24. :hide-after="2000"
  25. >
  26. <div @click="toggleMute">
  27. <div
  28. class="o-wave"
  29. :class="{ muted }"
  30. >
  31. <span class="o-wave__line" />
  32. <span class="o-wave__line" />
  33. <span class="o-wave__line" />
  34. <span class="o-wave__line" />
  35. </div>
  36. </div>
  37. </el-tooltip>
  38. <el-tooltip
  39. v-if="hasNext"
  40. class="c-tool__item"
  41. content="切歌"
  42. :hide-after="2000"
  43. >
  44. <div @click="chooseBgm">
  45. <i class="o-next" />
  46. </div>
  47. </el-tooltip>
  48. <el-tooltip
  49. v-if="bgmUrl"
  50. class="c-tool__item"
  51. content="背景音乐"
  52. :hide-after="2000"
  53. >
  54. <div @click.stop="onClickWidget()">
  55. <svg-icon icon-class="list" />
  56. </div>
  57. </el-tooltip>
  58. </div>
  59. <div
  60. class="c-viewer__canvas has-bg"
  61. :style="[transformStyles, styles]"
  62. >
  63. <div
  64. class="c-viewer__background has-bg"
  65. :style="backgroundStyles"
  66. />
  67. <widget
  68. v-for="(item, index) in widgets"
  69. :key="`${item.type}${index}`"
  70. :node="item"
  71. @click.native.stop="onClickWidget(item)"
  72. />
  73. </div>
  74. <el-dialog
  75. title="数据"
  76. :visible.sync="dialogVisibleAssets"
  77. custom-class="c-dialog"
  78. :before-close="onCloseAssetsDialog"
  79. >
  80. <div
  81. v-if="sources"
  82. class="c-grid"
  83. >
  84. <div
  85. v-for="(source, index) in sources"
  86. :key="index"
  87. class="c-card u-pointer"
  88. @click="onView(source.keyName)"
  89. >
  90. <div class="c-card__content">
  91. <i
  92. v-if="isImage"
  93. class="o-image"
  94. :style="{ 'background-image': `url('${source.url}')` }"
  95. />
  96. <div
  97. v-else
  98. class="c-card__text u-ellipsis"
  99. >
  100. {{ source.name }}
  101. </div>
  102. </div>
  103. </div>
  104. </div>
  105. </el-dialog>
  106. <preview ref="preview" />
  107. </div>
  108. </template>
  109. <script>
  110. import { getThumbnailUrl } from '@/api/asset'
  111. import { AssetType } from '@/constant'
  112. import base from '../core/base'
  113. import Widget from '../core/widget/WidgetViewer.vue'
  114. import Preview from '@/components/Preview'
  115. export default {
  116. name: 'BigScreenViewer',
  117. components: {
  118. Widget,
  119. Preview
  120. },
  121. mixins: [base],
  122. data () {
  123. return {
  124. dialogVisibleAssets: false,
  125. isImage: false,
  126. sources: null
  127. }
  128. },
  129. methods: {
  130. onLoaded () {
  131. this.$message({
  132. type: 'info',
  133. message: '点击组件可查看媒资列表'
  134. })
  135. },
  136. onClickWidget (item) {
  137. const sources = item ? item.sources : this.node.bgm
  138. if (sources?.length > 1) {
  139. this.$muted = this.muted
  140. this.isImage = item?.type === 'CImage'
  141. if (this.isImage) {
  142. this.sources = sources.map(source => {
  143. return {
  144. ...source,
  145. url: getThumbnailUrl(source.keyName)
  146. }
  147. })
  148. } else {
  149. this.sources = sources
  150. if (!this.muted) {
  151. this.muted = true
  152. }
  153. }
  154. this.dialogVisibleAssets = true
  155. }
  156. },
  157. onCloseAssetsDialog () {
  158. this.muted = this.$muted
  159. this.sources = null
  160. this.dialogVisibleAssets = false
  161. },
  162. onView (keyName) {
  163. this.$refs.preview.show({
  164. type: this.isImage ? AssetType.IMAGE : AssetType.VIDEO,
  165. keyName
  166. })
  167. }
  168. }
  169. }
  170. </script>
  171. <style lang="scss" scoped>
  172. .c-viewer {
  173. height: 100%;
  174. overflow: hidden;
  175. &__canvas {
  176. position: relative;
  177. background-color: #000;
  178. overflow: hidden;
  179. &::before {
  180. content: "";
  181. position: absolute;
  182. top: 0;
  183. left: 0;
  184. right: 0;
  185. bottom: 0;
  186. background-color: currentColor;
  187. z-index: -1;
  188. }
  189. }
  190. &__background {
  191. position: absolute;
  192. top: 0;
  193. left: 0;
  194. right: 0;
  195. bottom: 0;
  196. z-index: -1;
  197. }
  198. }
  199. .c-tool {
  200. position: absolute;
  201. top: 0;
  202. left: 0;
  203. z-index: 9;
  204. &__item {
  205. display: inline-flex;
  206. justify-content: center;
  207. align-items: center;
  208. padding: 10px 16px;
  209. color: $gray;
  210. font-size: 16px;
  211. cursor: pointer;
  212. &:hover {
  213. background-color: #191d22;
  214. }
  215. &:active {
  216. background-color: darken(#191d22, 5%);
  217. }
  218. }
  219. }
  220. .c-card {
  221. display: inline-block;
  222. position: relative;
  223. background-color: rgba(0, 0, 0, 0.8);
  224. &__content {
  225. position: relative;
  226. padding-top: 60%;
  227. }
  228. &__name {
  229. position: absolute;
  230. left: 0;
  231. right: 0;
  232. bottom: 0;
  233. padding: 4px 6px;
  234. color: $gray;
  235. font-size: 14px;
  236. text-align: center;
  237. background-color: rgba(0, 0, 0, 0.6);
  238. }
  239. &__text {
  240. position: absolute;
  241. top: 50%;
  242. left: 8px;
  243. right: 8px;
  244. color: #fff;
  245. font-size: 14px;
  246. text-align: center;
  247. transform: translateY(-50%);
  248. }
  249. }
  250. .o-image {
  251. position: absolute;
  252. top: 0;
  253. left: 0;
  254. width: 100%;
  255. height: 100%;
  256. background-position: center;
  257. background-size: contain;
  258. background-repeat: no-repeat;
  259. }
  260. </style>