index.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. <template>
  2. <wrapper
  3. fill
  4. margin
  5. background
  6. >
  7. <div class="l-flex__none l-flex--row c-step has-padding">
  8. <button
  9. class="l-flex__none c-sibling-item o-button"
  10. :class="{ hidden: active === 0 }"
  11. @click="onPresent"
  12. >
  13. 上一步
  14. </button>
  15. <el-steps
  16. :active="active"
  17. class="l-flex__fill"
  18. finish-status="success"
  19. align-center
  20. >
  21. <el-step title="选择设备" />
  22. <el-step title="选择内容" />
  23. </el-steps>
  24. <button
  25. class="l-flex__none c-sibling-item o-button"
  26. :class="{ hidden: hideNext }"
  27. @click="onNext"
  28. >
  29. {{ btnMsg }}
  30. </button>
  31. </div>
  32. <div class="l-flex__fill l-flex">
  33. <device-group-tree
  34. v-show="active === 0"
  35. ref="tree"
  36. class="l-flex__fill has-padding"
  37. @change="onChange"
  38. />
  39. <template v-if="active > 0">
  40. <div class="c-list has-padding u-overflow-y--auto">
  41. <div class="c-list__item u-bold">{{ resolutionRatio }}</div>
  42. <div
  43. v-for="device in selectedDevices"
  44. :key="device.id"
  45. class="c-list__item"
  46. >
  47. {{ device.name }}
  48. </div>
  49. </div>
  50. <div class="c-list large has-padding u-overflow-y--auto">
  51. <div class="c-list__item">
  52. <div class="o-type">发布类型</div>
  53. <el-select v-model="eventOptions.type">
  54. <el-option
  55. v-for="option in typeOptions"
  56. :key="option.value"
  57. :label="option.label"
  58. :value="option.value"
  59. />
  60. </el-select>
  61. </div>
  62. <div
  63. v-if="isEvent"
  64. class="c-list__item"
  65. >
  66. <div class="o-type">级别</div>
  67. <el-select v-model="priority">
  68. <el-option
  69. v-for="option in priorityOptions"
  70. :key="option.value"
  71. :label="option.label"
  72. :value="option.value"
  73. />
  74. </el-select>
  75. </div>
  76. <div
  77. v-if="isCalendar"
  78. class="c-list__item c-grid-form medium col"
  79. >
  80. <div class="c-grid-form__label required">播放内容</div>
  81. <div class="o-schedule-button u-pointer">
  82. <div
  83. class="o-schedule-button__label has-padding--h"
  84. @click="onChooseSchedule"
  85. >
  86. <div class="u-ellipsis">{{ msg }}</div>
  87. </div>
  88. </div>
  89. </div>
  90. <event-picker
  91. v-show="isEvent"
  92. ref="picker"
  93. class="c-list__item"
  94. :ratio="resolutionRatio"
  95. vertical
  96. @choosen="onChoosenProgram"
  97. />
  98. <table-dialog
  99. ref="scheduleDialog"
  100. title="排期选择"
  101. size="medium"
  102. :schema="scheduleSchema"
  103. @choosen="onChoosenSchedule"
  104. />
  105. </div>
  106. <div
  107. v-if="eventTarget"
  108. class="c-list fill has-padding u-overflow-y--auto"
  109. >
  110. <schedule
  111. v-if="scheduleId"
  112. :schedule="scheduleId"
  113. />
  114. <div
  115. v-if="programId"
  116. class="o-program u-pointer"
  117. @click="onViewProgram"
  118. >
  119. {{ eventTarget.name }}
  120. </div>
  121. </div>
  122. </template>
  123. </div>
  124. <program-dialog ref="programDialog" />
  125. </wrapper>
  126. </template>
  127. <script>
  128. import { getSchedules } from '@/api/calendar'
  129. import { publish } from '@/api/platform'
  130. import {
  131. State,
  132. ScheduleType,
  133. EventTarget,
  134. PublishType,
  135. EventPriority,
  136. EventPriorityDescription
  137. } from '@/constant'
  138. export default {
  139. name: 'ScheduleDeploy',
  140. data () {
  141. return {
  142. typeOptions: [
  143. { value: PublishType.CALENDAR, label: '排期' },
  144. { value: PublishType.EVENT, label: '节目' }
  145. ],
  146. active: 0,
  147. selectedDevices: [],
  148. priority: EventPriority.INSERTED,
  149. priorityOptions: [
  150. { value: EventPriority.INSERTED, label: EventPriorityDescription[EventPriority.INSERTED] },
  151. { value: EventPriority.EMERGENT, label: EventPriorityDescription[EventPriority.EMERGENT] }
  152. ],
  153. eventOptions: null,
  154. scheduleSchema: {
  155. condition: { type: ScheduleType.COMPLEX, status: State.AVAILABLE, name: '' },
  156. list: getSchedules,
  157. filters: [
  158. { key: 'name', type: 'search', placeholder: '排期名称' }
  159. ],
  160. cols: [{ prop: 'name', label: '名称', align: 'center' }]
  161. }
  162. }
  163. },
  164. computed: {
  165. hideNext () {
  166. switch (this.active) {
  167. case 0:
  168. return this.selectedDevices.length === 0
  169. case 1:
  170. return !this.eventTarget
  171. default:
  172. return false
  173. }
  174. },
  175. eventTarget () {
  176. if (this.isCalendar) {
  177. return this.eventOptions?.schedule
  178. }
  179. return this.eventOptions?.program
  180. },
  181. isCalendar () {
  182. return this.eventOptions?.type === PublishType.CALENDAR
  183. },
  184. isEvent () {
  185. return this.eventOptions?.type === PublishType.EVENT
  186. },
  187. btnMsg () {
  188. return this.active < 1 ? '下一步' : '发布'
  189. },
  190. resolutionRatio () {
  191. return this.selectedDevices[0]?.resolutionRatio
  192. },
  193. typeMsg () {
  194. return this.typeOptions[this.eventOptions?.type - 1]?.label
  195. },
  196. scheduleId () {
  197. return this.eventOptions?.type === PublishType.CALENDAR || this.eventTarget?.type === EventTarget.RECUR ? this.eventTarget.id : null
  198. },
  199. programId () {
  200. return this.eventTarget?.type === EventTarget.PROGRAM ? this.eventTarget.id : null
  201. },
  202. msg () {
  203. return this.eventTarget?.name ?? '点击选择内容'
  204. }
  205. },
  206. methods: {
  207. onPresent () {
  208. if (this.active > 0) {
  209. this.active = 0
  210. }
  211. },
  212. onNext () {
  213. switch (this.active) {
  214. case 0:
  215. if (this.checkDevices()) {
  216. this.active += 1
  217. }
  218. break
  219. case 1:
  220. case 2:
  221. this.publish().then(() => {
  222. this.active = 0
  223. this.$refs.tree.reset()
  224. this.eventOptions = null
  225. this.priority = EventPriority.INSERTED
  226. })
  227. break
  228. default:
  229. break
  230. }
  231. },
  232. onError (message) {
  233. this.$message({
  234. type: 'warning',
  235. message
  236. })
  237. return false
  238. },
  239. onChange (devices) {
  240. this.selectedDevices = devices
  241. },
  242. checkDevices () {
  243. const devices = this.selectedDevices
  244. const length = devices.length
  245. if (!length) {
  246. return this.onError('请选择目标设备')
  247. }
  248. const resolutionRatio = this.resolutionRatio
  249. if (devices.some(device => device.resolutionRatio !== resolutionRatio)) {
  250. return this.onError('选择的设备分辨率不一致')
  251. }
  252. this.eventOptions = this.createEventOptions()
  253. return true
  254. },
  255. createEventOptions () {
  256. return {
  257. ratio: this.resolutionRatio,
  258. type: PublishType.CALENDAR,
  259. schedule: null,
  260. program: null
  261. }
  262. },
  263. onChoosenProgram (val) {
  264. this.eventOptions.program = val
  265. },
  266. onChooseSchedule () {
  267. this.$refs.scheduleDialog.show({ resolutionRatio: this.resolutionRatio })
  268. },
  269. onChoosenSchedule ({ value: { id, name }, done }) {
  270. done()
  271. this.eventOptions.schedule = { id, name }
  272. },
  273. onViewProgram () {
  274. this.$refs.programDialog.show(this.programId)
  275. },
  276. getPublishTarget () {
  277. if (this.eventOptions.type === PublishType.CALENDAR) {
  278. return Promise.resolve({
  279. type: PublishType.CALENDAR,
  280. detail: this.eventTarget.id
  281. })
  282. }
  283. const event = this.$refs.picker.getValue()
  284. if (event) {
  285. return Promise.resolve({
  286. type: PublishType.EVENT,
  287. detail: {
  288. ...event,
  289. priority: this.priority
  290. }
  291. })
  292. }
  293. return Promise.reject()
  294. },
  295. publish () {
  296. return this.getPublishTarget().then(eventTarget => {
  297. const devices = this.selectedDevices
  298. return this.$confirm(
  299. `对设备 ${devices.map(device => device.name)}`,
  300. `发布 ${this.typeMsg} ${this.eventTarget.name}`,
  301. { type: 'warning' }
  302. ).then(() => publish(
  303. devices.map(device => device.id),
  304. eventTarget,
  305. {
  306. programCalendarName: this.eventTarget.name,
  307. resolutionRatio: this.resolutionRatio
  308. }
  309. ))
  310. })
  311. }
  312. }
  313. }
  314. </script>
  315. <style lang="scss" scoped>
  316. .c-step {
  317. border-bottom: 1px solid $gray--light;
  318. .hidden {
  319. visibility: hidden;
  320. }
  321. }
  322. .c-list {
  323. flex: 0 0 200px;
  324. min-width: 200px;
  325. padding-right: $spacing;
  326. color: $black;
  327. & + & {
  328. border-left: 1px solid $gray--light;
  329. }
  330. &.large {
  331. min-width: 336px;
  332. max-width: 336px;
  333. }
  334. &.fill {
  335. flex: 1 0 200px;
  336. }
  337. &__item {
  338. line-height: 1;
  339. & + & {
  340. margin-top: 8px;
  341. }
  342. &:nth-child(2) {
  343. margin-top: 10px;
  344. }
  345. }
  346. }
  347. .o-type {
  348. margin-bottom: 8px;
  349. font-size: 14px;
  350. font-weight: bold;
  351. line-height: 1;
  352. }
  353. .o-schedule-button {
  354. position: relative;
  355. width: 217px;
  356. height: 40px;
  357. color: $blue;
  358. font-size: 14px;
  359. line-height: 1;
  360. border-radius: $radius--mini;
  361. border: 1px solid #dcdfe6;
  362. &:hover {
  363. border-color: #c0c4cc;
  364. }
  365. &__label {
  366. display: inline-flex;
  367. justify-content: center;
  368. align-items: center;
  369. position: absolute;
  370. width: 100%;
  371. height: 100%;
  372. }
  373. }
  374. .o-program {
  375. font-size: 24px;
  376. font-weight: bold;
  377. &:hover {
  378. color: #409eff;
  379. }
  380. }
  381. </style>