AssetTask.vue 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837
  1. <template>
  2. <wrapper
  3. fill
  4. margin
  5. padding
  6. background
  7. horizontal
  8. >
  9. <schema-table
  10. ref="table"
  11. class="c-sibling-item far"
  12. row-key="id"
  13. :schema="schema"
  14. />
  15. <table-dialog
  16. ref="contentDialog"
  17. size="medium"
  18. title="上播内容"
  19. :schema="contentSchema"
  20. />
  21. <asset-task-dialog
  22. ref="taskDialog"
  23. @view="onViewAsset"
  24. @confirm="onSubmitAssetTask"
  25. />
  26. <radio-table-dialog
  27. ref="contractTableDialog"
  28. title="新增合同任务"
  29. message="请选择合同"
  30. :schema="contractTableSchema"
  31. @confirm="onSubmitContractTask"
  32. />
  33. <preview-dialog ref="previewDialog" />
  34. <confirm-dialog
  35. ref="timeDialog"
  36. title="上播时间设置"
  37. @confirm="onConfirmTime"
  38. >
  39. <div class="c-grid-form auto u-align-self--center">
  40. <div class="c-grid-form__label">上播方式</div>
  41. <schema-select
  42. v-model="taskTime.type"
  43. class="u-width"
  44. :schema="taskTimeTypeSelectSchema"
  45. />
  46. <template v-if="taskTime.type === 2">
  47. <div class="c-grid-form__label">时段</div>
  48. <el-time-picker
  49. key="task-range-picker"
  50. v-model="taskTime.range"
  51. class="u-width"
  52. is-range
  53. format="HH:mm"
  54. value-format="HH:mm"
  55. :clearable="false"
  56. />
  57. </template>
  58. <template v-if="taskTime.type === 3">
  59. <div class="c-grid-form__label">时间点</div>
  60. <el-time-picker
  61. key="task-time-picker"
  62. v-model="taskTime.point"
  63. class="u-width"
  64. value-format="HH:mm:ss"
  65. :clearable="false"
  66. />
  67. </template>
  68. </div>
  69. </confirm-dialog>
  70. <confirm-dialog
  71. ref="deviceDialog"
  72. title="上刊设备"
  73. size="lg fixed"
  74. @confirm="onChangeDevices"
  75. @closed="onClosedDeviceDialog"
  76. >
  77. <template #default>
  78. <div class="l-flex__auto l-flex c-device-toggle">
  79. <div class="l-flex__fill l-flex--col">
  80. <schema-table
  81. ref="deviceTable"
  82. :schema="deviceSchema"
  83. @row-click="onDeviceRowClick"
  84. @selection-change="onDeviceSelectionChange"
  85. />
  86. </div>
  87. <div class="l-flex__none l-flex--row c-device-toggle__button">
  88. <el-button
  89. type="primary"
  90. :disabled="!selectedDevices.length"
  91. @click="onAddDevice"
  92. >
  93. <i class="el-icon-arrow-right" />
  94. </el-button>
  95. </div>
  96. <el-empty
  97. v-if="isEmpty"
  98. class="l-flex__none l-flex--row center c-device-toggle__list"
  99. description="请添加设备"
  100. />
  101. <div
  102. v-else
  103. class="l-flex__none l-flex--col c-device-toggle__list u-font-size--sm u-overflow-y--auto"
  104. >
  105. <div
  106. v-for="(device, index) in devices"
  107. :key="device.id"
  108. class="l-flex--row c-sibling-item--v c-device-toggle__item"
  109. >
  110. <div class="l-flex__auto c-slibing-item has-padding u-ellipsis">
  111. {{ device.name }}
  112. </div>
  113. <i
  114. class="l-flex__none c-device-toggle__del el-icon-delete has-padding--h has-active"
  115. @click="onDelDevice(index)"
  116. />
  117. </div>
  118. </div>
  119. </div>
  120. </template>
  121. </confirm-dialog>
  122. </wrapper>
  123. </template>
  124. <script>
  125. import {
  126. TimeType,
  127. SCREEN_TIME_KEY,
  128. TaskFromType,
  129. TaskFromTypeInfo,
  130. AssetTag,
  131. AssetTagInfo,
  132. AssetType,
  133. AssetTypeInfo
  134. } from '@/constant'
  135. import {
  136. parseDuration,
  137. parseTaskTime,
  138. getTaskTimeInfo,
  139. transformToTaskTime,
  140. offsetDate,
  141. calculateDay,
  142. getAssetThumb
  143. } from '@/utils'
  144. import { getDevices } from '@/api/device'
  145. import {
  146. getOrderDetail,
  147. getContracts,
  148. getContract
  149. } from '../api'
  150. import {
  151. getTasks,
  152. addTask,
  153. deleteTask,
  154. updateTask
  155. } from './api'
  156. import AssetTaskDialog from './components/AssetTaskDialog.vue'
  157. export default {
  158. name: 'AdAssetTask',
  159. components: {
  160. AssetTaskDialog
  161. },
  162. data () {
  163. const canEdit = this.$store.getters.isOperator
  164. const canAudit = this.$store.getters.isGroupAdmin
  165. return {
  166. schema: {
  167. buttons: canEdit
  168. ? [
  169. { type: 'add', label: '素材任务', on: this.onAddAssetTask },
  170. { type: 'add', label: '合同任务', on: this.onAddContractTask }
  171. ]
  172. : null,
  173. list: getTasks,
  174. transform: this.transform,
  175. cols: [
  176. { prop: 'type', type: 'refresh', width: 80 },
  177. { render: (data, h) => data.allowed
  178. ? h(
  179. 'div',
  180. {
  181. staticClass: 'u-ellipsis has-active',
  182. on: {
  183. click: () => this.onViewTask(data)
  184. }
  185. },
  186. data.name
  187. )
  188. : data.name },
  189. { label: '上刊设备', render: (data, h) => h(
  190. 'div',
  191. {
  192. staticClass: 'u-ellipsis has-active',
  193. on: {
  194. click: () => this.onEditDevices(data)
  195. }
  196. },
  197. data.devices.length > 1
  198. ? `${data.devices[0].name}等`
  199. : data.devices.length === 1
  200. ? data.devices[0].name
  201. : '暂未绑定'
  202. ), 'min-width': 100 },
  203. { label: '上刊日期', render: (data, h) => canEdit && data.allowed && data.from === TaskFromType.ASSET
  204. ? h('el-date-picker', {
  205. staticClass: 'o-date-picker',
  206. props: {
  207. value: [data.startDate, data.endDate],
  208. type: 'daterange',
  209. rangeSeparator: '至',
  210. valueFormat: 'yyyy-MM-dd',
  211. editable: false,
  212. clearable: false
  213. },
  214. on: {
  215. input: val => this.onDateEdit(data, val)
  216. }
  217. })
  218. : `${data.startDate} 至 ${data.endDate}`, width: 220, align: 'center' },
  219. { label: '上播时间', render: (data, h) => canEdit && data.allowed && data.from === TaskFromType.ASSET
  220. ? h('div', {
  221. staticClass: 'o-date-picker jc',
  222. on: {
  223. click: () => this.onEditTime(data)
  224. }
  225. }, data.range)
  226. : data.range, 'min-width': 100, align: 'center' },
  227. { label: '上播时长(s)', render: (data, h) => canEdit && this.canEditDuration(data)
  228. ? h('edit-input', {
  229. staticClass: 'border',
  230. props: {
  231. value: `${data.duration}`,
  232. align: 'center'
  233. },
  234. on: {
  235. edit: val => this.onSimpleEdit(data, 'duration', val)
  236. }
  237. })
  238. : data.duration, 'min-width': 100, align: 'center' },
  239. { label: '上播次数', render: (data, h) => canEdit && data.allowed && data.from === TaskFromType.ASSET
  240. ? h('edit-input', {
  241. staticClass: 'border',
  242. props: {
  243. value: `${data.count}`,
  244. align: 'center'
  245. },
  246. on: {
  247. edit: val => this.onSimpleEdit(data, 'count', val)
  248. }
  249. })
  250. : data.count, 'min-width': 100, align: 'center' },
  251. { label: '审核次数', render: (data, h) => canAudit && data.allowed
  252. ? h('edit-input', {
  253. staticClass: 'border',
  254. props: {
  255. value: `${data.auditCount}`,
  256. align: 'center'
  257. },
  258. on: {
  259. edit: val => this.onAuditEdit(data, val)
  260. }
  261. })
  262. : '-', 'min-width': 100, align: 'center' },
  263. { prop: 'tag', type: 'tag', on: canAudit && this.onAudit },
  264. { type: 'invoke', render: [
  265. { label: '查看', allow: ({ allowed }) => allowed, on: this.onViewTask },
  266. { label: '删除', allow: ({ from }) => from !== TaskFromType.ORDER, on: this.onDel }
  267. ], width: 92 }
  268. ]
  269. },
  270. contentSchema: {
  271. list: this.getContentAssets,
  272. cols: [
  273. { prop: 'tagType', label: '文件', width: 100, align: 'center' },
  274. { prop: 'fileType', label: '', width: 80 },
  275. { prop: 'file', label: '', type: 'asset', on: this.onViewAsset },
  276. { prop: 'name', label: '' },
  277. { prop: 'adDuration', label: '上播时长', align: 'center' },
  278. { type: 'invoke', render: [
  279. { label: '查看', allow: ({ file }) => !!file, on: this.onViewAsset }
  280. ] }
  281. ]
  282. },
  283. contractTableSchema: {
  284. condition: { name: '' },
  285. list: getContracts,
  286. transform: this.transformContract,
  287. filters: [
  288. { key: 'name', type: 'search', placeholder: '合同名称' }
  289. ],
  290. cols: [
  291. { prop: 'name', label: '名称' },
  292. { prop: 'dateRange', label: '上刊日期', 'width': 200 },
  293. { prop: 'timeRange', label: '上播时间' },
  294. { prop: 'count', label: '上播次数' },
  295. { prop: 'durationInfo', label: '上播时长' }
  296. ]
  297. },
  298. taskTimeTypeSelectSchema: {
  299. options: [
  300. { value: TimeType.SCREEN, label: '开机期间' },
  301. { value: TimeType.RANGE, label: '时段' },
  302. { value: TimeType.POINT, label: '时间点' }
  303. ]
  304. },
  305. taskTime: {},
  306. deviceSchema: {
  307. list: getDevices,
  308. filters: [
  309. { key: 'name', type: 'search', placeholder: '设备名称' }
  310. ],
  311. cols: [
  312. { type: 'selection' },
  313. { prop: 'name', label: '名称' }
  314. ],
  315. pagination: { small: true, layout: 'prev,pager,next' }
  316. },
  317. devices: [],
  318. selectedDevices: []
  319. }
  320. },
  321. computed: {
  322. isEmpty () {
  323. return this.devices.length === 0
  324. }
  325. },
  326. methods: {
  327. canEditDuration ({ allowed, from, fromInfo }) {
  328. return allowed && from === TaskFromType.ASSET && fromInfo?.type === AssetType.IMAGE
  329. },
  330. transform (task) {
  331. const { id, devices, from, fromId, fromInfo, startDate, startTime, endTime, day, duration, count, auditCount, enable } = task
  332. const allowed = this.isValidTask(from, fromInfo)
  333. return {
  334. id,
  335. devices,
  336. from,
  337. fromId,
  338. fromInfo,
  339. type: this.getDataType(task),
  340. name: this.getDataName(task),
  341. startDate,
  342. endDate: offsetDate(startDate, day),
  343. startTime,
  344. endTime,
  345. range: getTaskTimeInfo({ startTime, endTime }),
  346. count,
  347. duration,
  348. auditCount,
  349. enable,
  350. tag: allowed
  351. ? this.getEnableTag(enable)
  352. : {
  353. type: 'danger',
  354. label: '异常',
  355. msg: '源数据丢失'
  356. },
  357. allowed
  358. }
  359. },
  360. isValidTask (from, fromInfo) {
  361. switch (from) {
  362. case TaskFromType.ORDER:
  363. return true
  364. default:
  365. return !!fromInfo
  366. }
  367. },
  368. getDataType ({ from, fromInfo }) {
  369. if (from === TaskFromType.ASSET && fromInfo) {
  370. return AssetTypeInfo[fromInfo.type]
  371. }
  372. return TaskFromTypeInfo[from]
  373. },
  374. getDataName ({ from, fromInfo }) {
  375. switch (from) {
  376. case TaskFromType.ORDER:
  377. return '自助广告'
  378. default:
  379. return fromInfo?.name || '-'
  380. }
  381. },
  382. getEnableTag (enable) {
  383. return {
  384. type: enable ? 'success' : 'primary',
  385. label: enable ? '已审核' : '待审核'
  386. }
  387. },
  388. transformContract (contract) {
  389. contract.durationInfo = parseDuration(contract.duration)
  390. contract.dateRange = `${contract.startDate} 至 ${offsetDate(contract.startDate, contract.day)}`
  391. contract.timeRange = getTaskTimeInfo(contract)
  392. return contract
  393. },
  394. onViewTask (task) {
  395. switch (task.from) {
  396. case TaskFromType.ORDER:
  397. getOrderDetail(task.fromId).then(({ data }) => {
  398. this.showContentDialog(data.assets.map(this.transformOrderAsset))
  399. })
  400. break
  401. case TaskFromType.ASSET:
  402. this.onViewAsset({
  403. file: {
  404. type: task.fromInfo.type,
  405. url: task.fromId
  406. }
  407. })
  408. break
  409. case TaskFromType.CONTRACT:
  410. getContract(task.fromId).then(({ data }) => {
  411. this.showContentDialog(data.assets.map(this.transformContractAsset))
  412. })
  413. break
  414. default:
  415. break
  416. }
  417. },
  418. showContentDialog (assets) {
  419. if (assets.length === 1) {
  420. assets[0].adDuration = '独占'
  421. }
  422. this.$assets = assets
  423. this.$refs.contentDialog.show()
  424. },
  425. getContentAssets () {
  426. const assets = this.$assets
  427. return Promise.resolve({
  428. data: assets,
  429. totalCount: assets.length
  430. })
  431. },
  432. transformOrderAsset ({ keyName, type, adDuration, thumb }) {
  433. const isImage = type === AssetType.IMAGE
  434. return type
  435. ? {
  436. tagType: AssetTagInfo[AssetTag.AD],
  437. fileType: AssetTypeInfo[type],
  438. file: {
  439. type,
  440. url: keyName,
  441. thumb: isImage ? keyName : thumb,
  442. origin: !isImage
  443. },
  444. adDuration: parseDuration(adDuration)
  445. }
  446. : {
  447. tagType: '素材已删除',
  448. adDuration: parseDuration(adDuration)
  449. }
  450. },
  451. transformContractAsset ({ duration, minioData }) {
  452. if (minioData) {
  453. const { tag, type, keyName } = minioData
  454. return {
  455. tagType: AssetTagInfo[tag],
  456. fileType: AssetTypeInfo[type],
  457. file: {
  458. type,
  459. url: keyName,
  460. thumb: getAssetThumb(minioData)
  461. },
  462. name: minioData.originalName,
  463. adDuration: parseDuration(duration)
  464. }
  465. }
  466. return {
  467. tagType: '素材已删除',
  468. adDuration: parseDuration(duration)
  469. }
  470. },
  471. onViewAsset ({ file }) {
  472. this.$refs.previewDialog.show(file)
  473. },
  474. onDel ({ id, type, name }) {
  475. deleteTask(id, `${type} ${name}`).then(() => {
  476. this.$refs.table.decrease(1)
  477. })
  478. },
  479. onAddAssetTask () {
  480. this.$refs.taskDialog.show()
  481. },
  482. onSubmitAssetTask ({ value, done }) {
  483. this.addTask(value).then(done)
  484. },
  485. onAddContractTask () {
  486. this.$refs.contractTableDialog.show()
  487. },
  488. onSubmitContractTask ({ value, done }) {
  489. this.addTask({
  490. from: TaskFromType.CONTRACT,
  491. fromId: value.id,
  492. startDate: value.startDate,
  493. day: value.day,
  494. startTime: value.startTime,
  495. endTime: value.endTime,
  496. count: value.count,
  497. duration: value.duration
  498. }).then(done)
  499. },
  500. addTask (task) {
  501. return addTask({
  502. ...task,
  503. auditCount: task.count,
  504. enable: false
  505. }).then(() => {
  506. this.$refs.table.pageTo(1)
  507. })
  508. },
  509. onAudit (task) {
  510. const { allowed, devices, enable, startTime, endTime, duration, auditCount } = task
  511. if (!allowed) {
  512. return
  513. }
  514. if (!devices.length) {
  515. this.$message({
  516. type: 'warning',
  517. message: '请先添加上刊设备'
  518. })
  519. return
  520. }
  521. if (!enable) {
  522. const totalDuration = duration * auditCount * 1000
  523. if (startTime && endTime && endTime !== SCREEN_TIME_KEY) {
  524. const remind = new Date(`2000-01-01 ${endTime}`) - new Date(`2000-01-01 ${startTime}`)
  525. if (remind < totalDuration) {
  526. this.$message({
  527. type: 'warning',
  528. message: '所选时段无法满足上播次数'
  529. })
  530. return
  531. }
  532. }
  533. }
  534. this.$confirm(
  535. enable ? '停止使用后将不可参与自动编单' : '启用后将可参与自动编单',
  536. enable ? '停用任务' : '启用任务',
  537. { type: 'warning' }
  538. ).then(() => {
  539. this.onUpdateEnable(task)
  540. })
  541. },
  542. onUpdateEnable (task) {
  543. const { id, enable } = task
  544. updateTask({
  545. id,
  546. enable: !enable
  547. }).then(() => {
  548. task.enable = !enable
  549. task.tag = this.getEnableTag(!enable)
  550. })
  551. },
  552. onSimpleEdit (task, key, { newVal, oldVal }) {
  553. if (!newVal || !/^\d+$/.test(newVal) || Number(newVal) < 1) {
  554. return
  555. }
  556. if (newVal !== oldVal) {
  557. task[key] = Number(newVal)
  558. updateTask({
  559. id: task.id,
  560. enable: false,
  561. [key]: newVal
  562. }).then(
  563. () => {
  564. if (task.enable) {
  565. task.enable = false
  566. task.tag = this.getEnableTag(false)
  567. }
  568. },
  569. () => {
  570. task[key] = oldVal
  571. }
  572. )
  573. }
  574. },
  575. onDateEdit (task, val) {
  576. const { id, enable, startDate, endDate } = task
  577. if (startDate !== val[0] || endDate !== val[1]) {
  578. const day = calculateDay(val[0], val[1]) + 1
  579. updateTask({
  580. id,
  581. enable: false,
  582. startDate: val[0],
  583. day
  584. }).then(
  585. () => {
  586. if (enable) {
  587. task.enable = false
  588. task.tag = this.getEnableTag(false)
  589. }
  590. task.startDate = val[0]
  591. task.endDate = val[1]
  592. task.day = day
  593. }
  594. )
  595. }
  596. },
  597. onAuditEdit (task, { newVal, oldVal }) {
  598. if (!newVal || !/^\d+$/.test(newVal) || Number(newVal) < 1) {
  599. return
  600. }
  601. if (newVal !== oldVal) {
  602. const auditCount = Number(newVal)
  603. if (task.from === TaskFromType.ORDER && auditCount < task.count) {
  604. this.$message({
  605. type: 'warning',
  606. message: '订单的审核次数不能小于上播次数'
  607. })
  608. return
  609. }
  610. if (task.from === TaskFromType.CONTRACT && auditCount < task.count) {
  611. this.$message({
  612. type: 'warning',
  613. message: '合同的审核次数不能小于上播次数'
  614. })
  615. return
  616. }
  617. task.auditCount = auditCount
  618. updateTask({
  619. id: task.id,
  620. enable: false,
  621. auditCount
  622. }).then(
  623. () => {
  624. if (task.enable) {
  625. task.enable = false
  626. task.tag = this.getEnableTag(false)
  627. }
  628. },
  629. () => {
  630. task.auditCount = oldVal
  631. }
  632. )
  633. }
  634. },
  635. onEditTime (task) {
  636. this.$task = task
  637. this.taskTime = parseTaskTime(task)
  638. this.$refs.timeDialog.show()
  639. },
  640. onConfirmTime (done) {
  641. const { id, enable, startTime, endTime } = this.$task
  642. const { startTime: targetStartTime, endTime: targetEndTime } = transformToTaskTime(this.taskTime)
  643. if (!targetStartTime) {
  644. this.$message({
  645. type: 'warning',
  646. message: '请选择上播时间'
  647. })
  648. return
  649. }
  650. if (startTime !== targetStartTime || endTime !== targetEndTime) {
  651. updateTask({
  652. id,
  653. enable: false,
  654. startTime: targetStartTime,
  655. endTime: targetEndTime
  656. }).then(
  657. () => {
  658. if (enable) {
  659. this.$task.enable = false
  660. this.$task.tag = this.getEnableTag(false)
  661. }
  662. this.$task.startTime = targetStartTime
  663. this.$task.endTime = targetEndTime
  664. this.$task.range = getTaskTimeInfo({ startTime: targetStartTime, endTime: targetEndTime })
  665. done()
  666. }
  667. )
  668. } else {
  669. done()
  670. }
  671. },
  672. onEditDevices (task) {
  673. if (!task.allowed) {
  674. return
  675. }
  676. this.$task = task
  677. this.$deviceMap = {}
  678. this.$currDeviceMap = {}
  679. const deviceArray = []
  680. task.devices.forEach(({ id, name }) => {
  681. this.$deviceMap[id] = 1
  682. this.$currDeviceMap[id] = 1
  683. deviceArray.push({ id, name })
  684. })
  685. this.devices = deviceArray
  686. this.$refs.deviceDialog.show()
  687. },
  688. onDeviceRowClick (row) {
  689. this.$refs.deviceTable.getInst().toggleRowSelection(row)
  690. },
  691. onDeviceSelectionChange (devices) {
  692. this.selectedDevices = devices
  693. },
  694. onAddDevice () {
  695. this.selectedDevices.forEach(({ id, name }) => {
  696. if (!this.$deviceMap[id]) {
  697. this.$deviceMap[id] = 1
  698. this.devices.push({ id, name })
  699. }
  700. })
  701. this.$refs.deviceTable.getInst().clearSelection()
  702. },
  703. onDelDevice (index) {
  704. const { id } = this.devices.splice(index, 1)[0]
  705. delete this.$deviceMap[id]
  706. },
  707. onChangeDevices (done) {
  708. let change = false
  709. if (this.$task.enable) {
  710. if (this.devices.length) {
  711. change = this.devices.some(({ id }) => !this.$currDeviceMap[id])
  712. } else {
  713. change = true
  714. }
  715. }
  716. if (change && this.devices.length) {
  717. this.$confirm(
  718. '新增上刊设备需重新审核,将影响其他设备的节目单生成',
  719. '操作确认',
  720. { type: 'warning' }
  721. ).then(() => this.onSubmitDevices(change)).then(done)
  722. return
  723. }
  724. this.onSubmitDevices(change).then(done)
  725. },
  726. onSubmitDevices (change) {
  727. const data = {
  728. id: this.$task.id,
  729. deviceIdList: this.devices.map(({ id }) => id)
  730. }
  731. if (change) {
  732. data.enable = false
  733. }
  734. return updateTask(data).then(() => {
  735. this.$task.devices = this.devices
  736. if (change) {
  737. this.$task.enable = false
  738. this.$task.tag = this.getEnableTag(false)
  739. }
  740. })
  741. },
  742. onClosedDeviceDialog () {
  743. this.$task = null
  744. this.$deviceMap = null
  745. this.devices = []
  746. this.selectedDevices = []
  747. }
  748. }
  749. }
  750. </script>
  751. <style lang="scss" scoped>
  752. .c-task {
  753. line-height: 1;
  754. border-radius: $radius--sm;
  755. border: 1px solid #dcdfe6;
  756. &:hover {
  757. border-color: #c0c4cc;
  758. }
  759. &__name {
  760. position: absolute;
  761. width: 100%;
  762. height: 100%;
  763. }
  764. }
  765. ::v-deep .o-date-picker {
  766. display: flex;
  767. justify-content: space-between;
  768. align-items: center;
  769. width: auto;
  770. min-height: $height;
  771. padding: 3px 0;
  772. border: 1px solid $primary;
  773. border-radius: $radius--sm;
  774. background-color: $blue--light;
  775. &.jc {
  776. justify-content: center;
  777. }
  778. &:hover {
  779. border-color: $gray--dark;
  780. }
  781. .el-range-input {
  782. flex: 1 1 auto;
  783. width: auto;
  784. min-width: 0;
  785. background-color: $blue--light;
  786. }
  787. .el-range-separator {
  788. flex: 0 0 auto;
  789. min-width: 0;
  790. width: auto;
  791. padding: 0;
  792. font-size: $font-size--xs;
  793. }
  794. .el-input__icon {
  795. display: none;
  796. }
  797. }
  798. .c-device-toggle {
  799. &__button {
  800. padding: 0 $spacing $spacing;
  801. margin: 0 $spacing;
  802. border-left: 1px solid $border;
  803. border-right: 1px solid $border;
  804. }
  805. &__list {
  806. width: 400px;
  807. }
  808. &__item {
  809. border: 1px solid $gray;
  810. border-radius: $radius--sm;
  811. }
  812. &__del {
  813. display: inline-flex;
  814. justify-content: center;
  815. align-items: center;
  816. height: $height;
  817. color: $gray;
  818. font-size: $font-size--md;
  819. }
  820. }
  821. </style>