| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133 |
- <template>
- <div>
- <confirm-dialog
- ref="dialog"
- size="xl fixed"
- title="编辑模板"
- append-to-body
- @closed="onClosed"
- @confirm="onConfirm"
- >
- <template #default>
- <div class="l-flex__auto l-flex">
- <div class="l-flex__none l-flex--col c-viewer__asserts">
- <div class="l-flex__none l-flex--row c-viewer__count has-padding--h">
- <span class="l-flex__auto u-color--black u-font-size u-bold">
- 资源
- </span>
- <span class="l-flex__none u-color--info u-font-size--xs">
- {{ count }}
- </span>
- </div>
- <el-scrollbar
- class="l-flex__fill l-flex--col c-viewer__scrollbar"
- native
- >
- <div class="c-viewer__list">
- <div
- v-for="widget in layers"
- ref="widgetElements"
- :key="widget.id"
- class="c-sibling-item--v o-layer"
- :class="{ active: widget.id === selectedWidgetId }"
- @click="onWidgetClick(widget, $event)"
- >
- <widget-shortcut
- :widget="widget"
- @view="onView"
- />
- </div>
- <!-- 背景的设置-->
- <!-- <div-->
- <!-- v-if="hasRootAssets"-->
- <!-- ref="rootElement"-->
- <!-- key="root"-->
- <!-- class="c-sibling-item--v o-layer"-->
- <!-- :class="{ active: !selectedWidgetId }"-->
- <!-- @click="onRootClick"-->
- <!-- >-->
- <!-- <widget-shortcut-->
- <!-- :widget="node"-->
- <!-- :custom-style="backgroundStyles"-->
- <!-- source-key="bgm"-->
- <!-- background-->
- <!-- @view="onView"-->
- <!-- />-->
- <!-- </div>-->
- </div>
- </el-scrollbar>
- </div>
- <div
- v-if="isMedia"
- class="l-flex__auto l-flex"
- >
- <directory-tree
- class="l-flex__none c-sibling-item c-sidebar u-width--md"
- style="display:none;"
- :class="{ mask: isStream }"
- :option="directoryOption"
- @change="onAssetDirectoryChanged"
- />
- <grid-table
- ref="table"
- class="l-flex__none c-sibling-item far"
- style="width: 496px;"
- size="large"
- :schema="schema"
- :custom="isDir"
- @changed="onTableRefresh"
- >
- <template #header>
- <template v-if="isDir">
- <div class="l-flex__fill l-flex--row u-height">
- <i
- class="l-flex__none o-icon o-icon--hover el-icon-arrow-left u-bold u-pointer"
- @click="fileDir = null"
- />
- <div class="l-flex__fill u-ellipsis u-bold">
- {{ fileDir.name }}
- </div>
- </div>
- </template>
- </template>
- <grid-table-item v-slot="item">
- <media-card
- :asset="item"
- @click="onToggleAsset"
- >
- <el-checkbox
- v-model="item.selected"
- class="o-card__checkbox"
- />
- <i
- class="o-card__play el-icon-video-play has-active"
- @click.stop="onViewAsset(item)"
- />
- <i
- v-if="item.file.files"
- class="o-card__grid el-icon-s-grid has-active"
- @click.stop="onViewDir(item)"
- />
- <div
- v-else
- class="o-card__info u-font-size--xs"
- >
- {{ item.diff }}
- </div>
- </media-card>
- </grid-table-item>
- <div
- v-if="isDir"
- class="l-flex__auto c-sibling-item--v u-overflow-y--auto"
- >
- <div class="l-flex__none l-grid large">
- <media-card
- v-for="file in fileDir.files"
- :key="file.keyName"
- :asset="file"
- @click="onToggleAsset"
- >
- <el-checkbox
- v-model="file.selected"
- class="o-card__checkbox"
- />
- <i
- class="o-card__play el-icon-video-play has-active"
- @click.stop="onViewAsset(file)"
- />
- </media-card>
- </div>
- </div>
- </grid-table>
- <div class="l-flex__none l-flex--row c-transfer-area">
- <el-button
- type="primary"
- size="mini"
- :disabled="!hasSelectionAssets"
- @click="onAddAssets"
- >
- <i class="el-icon-arrow-right" />
- </el-button>
- </div>
- <div class="l-flex__fill l-flex--col">
- <template v-if="assets.length">
- <div class="l-flex__none l-flex--row right c-sibling-item--v u-font-size--sm u-color-black u-bold">
- <div class="c-sibling-item">
- {{ resourceSize }}
- </div>
- <div class="c-sibling-item">
- {{ statistics }}
- </div>
- </div>
- <div
- v-if="options.durationEditable"
- class="l-flex__none l-flex--row right c-sibling-item--v"
- >
- <div class="c-sibling-item u-color--info u-font-size--sm">
- 图片统一上播时长(s)
- </div>
- <el-input-number
- v-model="duration"
- class="c-sibling-item u-width--xs"
- size="small"
- title="上播时长(s)"
- controls-position="right"
- :min="1"
- :max="86400"
- step-strictly
- />
- <div
- class="c-sibling-item near o-button"
- @click="onSetImageDuration"
- >
- 设置
- </div>
- </div>
- <draggable
- v-model="assets"
- class="l-flex__fill c-sibling-item--v u-font-size--sm u-overflow-y--auto"
- handle=".mover"
- animation="300"
- @change="onDragChange"
- @end="onDragEnd"
- >
- <div
- v-for="(asset, index) in assets"
- :key="asset.key"
- class="l-flex--row c-sibling-item--v near"
- >
- <el-input
- ref="input"
- v-model="inputValues[index]"
- :value="index"
- class="l-flex__none c-sibling-item u-width--3xs o-draggable-input"
- @focus="clearInput(index)"
- @blur="restoreInput(index, asset)"
- @keyup.enter.native="onTargetIndexInput(index, asset)"
- />
- <draggable-item
- class="l-flex__fill c-sibling-item near"
- :item="asset"
- @view="onViewAsset"
- @del="onDelAsset(index)"
- />
- </div>
- </draggable>
- </template>
- <el-empty
- v-else
- class="l-flex__auto l-flex--row center"
- description="请添加资源"
- />
- </div>
- </div>
- <div
- v-else
- class="l-flex__auto l-flex--col"
- style="margin-left: 16px;"
- >
- <toolbar
- style="border-bottom: 1px solid #ccc"
- mode="simple"
- :editor="editor"
- :default-config="toolbarConfig"
- />
- <editor
- v-model="selectedWidget.text"
- mode="simple"
- style="height: 500px; overflow: hidden;"
- :default-config="editorConfig"
- @onCreated="onEditorCreated"
- @customPaste="onCustomPaste"
- />
- </div>
- <!-- 放在底层,用截图封面图片-->
- <div
- ref="canvas"
- style="position: absolute;top:20px;left: 20px;z-index: -1;"
- class="l-flex__none"
- :style="canvasStyles"
- >
- <div
- class="c-viewer__canvas has-bg"
- :style="[transformStyles, styles]"
- >
- <div
- class="c-viewer__background has-bg"
- :style="backgroundStyles"
- />
- <widget
- v-for="item in widgets"
- :key="item.id"
- :node="item"
- />
- </div>
- </div>
- </div>
- </template>
- </confirm-dialog>
- <preview-dialog
- ref="previewDialog"
- @closed="onClosedPreview"
- />
- </div>
- </template>
- <script>
- import {
- State,
- AssetTag,
- AssetTagInfo,
- AssetType,
- AssetTypeInfo
- } from '@/constant'
- import {
- parseDuration,
- getAssetDuration
- } from '@/utils'
- import { getAssetsByQuery } from '@/api/asset'
- import Draggable from 'vuedraggable'
- import {
- getTemplateProgram, updateProgramDraft
- } from '@/api/program'
- import { WidgetType } from '@/views/screen/material/program/ast/core/constant'
- import WidgetShortcut from '@/views/screen/material/program/ast/components/WidgetShortcut'
- import {
- Editor,
- Toolbar
- } from '@wangeditor/editor-for-vue'
- import '@wangeditor/editor/dist/css/style.css'
- import domToImage from 'dom-to-image'
- import mixin2 from '@/views/screen/material/program/ast/mixin2'
- import Widget from '@/views/screen/material/program/ast/core/widget/WidgetViewer'
- import {
- fix, getDuration, getUsedAssets, toJSON
- } from '@/views/screen/material/program/ast/core/utils'
- export default {
- name: 'TemplateAssetChooseDialog',
- components: {
- Draggable,
- WidgetShortcut,
- Editor,
- Toolbar,
- Widget
- },
- mixins: [mixin2],
- props: {
- title: {
- type: String,
- default: ''
- },
- transform: {
- type: Function,
- default: null
- },
- choosen: {
- type: Function,
- default: null
- }
- },
- data () {
- return {
- snapping: false,
- canvasStyles: null,
- inputValues: [],
- lastIndex: 0,
- types: [],
- directoryOption: null,
- fileDir: null,
- assets: [],
- tableAssets: [],
- duration: 10,
- options: {},
- isStream: false,
- selectedWidget: null, //
- program: null,
- isMedia: true,
- editor: null,
- richHtml: '',
- toolbarConfig: {
- toolbarKeys: [
- 'headerSelect',
- '|',
- 'bold',
- // 'color',
- // '|',
- // 'fontSize',
- // 'lineHeight',
- '|',
- 'justifyLeft',
- 'justifyCenter',
- 'justifyRight'
- ]
- },
- editorConfig: {
- placeholder: '请输入内容...'
- }
- }
- },
- computed: {
- // dialogTitle () {
- // return this.title || (this.types.length > 1 ? '请选择资源' : `请选择${AssetTypeInfo[this.types[0]]}`)
- // },
- layers () {
- return this.widgets.filter(this.hasAssets).slice().reverse()
- },
- count () {
- if (this.node) {
- return this.layers.length
- }
- return 0
- },
- selectedWidgetId () {
- return this.selectedWidget?.id
- },
- hasRootAssets () {
- if (this.node) {
- const { backgroundImage, bgm } = this.node
- return backgroundImage.length > 0 || bgm.length > 0
- }
- return false
- },
- schema () {
- return {
- pagination: {
- layout: 'prev,pager,next'
- },
- list: this.getAssetsByQuery,
- transform: this.transformAsset,
- condition: {
- pageSize: 18,
- status: State.AVAILABLE,
- tag: '',
- type: this.types.length > 1 ? '' : this.types[0]
- },
- filters: [
- {
- key: 'tag', type: 'select', options: [
- { value: AssetTag.AD, label: AssetTagInfo[AssetTag.AD] },
- { value: AssetTag.PUBLICITY, label: AssetTagInfo[AssetTag.PUBLICITY] },
- { value: AssetTag.LOCAL_PUBLICITY, label: AssetTagInfo[AssetTag.LOCAL_PUBLICITY] },
- { value: AssetTag.SHIM, label: AssetTagInfo[AssetTag.SHIM] }
- ], placeholder: '资源分类'
- },
- this.types.length > 1
- ? {
- key: 'type', type: 'select', options: this.types.map(type => {
- return {
- value: type,
- label: AssetTypeInfo[type]
- }
- }), placeholder: '资源类型'
- }
- : null,
- { key: 'originalName', type: 'search', placeholder: '资源名称' }
- ].filter(Boolean),
- isStream: false
- }
- },
- isDir () {
- return !!this.fileDir
- },
- hasSelectionAssets () {
- return this.isDir
- ? this.fileDir.files.some(({ selected }) => selected)
- : this.tableAssets.some(({ selected }) => selected)
- },
- statistics () {
- const length = this.assets.length
- return `共${length}条,总时长 ${parseDuration(this.assets.reduce((total, { duration }) => total + duration, 0), false)}`
- },
- resourceSize () {
- const uniqueAssets = Array.from(new Set(this.assets.map(asset => asset.keyName)))
- .map(keyName => this.assets.find(asset => asset.keyName === keyName))
- const totalSizeMB = (uniqueAssets.reduce((total, item) => total + parseInt(item.size), 0) / (1024 * 1024))
- if (totalSizeMB >= 1024) {
- const totalSizeGB = totalSizeMB / 1024
- return `资源包大小: ${totalSizeGB.toFixed(2)} GB`
- }
- return `资源包大小: ${totalSizeMB.toFixed(2)} MB`
- },
- mediaTypes () {
- return this.types.filter(type => type !== AssetType.STREAMING_MEDIA)
- }
- },
- watch: {
- selectedWidget () {
- this.node && setTimeout(() => {
- if (this.selectedWidget) {
- this.$refs.widgetElements?.find(element => element.classList.contains('active'))
- ?.scrollIntoView({ behavior: 'smooth', block: 'start' })
- } else if (this.hasRootAssets) {
- this.$refs.rootElement.scrollIntoView({ behavior: 'smooth', block: 'start' })
- }
- })
- }
- },
- mounted () {
- this.types = [AssetType.IMAGE, AssetType.VIDEO, AssetType.PPT, AssetType.DOC, AssetType.PDF]
- this.updateInputValues()
- },
- methods: {
- checkRatio () {
- if (this.canvasStyles) {
- return
- }
- const { width, height } = this.node
- if (width <= 960 && height <= 540) {
- this.canvasStyles = {}
- } else {
- const wScale = 960 / width
- const hScale = 540 / height
- this.scale = Math.min(wScale, hScale) * 100 | 0
- if (wScale <= hScale) {
- this.canvasStyles = {
- width: '960px',
- height: `${height * wScale}px`
- }
- } else {
- this.canvasStyles = {
- width: `${width * hScale}px`,
- height: '540px'
- }
- }
- }
- },
- async test () {
- const base64 = await this.snap()
- if (base64) {
- const result = /^data:(.+);base64,(.+)$/.exec(base64)
- console.log('base64:', result[0])
- this.imageBase64 = result[0]
- }
- },
- snap () {
- this.snapping = true
- return domToImage.toJpeg(this.$refs.canvas, {
- filter (node) {
- const { tagName } = node
- if (tagName === 'CANVAS') {
- return /^data:.+;base64,.+/.test(node.toDataURL())
- }
- return tagName !== 'VIDEO' && tagName !== 'IFRAME'
- },
- width: this.node.width * this.scale / 100 | 0,
- height: this.node.height * this.scale / 100 | 0,
- quality: 0.1
- }).finally(() => {
- this.snapping = false
- })
- },
- onEditorCreated (editor) {
- this.editor = Object.seal(editor)
- },
- onCustomPaste (editor, event, callback) {
- // 返回 true ,继续默认的粘贴行为
- callback(true)
- this.$nextTick(() => {
- editor.setHtml(editor.getHtml()
- .replace(/text-indent[^;]+;/g, ''))
- })
- },
- onRichConfirm (done) {
- this.widget[this.widgetAttr.key] = this.richHtml
- done()
- },
- onDragChange () {
- console.log('onDragChange', this.assets)
- },
- onDragEnd () {
- console.log('onDragEnd:', this.assets)
- const sources = this.assets.map(this.transformAssetToData)
- this.selectedWidget.sources = sources
- },
- clearInput (index) {
- this.$set(this.inputValues, index, '')
- },
- restoreInput (index, asset) {
- if (this.inputValues[index] === '') {
- this.$set(this.inputValues, index, String(index + 1))
- } else {
- this.onTargetIndexInput(index, asset)
- }
- this.sortAssets()
- },
- sortAssets () {
- const inputValues = this.inputValues
- this.assets.sort((a, b) => {
- const indexA = parseInt(inputValues[this.assets.indexOf(a)])
- const indexB = parseInt(inputValues[this.assets.indexOf(b)])
- return indexA - indexB
- })
- this.updateInputValues()
- console.log('sortAssets', this.assets)
- },
- onTargetIndexInput (index, asset) {
- const inputValue = this.inputValues[index]
- let targetIndex = parseInt(inputValue) - 1
- if (isNaN(targetIndex)) {
- targetIndex = index
- }
- if (targetIndex < 0) {
- targetIndex = 0
- } else if (targetIndex >= this.assets.length) {
- targetIndex = this.assets.length - 1
- }
- this.assets.splice(index, 1)
- this.assets.splice(targetIndex, 0, asset)
- this.updateInputValues()
- },
- updateInputValues () {
- for (let i = 0; i < this.assets.length; i++) {
- const inputValue = (i + 1).toString()
- this.inputValues[i] = inputValue
- }
- },
- show (id) {
- const loading = this.$showLoading()
- getTemplateProgram(id)
- .then(({ data }) => {
- try {
- console.log('showProgram', data)
- console.log('itemJsonStr', JSON.parse(data.itemJsonStr))
- const { id, status, name, resolutionRatio, itemJsonStr } = data
- const [width, height] = resolutionRatio.split('x')
- if (!width || !height) {
- this.showMessage('error', '布局分辨率异常,请联系管理员')
- return
- }
- this.program = {
- id, status, name, resolutionRatio,
- detail: {
- width: Number(width),
- height: Number(height),
- ...JSON.parse(itemJsonStr)
- }
- }
- console.log('progam', this.program)
- this.initCanvas(this.program.detail)
- this.checkRatio()
- // 默认选中第一个
- const widget = this.layers[0]
- this.chooseWidget(widget)
- this.$refs.dialog.show()
- } catch (e) {
- console.log('catch:', e)
- this.showMessage('error', '布局解析失败')
- }
- })
- .finally(() => {
- this.$closeLoading(loading)
- })
- },
- showMessage (type, message) {
- this.$message({
- type,
- message
- })
- },
- // 使用右侧的文本编辑器
- showText (widget) {
- this.isMedia = false
- this.richHtml = widget.text
- },
- // 使用右侧图片视频选择器
- showMediaChoose (widget) {
- console.log('showMediaChoose', widget)
- const assets = widget.sources
- this.options = {
- duration: widget.interval || 10,
- durationEditable: !widget.sameInterval
- }
- this.assets = assets?.map(this.defaultTransform) || []
- this.updateInputValues()
- },
- defaultTransform (asset) {
- const data = this.transform ? this.transform(asset, this.options) : { ...asset }
- if (!data.key) {
- data.key = `${Date.now()}_${Math.random()
- .toString(16)
- .slice(2)}`
- }
- return data
- },
- onClosedPreview () {
- console.log('onClosedPreview')
- },
- onClosed () {
- this.fileDir = null
- this.assets = []
- this.tableAssets = []
- },
- onAssetDirectoryChanged (directory) {
- console.log('directory', directory)
- this.directoryOption = directory
- this.$emit('directory-changed', directory)
- // this.$refs.table?.pageTo(1)
- },
- getAssetsByQuery (params) {
- console.log('getAssetsByQuery', params)
- const { type, ...options } = params
- if (type === AssetType.STREAMING_MEDIA) {
- this.isStream = true
- return getAssetsByQuery({
- ...options,
- type
- })
- }
- this.isStream = false
- if (!this.directoryOption) {
- return Promise.resolve({ data: [] })
- }
- const { root, id, group: { path } } = this.directoryOption
- return getAssetsByQuery({
- ...options,
- ...(root
- ? { org: path }
- : { treeId: id, queryRelation: '1' }),
- typeList: type ? [type] : [...this.mediaTypes]
- })
- },
- transformAsset ({ tag, type, originalName, keyName, duration, size, md5, file, diff }) {
- return {
- tag,
- type,
- name: originalName,
- keyName,
- size,
- md5,
- duration,
- selected: false,
- file,
- diff
- }
- },
- transformAssetToData ({ tag, type, name, keyName, duration, size, md5, file }) {
- const source = {
- tag,
- type,
- name,
- keyName,
- size,
- md5,
- duration
- }
- if (file.thumb && keyName !== file.thumb) {
- source.thumb = file.thumb
- }
- return source
- },
- onTableRefresh (assets) {
- this.tableAssets = assets
- },
- onChoosenAsset (asset) {
- console.log('onChoosenAsset', asset)
- if (this.choosen) {
- this.choosen(asset)
- .then(() => {
- this.$refs.dialog.hide()
- })
- } else {
- this.$refs.dialog.hide()
- }
- },
- onToggleAsset (asset) {
- asset.selected = !asset.selected
- },
- onViewAsset ({ file }) {
- // this.$emit('view', asset)
- this.onView(file)
- },
- onViewDir ({ name, file: { files } }) {
- this.fileDir = {
- name,
- files: files.map(({ tag, type, keyName, size, md5, sort }) => {
- return {
- tag,
- type,
- name: `第${sort + 1}页`,
- keyName,
- size,
- md5,
- sort,
- selected: false,
- file: {
- type,
- url: keyName
- }
- }
- })
- }
- },
- onAddAssets () {
- if (this.isDir) {
- this.onAddDirAssets(this.fileDir)
- return
- }
- this.tableAssets.forEach(asset => {
- if (asset.selected) {
- if (asset.file.files) {
- this.onAddDirAssets({
- name: asset.name,
- files: asset.file.files
- }, true)
- } else {
- this.onAddAsset(asset)
- }
- asset.selected = false
- }
- })
- },
- onAddAsset (asset) {
- const { duration, durationEditable } = this.options
- console.log('this.options.', this.options)
- const { tag, type, name, keyName, size, md5, file } = asset
- this.assets.push({
- tag,
- type,
- keyName,
- name,
- size,
- md5,
- file,
- duration: getAssetDuration(asset, duration),
- key: `${Date.now()}_${Math.random()
- .toString(16)
- .slice(2)}`,
- disabled: !durationEditable || type === AssetType.VIDEO || type === AssetType.AUDIO,
- info: `${AssetTagInfo[tag]} ${AssetTypeInfo[type]}`
- })
- // 将先的资源传给sources,左侧更新UI
- const sources = this.assets.map(this.transformAssetToData)
- this.selectedWidget.sources = sources
- this.updateInputValues()
- },
- onAddDirAssets (fileDir, force) {
- const { name: dirName, files } = fileDir
- files.forEach(asset => {
- if (force) {
- this.onAddDirAsset(asset, dirName)
- } else if (asset.selected) {
- this.onAddDirAsset(asset, dirName)
- asset.selected = false
- }
- })
- },
- onAddDirAsset (asset, dirName) {
- const { duration, durationEditable } = this.options
- const { tag, type, keyName, size, md5, sort } = asset
- this.assets.push({
- tag,
- type,
- keyName,
- name: `${dirName}第${sort + 1}页`,
- size,
- md5,
- duration,
- disabled: !durationEditable,
- key: `${Date.now()}_${Math.random()
- .toString(16)
- .slice(2)}`,
- info: `${AssetTagInfo[tag]} ${AssetTypeInfo[type]}`,
- file: {
- type,
- url: keyName
- }
- })
- },
- onDelAsset (index) {
- this.assets.splice(index, 1)
- this.selectedWidget.sources = this.assets
- },
- onConfirm (done) {
- // 检查资源
- const { ready, message } = fix(this.node)
- if (!ready) {
- this.$message({
- type: 'error',
- message
- })
- return
- }
- // 输入名字
- this.$prompt(
- '<p class="u-color--black u-font-size--sm u-bold">请输入节目名称</p>',
- '保存节目',
- {
- dangerouslyUseHTMLString: true,
- closeOnClickModal: false,
- inputValue: '模板名字',
- inputPlaceholder: '请输入节目名称',
- inputPattern: /^.{0,30}$/,
- inputErrorMessage: '最多30个字符',
- confirmButtonText: '保存',
- cancelButtonText: '取消'
- }
- ).then(({ value }) => {
- console.log('value', value)
- const loading = this.$showLoading()
- setTimeout(() => {
- // 不太确定这个options的作用
- this._save({ name: value, generate: true }, done).finally(() => {
- this.$closeLoading(loading)
- })
- }, 100)
- }).catch(() => {
- console.log('cancel')
- })
- },
- // 这里参照的是src/views/screen/material/program/ast/Designer.vue
- async _save (options, done) {
- console.log('options', options)
- try {
- const base64 = await this.snap()
- console.log('base64:', base64)
- const result = await updateProgramDraft({
- id: this.program.id,
- duration: getDuration(this.node),
- itemJsonStr: JSON.stringify(toJSON(this.node)),
- keyNameList: getUsedAssets(this.node),
- base64,
- ...options
- })
- if (result) {
- this.$message({
- type: 'success',
- message: '保存成功'
- })
- // 关闭
- done()
- } else {
- this.$message({
- type: 'warning',
- message: '保存失败'
- })
- }
- } catch (e) {
- console.warn(e)
- this.$message({
- type: 'warning',
- message: '保存失败'
- })
- }
- },
- onSetImageDuration () {
- const duration = this.duration
- this.assets.forEach(asset => {
- const { type, disabled } = asset
- if (!disabled && type === AssetType.IMAGE) {
- asset.duration = duration
- }
- })
- },
- hasAssets (widget) {
- switch (widget.type) {
- case WidgetType.MEDIA:
- case WidgetType.IMAGE:
- case WidgetType.VIDEO:
- case WidgetType.TEXT:
- return true
- default:
- return false
- }
- },
- onView (source) {
- // this.$muted = this.muted
- // switch (source.type) {
- // case AssetType.VIDEO:
- // case AssetType.AUDIO:
- // if (!this.muted) {
- // this.muted = true
- // }
- // break
- // default:
- // break
- // }
- console.log('onView:', source)
- this.$refs.previewDialog.show(source)
- },
- onWidgetClick (widget, evt) {
- console.log('onWidgetClick', widget)
- evt.stopPropagation()
- this.chooseWidget(widget)
- },
- chooseWidget (widget) {
- if (!this.selectedWidget || this.selectedWidget !== widget) {
- this.selectedWidget = widget
- console.log('selectedWidget:', widget)
- if (this.selectedWidget.type === 'CText') {
- this.isMedia = false
- this.showText(widget)
- } else {
- this.isMedia = true
- this.showMediaChoose(widget)
- }
- }
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .c-viewer {
- &__header {
- height: $height--md;
- line-height: 1;
- }
- &__wrapper {
- position: absolute;
- top: 0;
- left: $spacing;
- right: $font-size--xl + 2 * $padding--lg;
- height: 100%;
- }
- &__asserts {
- width: 160px;
- border-right: 1px solid $border;
- background-color: #fff;
- }
- &__count {
- height: $height--md;
- line-height: 1;
- background-color: #e8eaee;
- }
- &__scrollbar {
- ::v-deep {
- .el-scrollbar__wrap {
- flex: 1 1 0;
- min-height: 0;
- margin-bottom: 0 !important;
- }
- }
- }
- &__list {
- padding: $padding;
- }
- &__canvas {
- position: relative;
- background-color: #000;
- overflow: hidden;
- }
- &__background {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background-color: currentColor;
- z-index: -1;
- }
- }
- .mask {
- position: relative;
- &::after {
- content: "";
- position: absolute;
- top: 0;
- left: 0;
- right: $spacing;
- bottom: 0;
- background-color: rgba(#000, 0.6);
- }
- }
- .o-card {
- &__checkbox {
- position: absolute;
- top: 10px;
- left: 10px;
- pointer-events: none;
- z-index: 9;
- }
- &__play {
- position: absolute;
- top: 50%;
- left: 50%;
- padding: 2px;
- font-size: 24px;
- border-radius: 50%;
- background-color: rgba(#000, 0.4);
- transform: translate(-50%, -50%);
- }
- &__grid {
- position: absolute;
- top: 10px;
- right: 10px;
- font-size: 18px;
- z-index: 9;
- }
- &__info {
- position: absolute;
- top: 10px;
- right: 10px;
- z-index: 9;
- }
- }
- .c-transfer-area {
- padding: 0 $spacing;
- margin: 0 $spacing;
- border-left: 1px solid $border;
- border-right: 1px solid $border;
- }
- .c-transfer-area {
- padding: 0 $spacing;
- margin: 0 $spacing;
- border-left: 1px solid $border;
- border-right: 1px solid $border;
- }
- .c-textfield-area {
- padding: 0 $spacing;
- margin: 0 $spacing;
- border-left: 1px solid $border;
- }
- .o-draggable-input {
- ::v-deep .el-input__inner {
- text-align: center;
- padding: 0 $padding--sm;
- }
- }
- .o-layer {
- color: $black;
- user-select: none;
- border-radius: $radius;
- background-color: #f4f7f8;
- overflow: hidden;
- cursor: pointer;
- &.active {
- color: #fff;
- outline: 2px solid $blue;
- background-color: $blue;
- }
- }
- </style>
|