| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680 |
- <template>
- <wrapper
- fill
- margin
- padding
- background
- horizontal
- >
- <schema-table
- ref="table"
- class="c-sibling-item far"
- row-key="id"
- :schema="schema"
- />
- <table-dialog
- ref="contentDialog"
- size="medium"
- title="上播内容"
- :schema="contentSchema"
- />
- <asset-task-dialog
- ref="taskDialog"
- @view="onViewAsset"
- @confirm="onSubmitAssetTask"
- />
- <radio-table-dialog
- ref="contractTableDialog"
- title="新增合同任务"
- message="请选择合同"
- :schema="contractTableSchema"
- @confirm="onSubmitContractTask"
- />
- <preview-dialog ref="previewDialog" />
- <confirm-dialog
- ref="timeDialog"
- title="上播时间设置"
- @confirm="onConfirmTime"
- >
- <div class="c-grid-form auto u-align-self--center">
- <div class="c-grid-form__label">上播方式</div>
- <schema-select
- v-model="taskTime.type"
- class="u-width"
- :schema="taskTimeTypeSelectSchema"
- />
- <template v-if="taskTime.type === 2">
- <div class="c-grid-form__label">时段</div>
- <el-time-picker
- key="task-range-picker"
- v-model="taskTime.range"
- class="u-width"
- is-range
- value-format="HH:mm:ss"
- :clearable="false"
- />
- </template>
- <template v-if="taskTime.type === 3">
- <div class="c-grid-form__label">时间点</div>
- <el-time-picker
- key="task-time-picker"
- v-model="taskTime.point"
- class="u-width"
- value-format="HH:mm:ss"
- :clearable="false"
- />
- </template>
- </div>
- </confirm-dialog>
- <multi-device-dialog
- ref="multiDeviceDialog"
- @confirm="onChangeDevices"
- />
- </wrapper>
- </template>
- <script>
- import {
- TimeType,
- SCREEN_TIME_KEY,
- TaskFromType,
- TaskFromTypeInfo,
- AssetType,
- AssetTypeInfo
- } from '@/constant'
- import {
- parseDuration,
- parseTaskTime,
- getTaskTimeInfo,
- transformToTaskTime,
- offsetDate,
- calculateDay,
- transformOrderAssetToAsset,
- transformContractAssetToAsset
- } from '@/utils'
- import {
- getOrderDetail,
- getContracts,
- getContract
- } from '../api'
- import {
- getDepartmentTasks,
- addDepartmentTask,
- deleteTask,
- updateTask
- } from './api'
- import AssetTaskDialog from './components/AssetTaskDialog.vue'
- export default {
- name: 'AdAssetTask',
- components: {
- AssetTaskDialog
- },
- data () {
- const canEdit = this.$store.getters.isOperator
- const canAudit = this.$store.getters.isGroupAdmin
- return {
- schema: {
- props: {
- size: 'small'
- },
- list: getDepartmentTasks,
- transform: this.transform,
- buttons: canEdit
- ? [
- { type: 'add', label: '文件资源任务', on: this.onAddAssetTask },
- { type: 'add', label: '流媒体任务', on: this.onAddStreamTask },
- { type: 'add', label: '合同任务', on: this.onAddContractTask }
- ]
- : null,
- cols: [
- { prop: 'type', type: 'refresh', width: 72 },
- { render: (data, h) => data.allowed
- ? h(
- 'div',
- {
- staticClass: 'u-ellipsis has-active',
- on: {
- click: () => this.onViewTask(data)
- }
- },
- data.name
- )
- : data.name },
- { label: '上刊设备', render: (data, h) => h(
- 'div',
- {
- staticClass: canEdit ? 'u-ellipsis has-active' : 'u-ellipsis',
- on: canEdit
- ? {
- click: () => this.onEditDevices(data)
- }
- : {}
- },
- data.devices.length > 1
- ? `${data.devices[0].name}等`
- : data.devices.length === 1
- ? data.devices[0].name
- : '暂未绑定'
- ), 'min-width': 100 },
- { label: '上刊日期', render: (data, h) => canEdit && data.allowed && data.from === TaskFromType.ASSET
- ? h('el-date-picker', {
- staticClass: 'o-date-picker',
- props: {
- value: [data.startDate, data.endDate],
- type: 'daterange',
- rangeSeparator: '至',
- valueFormat: 'yyyy-MM-dd',
- editable: false,
- clearable: false
- },
- on: {
- input: val => this.onDateEdit(data, val)
- }
- })
- : `${data.startDate} 至 ${data.endDate}`, width: 200, align: 'center' },
- { label: '上播时间', render: (data, h) => canEdit && data.allowed && data.from === TaskFromType.ASSET
- ? h('div', {
- staticClass: 'o-date-picker jc',
- on: {
- click: () => this.onEditTime(data)
- }
- }, data.range)
- : data.range, width: 160, align: 'center' },
- { label: '单次时长(s)', render: (data, h) => canEdit && this.canEditDuration(data)
- ? h('edit-input', {
- staticClass: 'sm border',
- props: {
- value: `${data.duration}`,
- align: 'center'
- },
- on: {
- edit: val => this.onSimpleEdit(data, 'duration', val)
- }
- })
- : data.duration, 'min-width': 96, align: 'center' },
- { label: '上播次数', render: (data, h) => canEdit && data.allowed && data.from === TaskFromType.ASSET
- ? h('edit-input', {
- staticClass: 'sm border',
- props: {
- value: `${data.count}`,
- align: 'center'
- },
- on: {
- edit: val => this.onSimpleEdit(data, 'count', val)
- }
- })
- : data.count, align: 'center' },
- { label: '审核次数', render: (data, h) => canAudit && data.allowed
- ? h('edit-input', {
- staticClass: 'sm border',
- props: {
- value: `${data.auditCount}`,
- align: 'center'
- },
- on: {
- edit: val => this.onAuditEdit(data, val)
- }
- })
- : '-', align: 'center' },
- { prop: 'tag', type: 'tag', size: 'sm', on: canAudit && this.onAudit, width: 80 },
- { type: 'invoke', render: [
- { label: '查看', allow: ({ allowed }) => allowed, on: this.onViewTask },
- { label: '删除', allow: ({ from }) => from !== TaskFromType.ORDER, on: this.onDel }
- ], width: 92 }
- ]
- },
- contentSchema: {
- singlePage: true,
- list: this.getContentAssets,
- cols: [
- { prop: 'tagInfo', label: '类型', width: 100, align: 'center' },
- { prop: 'typeInfo', label: '资源', width: 72, align: 'center' },
- { prop: 'file', label: '', type: 'asset', on: this.onViewAsset },
- { prop: 'name', label: '' },
- { prop: 'adDuration', label: '上播时长', align: 'center' },
- { type: 'invoke', render: [
- { label: '查看', allow: ({ file }) => !!file, on: this.onViewAsset }
- ] }
- ]
- },
- contractTableSchema: {
- list: getContracts,
- transform: this.transformContract,
- filters: [
- { key: 'name', type: 'search', placeholder: '合同名称' }
- ],
- cols: [
- { prop: 'name', label: '名称' },
- { prop: 'dateRange', label: '上刊日期', 'width': 200 },
- { prop: 'timeRange', label: '上播时间' },
- { prop: 'count', label: '上播次数' },
- { prop: 'durationInfo', label: '上播时长' }
- ]
- },
- taskTimeTypeSelectSchema: {
- options: [
- { value: TimeType.SCREEN, label: '开机期间' },
- { value: TimeType.RANGE, label: '时段' },
- { value: TimeType.POINT, label: '时间点' }
- ]
- },
- taskTime: {}
- }
- },
- methods: {
- canEditDuration ({ allowed, from, fromInfo }) {
- return allowed && from === TaskFromType.ASSET && fromInfo?.type === AssetType.IMAGE
- },
- transform (task) {
- const { id, devices, from, fromId, fromInfo, startDate, startTime, endTime, day, duration, count, auditCount, enable } = task
- const allowed = this.isValidTask(from, fromInfo)
- return {
- id,
- devices,
- from,
- fromId,
- fromInfo,
- type: this.getDataType(task),
- name: this.getDataName(task),
- startDate,
- endDate: offsetDate(startDate, day),
- startTime,
- endTime,
- range: getTaskTimeInfo({ startTime, endTime }),
- count,
- duration,
- auditCount,
- enable,
- tag: allowed
- ? this.getEnableTag(enable)
- : {
- type: 'danger',
- label: '异常',
- msg: '源数据丢失'
- },
- allowed
- }
- },
- isValidTask (from, fromInfo) {
- switch (from) {
- case TaskFromType.ORDER:
- return true
- default:
- return !!fromInfo
- }
- },
- getDataType ({ from, fromInfo }) {
- if (from === TaskFromType.ASSET && fromInfo) {
- return AssetTypeInfo[fromInfo.type]
- }
- return TaskFromTypeInfo[from]
- },
- getDataName ({ from, fromInfo }) {
- switch (from) {
- case TaskFromType.ORDER:
- return '自助广告'
- default:
- return fromInfo?.name || '-'
- }
- },
- getEnableTag (enable) {
- return {
- type: enable ? 'success' : 'primary',
- label: enable ? '已审核' : '待审核'
- }
- },
- transformContract (contract) {
- contract.durationInfo = parseDuration(contract.duration)
- contract.dateRange = `${contract.startDate} 至 ${offsetDate(contract.startDate, contract.day)}`
- contract.timeRange = getTaskTimeInfo(contract)
- return contract
- },
- onViewTask (task) {
- switch (task.from) {
- case TaskFromType.ORDER:
- getOrderDetail(task.fromId).then(({ data }) => {
- this.showContentDialog(data.assets.map(transformOrderAssetToAsset))
- })
- break
- case TaskFromType.ASSET:
- this.onViewAsset({
- file: {
- type: task.fromInfo.type,
- url: task.fromId
- }
- })
- break
- case TaskFromType.CONTRACT:
- getContract(task.fromId).then(({ data }) => {
- this.showContentDialog(data.assets.map(transformContractAssetToAsset))
- })
- break
- default:
- break
- }
- },
- showContentDialog (assets) {
- if (assets.length === 1) {
- assets[0].adDuration = '独占'
- }
- this.$assets = assets
- this.$refs.contentDialog.show()
- },
- getContentAssets () {
- return Promise.resolve({ data: this.$assets })
- },
- onViewAsset ({ file }) {
- this.$refs.previewDialog.show(file)
- },
- onDel ({ id, type, name }) {
- deleteTask(id, `${type} ${name}`).then(() => {
- this.$refs.table.decrease(1)
- })
- },
- onAddAssetTask () {
- this.$refs.taskDialog.show()
- },
- onAddStreamTask () {
- this.$refs.taskDialog.show(AssetType.STREAMING_MEDIA)
- },
- onSubmitAssetTask ({ value, done }) {
- this.addTask(value).then(done)
- },
- onAddContractTask () {
- this.$refs.contractTableDialog.show()
- },
- onSubmitContractTask ({ value, done }) {
- this.addTask({
- from: TaskFromType.CONTRACT,
- fromId: value.id,
- startDate: value.startDate,
- day: value.day,
- startTime: value.startTime,
- endTime: value.endTime,
- count: value.count,
- duration: value.duration
- }).then(done)
- },
- addTask (task) {
- return addDepartmentTask({
- ...task,
- auditCount: task.count,
- enable: false
- }).then(() => {
- this.$refs.table.pageTo(1)
- })
- },
- onAudit (task) {
- const { allowed, devices, enable, startTime, endTime, duration, auditCount } = task
- if (!allowed) {
- return
- }
- if (!devices.length) {
- this.$message({
- type: 'warning',
- message: '请先添加上刊设备'
- })
- return
- }
- if (!enable) {
- const totalDuration = duration * auditCount * 1000
- if (startTime && endTime && endTime !== SCREEN_TIME_KEY) {
- const remind = new Date(`2000-01-01 ${endTime}`) - new Date(`2000-01-01 ${startTime}`)
- if (remind < totalDuration) {
- this.$message({
- type: 'warning',
- message: '所选时段无法满足上播次数'
- })
- return
- }
- }
- }
- this.$confirm(
- enable ? '停止使用后将不可参与自动编单' : '启用后将可参与自动编单',
- enable ? '停用任务' : '启用任务',
- { type: 'warning' }
- ).then(() => {
- this.onUpdateEnable(task)
- })
- },
- onUpdateEnable (task) {
- const { id, enable } = task
- updateTask({
- id,
- enable: !enable
- }).then(() => {
- task.enable = !enable
- task.tag = this.getEnableTag(!enable)
- })
- },
- onSimpleEdit (task, key, { newVal, oldVal }) {
- if (!newVal || !/^\d+$/.test(newVal) || Number(newVal) < 1) {
- return
- }
- if (newVal !== oldVal) {
- task[key] = Number(newVal)
- updateTask({
- id: task.id,
- enable: false,
- [key]: newVal
- }).then(
- () => {
- if (task.enable) {
- task.enable = false
- task.tag = this.getEnableTag(false)
- }
- },
- () => {
- task[key] = oldVal
- }
- )
- }
- },
- onDateEdit (task, val) {
- const { id, enable, startDate, endDate } = task
- if (startDate !== val[0] || endDate !== val[1]) {
- const day = calculateDay(val[0], val[1]) + 1
- updateTask({
- id,
- enable: false,
- startDate: val[0],
- day
- }).then(
- () => {
- if (enable) {
- task.enable = false
- task.tag = this.getEnableTag(false)
- }
- task.startDate = val[0]
- task.endDate = val[1]
- task.day = day
- }
- )
- }
- },
- onAuditEdit (task, { newVal, oldVal }) {
- if (!newVal || !/^\d+$/.test(newVal) || Number(newVal) < 1) {
- return
- }
- if (newVal !== oldVal) {
- const auditCount = Number(newVal)
- if (task.from === TaskFromType.ORDER && auditCount < task.count) {
- this.$message({
- type: 'warning',
- message: '订单的审核次数不能小于上播次数'
- })
- return
- }
- if (task.from === TaskFromType.CONTRACT && auditCount < task.count) {
- this.$message({
- type: 'warning',
- message: '合同的审核次数不能小于上播次数'
- })
- return
- }
- task.auditCount = auditCount
- updateTask({
- id: task.id,
- enable: false,
- auditCount
- }).then(
- () => {
- if (task.enable) {
- task.enable = false
- task.tag = this.getEnableTag(false)
- }
- },
- () => {
- task.auditCount = oldVal
- }
- )
- }
- },
- onEditTime (task) {
- this.$task = task
- this.taskTime = parseTaskTime(task)
- this.$refs.timeDialog.show()
- },
- onConfirmTime (done) {
- const { id, enable, startTime, endTime } = this.$task
- const { startTime: targetStartTime, endTime: targetEndTime } = transformToTaskTime(this.taskTime)
- if (!targetStartTime) {
- this.$message({
- type: 'warning',
- message: '请选择上播时间'
- })
- return
- }
- if (startTime !== targetStartTime || endTime !== targetEndTime) {
- updateTask({
- id,
- enable: false,
- startTime: targetStartTime,
- endTime: targetEndTime
- }).then(
- () => {
- if (enable) {
- this.$task.enable = false
- this.$task.tag = this.getEnableTag(false)
- }
- this.$task.startTime = targetStartTime
- this.$task.endTime = targetEndTime
- this.$task.range = getTaskTimeInfo({ startTime: targetStartTime, endTime: targetEndTime })
- done()
- }
- )
- } else {
- done()
- }
- },
- onEditDevices (task) {
- if (!task.allowed) {
- return
- }
- this.$task = task
- this.$currDeviceMap = {}
- task.devices.forEach(({ id }) => {
- this.$currDeviceMap[id] = 1
- })
- this.$refs.multiDeviceDialog.show([...task.devices])
- },
- onChangeDevices ({ value, done }) {
- let change = false
- if (this.$task.enable) {
- if (value.length) {
- change = value.some(({ id }) => !this.$currDeviceMap[id])
- } else {
- change = true
- }
- }
- if (change && value.length) {
- this.$confirm(
- '新增上刊设备需重新审核,将影响其他设备的节目单生成',
- '操作确认',
- { type: 'warning' }
- ).then(() => this.onSubmitDevices(change, value)).then(done)
- return
- }
- this.onSubmitDevices(change, value).then(done)
- },
- onSubmitDevices (change, devices) {
- const data = {
- id: this.$task.id,
- deviceIdList: devices.map(({ id }) => id)
- }
- if (change) {
- data.enable = false
- }
- return updateTask(data).then(() => {
- this.$task.devices = devices
- if (change) {
- this.$task.enable = false
- this.$task.tag = this.getEnableTag(false)
- }
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .c-task {
- line-height: 1;
- border-radius: $radius--sm;
- border: 1px solid #dcdfe6;
- &:hover {
- border-color: #c0c4cc;
- }
- &__name {
- position: absolute;
- width: 100%;
- height: 100%;
- }
- }
- ::v-deep .o-date-picker {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: auto;
- height: $height--sm;
- padding: 2px 0;
- line-height: $height--sm - 6px;
- border: 1px solid $primary;
- border-radius: $radius--sm;
- background-color: $blue--light;
- &.jc {
- justify-content: center;
- }
- &:hover {
- border-color: $gray--dark;
- }
- .el-range-input {
- flex: 1 1 auto;
- width: auto;
- min-width: 0;
- font-size: $font-size--xs;
- background-color: $blue--light;
- }
- .el-range-separator {
- flex: 0 0 auto;
- min-width: 0;
- width: auto;
- padding: 0;
- font-size: $font-size--xs;
- line-height: inherit;
- }
- .el-input__icon {
- display: none;
- }
- }
- </style>
|