index.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. <template>
  2. <wrapper
  3. class="c-step"
  4. fill
  5. margin
  6. padding
  7. background
  8. >
  9. <div class="l-flex__none l-flex--row c-step__header">
  10. <button
  11. class="l-flex__none c-sibling-item o-button"
  12. @click="onPresent"
  13. >
  14. 导入历史编单
  15. </button>
  16. <div class="l-flex__fill u-text--center">
  17. 请选择需要上播的设备并配置相关上播内容
  18. </div>
  19. <button
  20. class="l-flex__none c-sibling-item o-button"
  21. @click="onNext"
  22. >
  23. 发布
  24. </button>
  25. </div>
  26. <div class="l-flex__fill l-flex">
  27. <device-tree
  28. ref="tree"
  29. class="c-sibling-item c-step__column u-width--md"
  30. exact
  31. checkbox
  32. check-on-click-node
  33. @change="onChange"
  34. />
  35. <div
  36. class="l-flex__none l-flex--col c-step__column"
  37. style="width: 360px"
  38. >
  39. <div class="c-sibling-item--v near u-font-size--sm u-bold">
  40. 上播类型
  41. </div>
  42. <el-select
  43. v-model="eventType"
  44. class="c-sibling-item--v nearer u-width--sm"
  45. size="small"
  46. >
  47. <el-option
  48. v-for="option in eventTypeOptions"
  49. :key="option.value"
  50. :label="option.label"
  51. :value="option.value"
  52. />
  53. </el-select>
  54. <template v-if="isNormal">
  55. <div class="c-sibling-item--v near u-font-size--sm">
  56. 优先级
  57. </div>
  58. <el-select
  59. v-model="priority"
  60. class="c-sibling-item--v nearer u-width--sm"
  61. size="small"
  62. >
  63. <el-option
  64. v-for="option in priorityOptions"
  65. :key="option.value"
  66. :label="option.label"
  67. :value="option.value"
  68. />
  69. </el-select>
  70. <div class="l-flex--row c-sibling-item--v near">
  71. <div
  72. class="l-flex__none l-flex--row inline c-sibling-item u-font-size--sm has-active"
  73. @click="onAddEvent"
  74. >
  75. <span class="c-sibling-item">
  76. 播放时段
  77. </span>
  78. <i class="c-sibling-item near el-icon-circle-plus-outline" />
  79. </div>
  80. </div>
  81. <schema-table
  82. ref="timeTable"
  83. class="c-sibling-item--v nearer"
  84. :schema="timeSchema"
  85. />
  86. </template>
  87. <template v-if="isIntercut">
  88. <div class="c-sibling-item--v near u-font-size--sm u-required">
  89. 插播时段
  90. </div>
  91. <el-date-picker
  92. v-model="rangeDate"
  93. class="c-sibling-item--v nearer u-width--lg"
  94. type="daterange"
  95. range-separator="至"
  96. start-placeholder="开始日期"
  97. end-placeholder="结束日期"
  98. value-format="yyyy-MM-dd"
  99. :clearable="false"
  100. />
  101. </template>
  102. </div>
  103. <event-target-picker
  104. ref="eventTargetPicker"
  105. class="l-flex__fill c-step__column"
  106. :event-target="eventTarget"
  107. :only-assets="isIntercut"
  108. />
  109. </div>
  110. <radio-table-dialog
  111. ref="workflowTableDialog"
  112. title="历史编单"
  113. size="lg"
  114. :schema="workflowSchema"
  115. @confirm="onChooseWorkflow"
  116. />
  117. <workflow-dialog ref="workflowDialog" />
  118. <intercut-workflow-dialog ref="intercutWorkflowDialog" />
  119. <event-frequency-config-dialog
  120. ref="eventFrequencyConfigDialog"
  121. @confirm="onConfirmEventFrequency"
  122. />
  123. <confirm-dialog
  124. ref="selfConflictDialog"
  125. title="冲突提醒"
  126. cancel-text="重新编辑"
  127. confirm-text="覆盖"
  128. append-to-body
  129. @confirm="onCover"
  130. >
  131. <div
  132. v-for="conflict in selfConflicts"
  133. :key="conflict.key"
  134. >
  135. {{ conflict.info }}
  136. </div>
  137. </confirm-dialog>
  138. <c-dialog
  139. ref="priorityConflictDialog"
  140. title="冲突数据"
  141. size="medium"
  142. append-to-body
  143. >
  144. <div class="c-sibling-item--v u-color--error">
  145. 以下设备将与新发布的时段存在冲突
  146. </div>
  147. <schema-table
  148. class="c-sibling-item--v nearer sm"
  149. :schema="priorityConflictSchema"
  150. />
  151. </c-dialog>
  152. <confirm-dialog
  153. ref="conflictDialog"
  154. title="冲突数据提醒"
  155. size="medium"
  156. cancel-text="重新编辑"
  157. confirm-text="覆盖"
  158. append-to-body
  159. @confirm="onCoverConfilcts"
  160. >
  161. <schema-table :schema="conflictSchema" />
  162. </confirm-dialog>
  163. </wrapper>
  164. </template>
  165. <script>
  166. import {
  167. State,
  168. EventTarget,
  169. WorkflowType,
  170. PublishType,
  171. PublishTargetType,
  172. EventPriority,
  173. EventPriorityInfo,
  174. EventFrequency
  175. } from '@/constant.js'
  176. import {
  177. toDateStr,
  178. getConflict,
  179. getEventDescription
  180. } from '@/utils/event.js'
  181. import {
  182. publish,
  183. getPublishConflicts,
  184. publishIntercut
  185. } from '@/api/platform.js'
  186. import {
  187. getWorkflowsByUser,
  188. getWorkflowsBySuperAdmin,
  189. getWorkflowDetail
  190. } from '@/api/workflow.js'
  191. import EventFrequencyConfigDialog from '../components/EventFrequencyConfigDialog.vue'
  192. import WorkflowDialog from '../workflow/components/WorkflowDialog.vue'
  193. import IntercutWorkflowDialog from '../workflow/components/IntercutWorkflowDialog.vue'
  194. import PriorityChecking from './components/PriorityChecking.vue'
  195. const PublishDataType = {
  196. NORMAL: 'NORMAL',
  197. DEFAULT_PLAYBACK: 'DEFAULT_PLAYBACK',
  198. INTERCUT: 'INTERCUT'
  199. }
  200. export default {
  201. name: 'DeployDevice',
  202. components: {
  203. EventFrequencyConfigDialog,
  204. WorkflowDialog,
  205. IntercutWorkflowDialog
  206. },
  207. data () {
  208. return {
  209. selectedDevices: [],
  210. eventType: PublishDataType.NORMAL,
  211. eventTypeOptions: [
  212. { value: PublishDataType.NORMAL, label: '常规' },
  213. { value: PublishDataType.INTERCUT, label: '资源插播' },
  214. { value: PublishDataType.DEFAULT_PLAYBACK, label: '默认播放' }
  215. ],
  216. priority: EventPriority.INSERTED,
  217. priorityOptions: [
  218. {
  219. value: EventPriority.SCHEDULING,
  220. label: EventPriorityInfo[EventPriority.SCHEDULING]
  221. },
  222. {
  223. value: EventPriority.INSERTED,
  224. label: EventPriorityInfo[EventPriority.INSERTED]
  225. },
  226. {
  227. value: EventPriority.EMBEDDED,
  228. label: EventPriorityInfo[EventPriority.EMBEDDED]
  229. },
  230. {
  231. value: EventPriority.EMERGENT,
  232. label: EventPriorityInfo[EventPriority.EMERGENT]
  233. }
  234. ],
  235. rangeDate: null,
  236. timeSchema: {
  237. nonPagination: true,
  238. props: {
  239. size: 'small',
  240. 'row-key': 'key'
  241. },
  242. list: this.getEvents,
  243. cols: [
  244. {
  245. label: '在播',
  246. render: ({ origin }, h) => h(PriorityChecking, {
  247. props: {
  248. deviceIds: this.selectedDeviceIds,
  249. priority: this.priority,
  250. event: origin
  251. },
  252. on: {
  253. click: this.onViewPriorityConflicts
  254. }
  255. }),
  256. width: 84,
  257. align: 'center'
  258. },
  259. { prop: 'time', label: '生效时间', 'show-overflow-tip': false },
  260. {
  261. type: 'invoke',
  262. render: [{ label: '移除', on: this.removeEventProxy }],
  263. width: 52
  264. }
  265. ]
  266. },
  267. priorityConflicts: [],
  268. priorityConflictSchema: {
  269. list: this.getPriorityConflicts,
  270. props: {
  271. size: 'small'
  272. },
  273. cols: [
  274. { prop: 'deviceName', label: '设备名称' },
  275. { prop: 'name', label: '上播内容' },
  276. { prop: 'priority', label: '优先级', render: row => EventPriorityInfo[row.priority], size: 'sm', width: 84, align: 'center' },
  277. { prop: 'start', label: '开始时间', width: 140, align: 'center' },
  278. { prop: 'until', label: '结束时间', width: 140, align: 'center' }
  279. ]
  280. },
  281. conflicts: [],
  282. conflictSchema: {
  283. list: this.getConflicts,
  284. props: {
  285. size: 'small'
  286. },
  287. cols: [
  288. { prop: 'deviceName', label: '设备名称' },
  289. { prop: 'name', label: '上播内容' },
  290. { prop: 'priority', label: '优先级', render: row => EventPriorityInfo[row.priority], size: 'sm', width: 84, align: 'center' },
  291. { prop: 'start', label: '开始时间', width: 140, align: 'center' },
  292. { prop: 'until', label: '结束时间', width: 140, align: 'center' }
  293. ]
  294. },
  295. events: [],
  296. selfConflicts: [],
  297. eventTarget: this.createEventTarget(),
  298. workflowSchema: {
  299. props: {
  300. size: 'small'
  301. },
  302. list: this.$store.getters.isSuperAdmin ? getWorkflowsBySuperAdmin : getWorkflowsByUser,
  303. filters: [
  304. { key: 'status', type: 'select', placeholder: '流程状态', options: [
  305. { value: State.SUBMITTED, label: '待审核' },
  306. { value: State.RESOLVED, label: '通过' },
  307. { value: State.REJECTED, label: '驳回' }
  308. ] },
  309. { key: 'flowName', type: 'search', placeholder: '上播内容' },
  310. { type: 'refresh' }
  311. ],
  312. cols: [
  313. { prop: 'flowDesc', label: '优先级', width: 120, align: 'center' },
  314. { prop: 'flowName', label: '上播内容' },
  315. { label: '状态', type: 'tag', render: ({ status }) => {
  316. return {
  317. type: ['', 'primary', 'success', 'danger'][status],
  318. label: ['', '待审核', '通过', '驳回'][status]
  319. }
  320. } },
  321. this.$store.getters.isSuperAdmin && { prop: 'createUser', label: '提交人', width: 140, align: 'center' },
  322. { prop: 'createTime', label: '提交时间', width: 140, align: 'center' },
  323. { type: 'invoke', render: [
  324. { label: '详情', on: this.onViewWorkflow }
  325. ] }
  326. ]
  327. }
  328. }
  329. },
  330. computed: {
  331. isNormal () {
  332. return this.eventType === PublishDataType.NORMAL
  333. },
  334. isDefaultPlayback () {
  335. return this.eventType === PublishDataType.DEFAULT_PLAYBACK
  336. },
  337. isIntercut () {
  338. return this.eventType === PublishDataType.INTERCUT
  339. },
  340. selectedDeviceIds () {
  341. return this.selectedDevices.map(device => device.id)
  342. }
  343. },
  344. methods: {
  345. createEventTarget (options) {
  346. return { type: EventTarget.ASSETS, ...options }
  347. },
  348. onPresent () {
  349. this.$refs.workflowTableDialog.show()
  350. },
  351. onNext () {
  352. const devices = this.selectedDevices
  353. const length = devices.length
  354. if (!length) {
  355. this.$message({
  356. type: 'warning',
  357. message: '请选择目标设备'
  358. })
  359. return
  360. }
  361. switch (this.eventType) {
  362. case PublishDataType.NORMAL:
  363. this.onPublishNormal()
  364. break
  365. case PublishDataType.DEFAULT_PLAYBACK:
  366. this.onPublishDefaultPlayback()
  367. break
  368. case PublishDataType.INTERCUT:
  369. this.onPublishIntercut()
  370. break
  371. default:
  372. break
  373. }
  374. },
  375. onChange (devices) {
  376. this.selectedDevices = Object.freeze(devices)
  377. },
  378. getEvents () {
  379. return Promise.resolve({ data: this.events })
  380. },
  381. getPriorityConflicts () {
  382. return Promise.resolve({ data: this.priorityConflicts })
  383. },
  384. getConflicts () {
  385. return Promise.resolve({ data: this.conflicts })
  386. },
  387. onAddEvent () {
  388. this.$refs.eventFrequencyConfigDialog.show()
  389. },
  390. onConfirmEventFrequency ({ value, done }) {
  391. this.$mergedValue = value
  392. const selfConflicts = new Map()
  393. if (this.events.length) {
  394. this.events.forEach(eventProxy => {
  395. value.forEach(event => {
  396. const date = getConflict(event, eventProxy.origin)
  397. if (date) {
  398. selfConflicts.set(eventProxy.key, {
  399. key: eventProxy.key,
  400. info: `与 ${eventProxy.time} 有冲突`
  401. })
  402. }
  403. })
  404. })
  405. }
  406. if (selfConflicts.size) {
  407. this.selfConflicts = [...selfConflicts.values()]
  408. this.$conflictOptions = { value, done }
  409. this.$refs.selfConflictDialog.show()
  410. return
  411. }
  412. this.onAdded(value, done)
  413. },
  414. onCover (closeCb) {
  415. this.selfConflicts.forEach(this.removeEventProxy)
  416. const { value, done } = this.$conflictOptions
  417. this.$conflictOptions = null
  418. closeCb()
  419. this.onAdded(value, done)
  420. },
  421. getDeviceName (deviceId) {
  422. if (!this._deviceNameCache) {
  423. this._deviceNameCache = {}
  424. }
  425. if (!this._deviceNameCache[deviceId]) {
  426. this._deviceNameCache[deviceId] = this.selectedDevices.find(device => device.id === deviceId)?.name || '-'
  427. }
  428. return this._deviceNameCache[deviceId]
  429. },
  430. onViewPriorityConflicts (conflicts) {
  431. this.priorityConflicts = conflicts.map(item => {
  432. const { deviceId, name, priority, start, until } = item
  433. return {
  434. deviceName: this.getDeviceName(deviceId),
  435. name, priority, start, until
  436. }
  437. })
  438. this.$refs.priorityConflictDialog.show()
  439. },
  440. onAdded (eventList, done) {
  441. this.events = [
  442. ...eventList.map(event => {
  443. return {
  444. key: `${Date.now()}_${Math.random()
  445. .toString(16)
  446. .slice(2)}`,
  447. origin: event,
  448. time: getEventDescription(event)
  449. }
  450. }),
  451. ...this.events
  452. ]
  453. this.$refs.timeTable?.pageTo()
  454. done()
  455. },
  456. removeEventProxy (eventProxy) {
  457. if (eventProxy) {
  458. const { key } = eventProxy
  459. const index = this.events.findIndex(event => event.key === key)
  460. if (~index) {
  461. this.events.splice(index, 1)
  462. return index
  463. }
  464. }
  465. return -1
  466. },
  467. onViewWorkflow ({ id, type }) {
  468. if (type === WorkflowType.INTERCUT) {
  469. this.$refs.intercutWorkflowDialog.show(id)
  470. } else {
  471. this.$refs.workflowDialog.show(id)
  472. }
  473. },
  474. onChooseWorkflow ({ value: { id, type }, done }) {
  475. getWorkflowDetail(id, { loading: true }).then(({ data }) => {
  476. let devices = []
  477. if (type === WorkflowType.INTERCUT) {
  478. this.eventType = PublishDataType.INTERCUT
  479. this.rangeDate = [data.startDate, data.endDate]
  480. this.eventTarget = this.createEventTarget({
  481. name: data.name,
  482. sources: data.deviceCalendarAdditionMediaDtoList.map(media => {
  483. return {
  484. md5: media.md5,
  485. tag: media.tag,
  486. name: media.originalName,
  487. size: media.size,
  488. type: media.type,
  489. keyName: media.keyName,
  490. duration: media.addDuration
  491. }
  492. })
  493. })
  494. devices = data.deviceIdList.map((deviceId, index) => {
  495. return {
  496. deviceId,
  497. deviceName: data.deviceNameList[index]
  498. }
  499. })
  500. } else {
  501. const {
  502. programCalendarName,
  503. calendarReleaseDeviceList,
  504. targetList
  505. } = data
  506. const targets = targetList.map(JSON.parse)
  507. const { detail: { priority, target } } = targets[0]
  508. this.eventType = priority === EventPriority.SHIM
  509. ? PublishDataType.DEFAULT_PLAYBACK
  510. : PublishDataType.NORMAL
  511. this.priority = priority
  512. this.events = targets.map(
  513. ({ detail: { priority, target, ...event } }) => {
  514. return {
  515. key: `${Date.now()}_${Math.random()
  516. .toString(16)
  517. .slice(2)}`,
  518. origin: event,
  519. time: getEventDescription(event)
  520. }
  521. }
  522. )
  523. this.$refs.timeTable?.pageTo(1)
  524. this.eventTarget = target.type === EventTarget.ASSETS
  525. ? {
  526. name: programCalendarName,
  527. ...this.createEventTarget(target)
  528. }
  529. : this.createEventTarget(target)
  530. devices = calendarReleaseDeviceList
  531. }
  532. const deviceCount = devices.length
  533. const validDevices = devices.filter(({ deviceName }) => !!deviceName)
  534. const validDeviceCount = validDevices.length
  535. const diffDeviceCount = this.$refs.tree.reset(validDevices.map(({ deviceId }) => deviceId))
  536. console.log(
  537. 'deploy import',
  538. diffDeviceCount,
  539. validDeviceCount,
  540. deviceCount
  541. )
  542. if (diffDeviceCount > 0 || validDeviceCount !== deviceCount) {
  543. this.$message({
  544. type: 'warning',
  545. message: '部分设备无操作权限或已移除,请确认设备'
  546. })
  547. }
  548. done()
  549. })
  550. },
  551. getPublishDescription (value = '', warningTip = '') {
  552. return this.$prompt(
  553. `<p>发布后需审核生效,操作完成后请通知相关人员进行审核</p>${warningTip}<br/><p class="u-color--black u-font-size--sm u-bold">编单名称</p>`,
  554. '操作确认',
  555. {
  556. dangerouslyUseHTMLString: true,
  557. closeOnClickModal: false,
  558. inputPlaceholder: '发布内容的简单描述',
  559. inputValue: value,
  560. inputPattern: /^.{1,30}$/,
  561. inputErrorMessage: '请用1~30个字符进行描述',
  562. confirmButtonText: '发布',
  563. cancelButtonText: '取消'
  564. }
  565. )
  566. },
  567. onPublishNormal () {
  568. return this.getNoramlPublishData().then(
  569. ({ publishType, targetList, name, resolutionRatio }) => {
  570. const warningTip = resolutionRatio && (!this.ratio || resolutionRatio !== this.ratio)
  571. ? '<p class="u-color--error">上播内容与设备分辨率不一致,可能无法完全适配</p>'
  572. : ''
  573. return this.getPublishDescription(name, warningTip).then(({ value }) => getPublishConflicts({
  574. deviceIdList: this.selectedDevices.map(device => device.id),
  575. conflictCheckTimeList: targetList.map(({ detail: { freq, start, until, byDay, startTime, endTime } }) => {
  576. return { freq, start, until, byDay, startTime, endTime }
  577. }),
  578. minPriority: this.priority,
  579. maxPriority: this.priority
  580. }).then(({ data }) => {
  581. const publishData = {
  582. publishType,
  583. targetList,
  584. options: {
  585. programCalendarName: value,
  586. resolutionRatio: resolutionRatio || '自适应',
  587. remark: EventPriorityInfo[this.priority]
  588. }
  589. }
  590. if (data && data.length > 0) {
  591. this._cachePublishData = publishData
  592. this.showConflicts(data)
  593. } else {
  594. this.conflicts = []
  595. this.onSubmitPublish(publishData)
  596. }
  597. }))
  598. }
  599. )
  600. },
  601. showConflicts (data) {
  602. this.conflicts = data.map(item => {
  603. const { deviceId, name, priority, start, until } = item.deviceCalendarRecordCO
  604. return {
  605. deviceName: this.getDeviceName(deviceId),
  606. name, priority, start, until
  607. }
  608. })
  609. this.$refs.conflictDialog.show()
  610. },
  611. onCoverConfilcts (done) {
  612. this.onSubmitPublish(this._cachePublishData).then(done)
  613. },
  614. getNoramlPublishData () {
  615. if (!this.events.length) {
  616. this.$message({
  617. type: 'warning',
  618. message: '请添加上播时段'
  619. })
  620. return Promise.reject('invalid event, no time')
  621. }
  622. const eventTarget = this.$refs.eventTargetPicker.getValue()
  623. if (!eventTarget) {
  624. return Promise.reject('invalid event, no target')
  625. }
  626. const { detail } = this.$refs.eventTargetPicker.getSnapshot()
  627. const type = PublishTargetType.EVENT
  628. const priority = this.priority
  629. return Promise.resolve({
  630. publishType: eventTarget.type === EventTarget.ASSETS
  631. ? PublishType.ASSET_TO_DEVICE
  632. : PublishType.PROGRAM_TO_DEVICE,
  633. targetList: this.events.map(({ origin }) => {
  634. return {
  635. type,
  636. detail: {
  637. priority,
  638. ...origin,
  639. target: eventTarget
  640. }
  641. }
  642. }),
  643. name: detail?.name || '',
  644. resolutionRatio: detail?.resolutionRatio
  645. })
  646. },
  647. onPublishDefaultPlayback () {
  648. return this.getDefaultPlaybackPublishData().then(
  649. ({ publishType, targetList, name, resolutionRatio }) => {
  650. const warningTip = resolutionRatio && (!this.ratio || resolutionRatio !== this.ratio)
  651. ? '<p class="u-color--error">上播内容与设备分辨率不一致,可能无法完全适配</p>'
  652. : ''
  653. return this.getPublishDescription(name, warningTip).then(({ value }) => this.onSubmitPublish({
  654. publishType,
  655. targetList,
  656. options: {
  657. programCalendarName: value,
  658. resolutionRatio: resolutionRatio || '自适应',
  659. remark: EventPriorityInfo[EventPriority.SHIM]
  660. }
  661. }))
  662. }
  663. )
  664. },
  665. getDefaultPlaybackPublishData () {
  666. const eventTarget = this.$refs.eventTargetPicker.getValue()
  667. if (!eventTarget) {
  668. return Promise.reject('invalid event, no target')
  669. }
  670. const { detail } = this.$refs.eventTargetPicker.getSnapshot()
  671. return Promise.resolve({
  672. publishType: eventTarget.type === EventTarget.ASSETS
  673. ? PublishType.ASSET_TO_DEVICE
  674. : PublishType.PROGRAM_TO_DEVICE,
  675. targetList: [{
  676. type: PublishTargetType.EVENT,
  677. detail: {
  678. priority: EventPriority.SHIM,
  679. freq: EventFrequency.ONCE,
  680. start: `${toDateStr(new Date())} 00:00:00`,
  681. target: eventTarget
  682. }
  683. }],
  684. name: detail?.name || '',
  685. resolutionRatio: detail?.resolutionRatio
  686. })
  687. },
  688. onSubmitPublish ({ publishType, targetList, options }) {
  689. return publish(
  690. publishType,
  691. this.selectedDevices.map(device => device.id),
  692. targetList,
  693. options
  694. ).then(() => {
  695. this.$refs.tree.reset()
  696. this.eventTarget = this.createEventTarget()
  697. })
  698. },
  699. onPublishIntercut () {
  700. return this.getIntercutPublishData().then(
  701. ({ name, ...data }) => this.getPublishDescription(name).then(
  702. ({ value }) => publishIntercut({
  703. name: value,
  704. ...data
  705. })
  706. )
  707. ).then(() => {
  708. this.$refs.tree.reset()
  709. this.eventTarget = this.createEventTarget()
  710. })
  711. },
  712. getIntercutPublishData () {
  713. if (!this.rangeDate?.length) {
  714. this.$message({
  715. type: 'warning',
  716. message: '请选择插播时段'
  717. })
  718. return Promise.reject('invalid event, no time')
  719. }
  720. const eventTarget = this.$refs.eventTargetPicker.getValue()
  721. if (!eventTarget) {
  722. return Promise.reject('invalid event, no target')
  723. }
  724. const { detail } = this.$refs.eventTargetPicker.getSnapshot()
  725. return Promise.resolve({
  726. startDate: this.rangeDate[0],
  727. endDate: this.rangeDate[0],
  728. deviceIdList: this.selectedDevices.map(device => device.id),
  729. mediaInfoDtoList: eventTarget.sources.map(item => {
  730. return {
  731. keyName: item.keyName,
  732. duration: item.duration
  733. }
  734. }),
  735. name: detail?.name || ''
  736. })
  737. }
  738. }
  739. }
  740. </script>