| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797 |
- <template>
- <wrapper
- v-loading="!dataMap.length"
- fill
- margin
- padding
- background
- >
- <status-wrapper
- slot="empty"
- :error="error"
- @click="getPublishWorkflowDetail"
- />
- <div v-if="dataMap.length">
- <div class="l-flex--row o-title has-bottom-padding u-color--black u-bold">{{ title }}</div>
- <div class="l-flex--row has-padding">
- <el-steps
- :active="active"
- finish-status="success"
- class="l-flex__fill"
- align-center
- >
- <el-step
- v-if="dataMap.includes('minios')"
- title="媒资审核"
- />
- <el-step
- v-if="dataMap.includes('items')"
- title="节目审核"
- />
- <el-step
- v-if="dataMap.includes('carousels')"
- title="轮播审核"
- />
- <el-step
- v-if="dataMap.includes('programCalendar')"
- title="排期审核"
- />
- <el-step
- v-if="dataMap.includes('calendarReleaseScheduling')"
- title="发布审核"
- />
- <el-step title="完成" />
- </el-steps>
- </div>
- <div class="l-flex--row fl-end has-padding">
- <!-- <el-button
- v-if="active === totalStep - 2"
- class="o-button"
- @click="onPublish"
- >确认发布</el-button
- > -->
- <el-button
- v-if="showTempReject && tempRejectInfo.length"
- class="o-button"
- @click="reject()"
- >{{ tempRejectMap[backDataType]["text"] }}</el-button>
- </div>
- <schema-table
- v-if="active < totalStep"
- ref="table"
- :key="tableKey"
- :schema="schema"
- @row-click="onToggle"
- >
- <preview-dialog ref="previewDialog" />
- <review-dialog
- v-if="dataMap[active] === 'minios'"
- ref="reviewDialog"
- :list="tableData"
- @resolve="onResolve"
- @reject="onConfirmReject"
- />
- <schedule-dialog ref="scheduleDialog" />
- </schema-table>
- <div
- v-if="active === totalStep"
- class="o-card has-padding"
- >
- <i class="el-icon-success o-card__icon" />
- <div class="o-card__title">发布成功</div>
- <div class="o-card__desc">排期发布成功!</div>
- </div>
- <confirm-dialog
- ref="rejectDialog"
- title="驳回"
- @confirm="onConfirmReject"
- >
- <div class="c-grid-form u-align-self--center">
- <span class="c-grid-form__label">审核意见:</span>
- <el-select
- v-model="review.type"
- placeholder="请选择"
- >
- <el-option
- v-for="option in reviewOptions"
- :key="option.label"
- :label="option.label"
- :value="option.value"
- />
- </el-select>
- <template v-if="review.type === 'reject'">
- <span class="c-grid-form__label required">原因:</span>
- <el-input
- v-model.trim="review.reason"
- type="textarea"
- placeholder="请填写驳回原因"
- maxlength="50"
- :rows="3"
- resize="none"
- show-word-limit
- />
- </template>
- </div>
- </confirm-dialog>
- </div>
- </wrapper>
- </template>
- <script>
- import ReviewDialog from './components/ReviewDialog'
- import {
- getPublishWorkflowDetail,
- calendarPublishReject
- } from '@/api/workflow'
- import { resolveAsset } from '@/api/asset'
- import { resolveProgram } from '@/api/program'
- import { resolveSchedule } from '@/api/calendar'
- import { resolvePublish } from '@/api/platform'
- import {
- parseByte, parseDuration
- } from '@/utils'
- import mediaMixin from '@/views/platform/media/mixin.js'
- import {
- State,
- ScheduleType,
- EventPriority,
- EventFreq,
- EventTarget,
- PublishType
- } from '@/constant'
- // 前端命名 和后端数据命名
- const front2back = {
- assets: 'minios',
- program: 'items',
- programRecur: 'carousels',
- schedule: 'programCalendar',
- publish: 'calendarReleaseScheduling'
- }
- // 数据 是否单个还是list
- const singleMap = {
- minios: false,
- items: false,
- carousels: false,
- programCalendar: true,
- calendarReleaseScheduling: true
- }
- // 数据 转 驳回type
- const data2type = {
- minios: 'minio',
- items: 'item',
- carousels: 'carousel',
- programCalendar: 'program',
- calendarReleaseScheduling: 'calendar'
- }
- // label
- const data2label = {
- minios: '媒资',
- items: '节目',
- carousels: '轮播',
- programCalendar: '排期',
- calendarReleaseScheduling: '发布'
- }
- function showOpt (status) {
- return ![State.RESOLVED, State.REJECTED].includes(status)
- }
- const allDataMap = [
- 'minios',
- 'items',
- 'carousels',
- 'programCalendar',
- 'calendarReleaseScheduling'
- ]
- export default {
- name: 'ReviewDetail',
- components: {
- ReviewDialog
- },
- data () {
- return {
- error: false,
- dataMap: [],
- active: 0,
- tableKey: 1,
- sourceMap: {}, // 总数据
- loaded: false,
- reviewOptions: [
- { value: 'reject', label: '驳回' },
- { value: '图文不符' },
- { value: '内容不合规' }
- ],
- review: {
- type: '',
- reason: ''
- },
- tempRejectInfo: [],
- tempRejectMap: {}
- }
- },
- computed: {
- backDataType () {
- return this.dataMap[this.active]
- },
- tableData () {
- return this.sourceMap[this.backDataType] || []
- },
- id () {
- return this.$route.params.id
- },
- title () {
- return this.$route.params.name
- },
- totalStep () {
- return this.dataMap.length + 1
- },
- showTempReject () {
- if (
- this.tempRejectMap[this.backDataType]
- && this.tempRejectMap[this.backDataType].length > 1
- ) {
- return true
- }
- return false
- },
- schema () {
- switch (this.backDataType) {
- case front2back['assets']:
- return {
- singlePage: true,
- condition: { status: State.REVIEW },
- list: this.getList('assets'),
- // transform: this.transform,
- cols: [
- { prop: 'typeName', label: '类型', align: 'center', width: 80 },
- { prop: 'file', type: 'asset', on: this.onViewAsset },
- { prop: 'originalName', label: '' },
- { prop: 'duration', label: '时长' },
- { prop: 'size', label: '文件大小' },
- { prop: 'createBy', label: '申请人' },
- { prop: 'ai', label: 'AI审核', type: 'tag', width: 100 },
- {
- label: '审核状态',
- type: 'tag',
- render ({ status }) {
- return {
- type: ['warning', 'warning', 'success', 'danger'][status],
- label: ['未审核', '未审核', '通过', '驳回'][status]
- }
- }
- },
- {
- type: 'invoke',
- width: 80,
- render: [{ label: '审核', on: this.onView }]
- }
- ]
- }
- case front2back['program']:
- return {
- singlePage: true,
- condition: { status: State.REVIEW },
- list: this.getList('program'),
- // transform: this.transform,
- cols: [
- { prop: 'name', label: '节目名称', 'min-width': 100 },
- { prop: 'resolutionRatio', label: '分辨率' },
- { prop: 'createBy', label: '申请人' },
- {
- label: '审核状态',
- type: 'tag',
- render ({ status }) {
- return {
- type: ['warning', 'warning', 'success', 'danger'][status],
- label: ['未审核', '未审核', '通过', '驳回'][status]
- }
- }
- },
- {
- type: 'invoke',
- width: 160,
- render: [
- { label: '查看', on: this.onView },
- {
- label: '通过',
- render ({ status }) {
- return showOpt(status)
- },
- on: this.onResolve
- },
- {
- label: '驳回',
- render ({ status }) {
- return showOpt(status)
- },
- on: this.onReject
- }
- ]
- }
- ]
- }
- case front2back['programRecur']:
- case front2back['schedule']:
- return {
- singlePage: true,
- condition: {
- type: ScheduleType.COMPLEX,
- status: State.REVIEW
- },
- list: this.getList('schedule'),
- cols: [
- { prop: 'name', label: '排期名称', 'min-width': 100 },
- { prop: 'resolutionRatio', label: '分辨率' },
- { prop: 'createBy', label: '申请人' },
- {
- label: '审核状态',
- type: 'tag',
- render ({ status }) {
- return {
- type: ['warning', 'warning', 'success', 'danger'][status],
- label: ['未审核', '未审核', '通过', '驳回'][status]
- }
- }
- },
- {
- type: 'invoke',
- width: 160,
- render: [
- { label: '查看', on: this.onView },
- {
- label: '通过',
- render ({ status }) {
- return showOpt(status)
- },
- on: this.onResolve
- },
- {
- label: '驳回',
- render ({ status }) {
- return showOpt(status)
- },
- on: this.onReject
- }
- ]
- }
- ]
- }
- case front2back['publish']:
- return {
- singlePage: true,
- condition: { status: State.REVIEW },
- list: this.getList('publish'),
- // transform: this.transform,
- cols: [
- {
- prop: 'expand',
- type: 'expand',
- render (data, h) {
- return h(
- 'div',
- {
- staticClass: 'o-info'
- },
- [
- h('div', null, data.desc),
- h('div', null, `设备:${data.device}`)
- ]
- )
- }
- },
- { prop: 'type', label: '类型', width: 100 },
- { prop: 'name', label: '名称', 'min-width': 100 },
- { prop: 'resolutionRatio', label: '分辨率' },
- { prop: 'createBy', label: '申请人' },
- {
- type: 'invoke',
- width: 160,
- render: [
- { label: '查看', on: this.onView },
- {
- label: '通过',
- render ({ status }) {
- return showOpt(status)
- },
- on: this.onPublish
- },
- {
- label: '驳回',
- render ({ status }) {
- return showOpt(status)
- },
- on: this.onReject
- }
- ]
- }
- ]
- }
- default:
- return {}
- }
- }
- },
- mounted () {
- this.getPublishWorkflowDetail()
- },
- methods: {
- // 判断是否需要缓存驳回
- calTempReject (item) {
- if (!singleMap[item]) {
- this.tempRejectMap[item] = {
- text: `${data2label[item]}驳回`,
- show:
- !this.tempRejectMap.length
- && this.sourceMap[item].filter(i => ![State.RESOLVED, State.REJECTED].includes(i.status))
- .length
- }
- }
- },
- async getPublishWorkflowDetail () {
- let res = await getPublishWorkflowDetail(this.id).catch(err => {
- console.log(err)
- })
- if (!res || !res.success) {
- this.error = true
- return
- }
- this.error = false
- res = res.data
- for (const key in res) {
- if (Object.prototype.hasOwnProperty.call(res, key)) {
- const element = res[key]
- if (!Array.isArray(element)) {
- res[key] = [element]
- }
- }
- }
- this.sourceMap = res
- // init
- // 判断步骤 filter datamap 并transform row
- const temp = []
- for (const item of allDataMap) {
- if (this.sourceMap[item][0]) {
- this.sourceMap[item] = this.sourceMap[item].map(row => this.transform(row, item))
- temp.push(item)
- // 处理缓存驳回初始状态
- if (!singleMap[item]) {
- this.tempRejectMap[item] = {
- text: `${data2label[item]}驳回`,
- length: this.sourceMap[item].filter(
- i => ![State.RESOLVED, State.REJECTED].includes(i.status)
- ).length
- }
- }
- }
- }
- this.dataMap = temp
- // 确定节点
- let active = 0
- for (const item of this.dataMap) {
- if (this.sourceMap[item].every(i => i.status === State.RESOLVED)) {
- active++
- continue
- }
- break
- }
- this.active = active
- if (this.active === this.totalStep - 1) {
- this.active = this.totalStep
- }
- // this.$refs.table.onPagination();
- },
- refresh () {
- this.getPublishWorkflowDetail()
- },
- refreshStatus (item, status, review) {
- const list = this.sourceMap[this.backDataType]
- const index = list.findIndex(i => i.id === item.id)
- list[index].status = status
- this.$refs.table.onPagination()
- if (status === State.RESOLVED && this.tableData.every(i => i.status === State.RESOLVED)) {
- this.closePreviewDialog()
- this.nextStep()
- }
- if (status === State.REJECTED) {
- list[index].review = review
- }
- },
- getList () {
- return () => Promise.resolve({ data: this.tableData })
- },
- // 全部审批通过
- nextStep () {
- this.active += 1
- if (this.active === this.totalStep - 1) {
- this.active = this.totalStep
- }
- this.tempRejectInfo = []
- this.tableKey++
- },
- next () {
- if (this.active++ > 5) {
- this.active = 0
- }
- this.tableKey++
- },
- transform (row, kind) {
- const { type } = row
- switch (kind) {
- case front2back['assets']:
- row.typeName = [null, '图片', '视频', '音频'][type]
- row.file = {
- type: row.type,
- url: row.keyName,
- thumbnail: row.thumbnail
- }
- row.duration = parseDuration(row.duration)
- row.size = parseByte(row.size)
- row.createBy = row.userName || row.createBy
- row.ai = mediaMixin.methods.getAIState(row)
- row.id = row.keyName
- return row
- case front2back['program']:
- row.createBy = row.userName || row.createBy
- return row
- case front2back['publish']:
- return { ...this.getSame(row), ...this.getDiff(row) }
- default:
- return row
- }
- },
- // publish 排期辅助函数
- getSame ({
- id,
- programCalendarName,
- resolutionRatio,
- createBy,
- createByUsername,
- createTime,
- calendarReleaseDeviceList
- }) {
- return {
- id,
- name: programCalendarName,
- resolutionRatio,
- createBy: createByUsername || createBy,
- createTime,
- device: calendarReleaseDeviceList
- ?.map(item => item.deviceName)
- .join(',')
- }
- },
- getDiff (item) {
- const target = JSON.parse(item.target)
- let type = ''
- switch (target.type) {
- case PublishType.CALENDAR:
- type = '排期'
- break
- case PublishType.EVENT:
- type = ['', '默认播放', '单播', '插播'][target.detail.priority]
- break
- default:
- break
- }
- return {
- type,
- target,
- desc: this.getDesc(target)
- }
- },
- getDesc (target) {
- if (
- target.type === PublishType.EVENT
- && target.detail.priority === EventPriority.INSERTED
- ) {
- const { freq, start, until, byDay, startTime, endTime } = target.detail
- switch (freq) {
- case EventFreq.WEEKLY:
- return `自${start.split(' ')[0]}开始${
- until ? `${until.split(' ')[0]}前` : ''
- } 每周${byDay
- .split(',')
- .map(val => ['日', '一', '二', '三', '四', '五', '六'][val])
- .join('、')} ${startTime} - ${endTime}`
- default:
- return until ? `${start} - ${until}` : `自${start}开始`
- }
- }
- return ''
- },
- onToggle (row) {
- if (this.backDataType !== 'publish') {
- return
- }
- this.$refs.table.getInst().toggleRowExpansion(row)
- },
- onPublishView ({ target: { type, detail } }) {
- switch (type) {
- case PublishType.CALENDAR:
- this.viewSchedule(detail)
- break
- case PublishType.EVENT:
- if (detail.target.type === EventTarget.RECUR) {
- this.viewSchedule(detail.target.id)
- } else {
- this.viewProgram(detail.target.id)
- }
- break
- default:
- break
- }
- },
- viewSchedule (id) {
- this.$refs.scheduleDialog.show(id)
- },
- viewProgram (id) {
- this.$viewProgram(id)
- },
- // 查看
- onView (row) {
- const { id } = row
- switch (this.backDataType) {
- case front2back['assets']:
- this.$refs.reviewDialog.show(
- this.tableData.findIndex(i => i.id === id)
- )
- break
- case front2back['program']:
- this.$viewProgram(id)
- break
- case front2back['schedule']:
- case front2back['programRecur']:
- this.$refs.scheduleDialog.show(id)
- break
- case front2back['publish']:
- this.onPublishView(row)
- break
- default:
- break
- }
- },
- onViewAsset (asset) {
- this.$refs.previewDialog.show(asset)
- },
- closePreviewDialog () {
- if (this.backDataType === front2back['assets']) {
- this.$refs.reviewDialog.close()
- }
- },
- // 通过
- onResolve (item) {
- this.resolve(item).then(() => {
- this.refreshStatus(item, State.RESOLVED)
- })
- },
- resolve (item) {
- switch (this.backDataType) {
- case front2back['assets']:
- return resolveAsset(item)
- case front2back['program']:
- return resolveProgram(item)
- case front2back['schedule']:
- case front2back['programRecur']:
- return resolveSchedule(item)
- case front2back['publish']:
- return resolvePublish(item)
- default:
- return new Promise().reject()
- }
- },
- // 行内
- // 驳回 列表按钮触发
- onReject (item) {
- this.$item = item
- this.review = {
- type: 'reject',
- reason: ''
- }
- this.$refs.rejectDialog.show()
- },
- // dialog 直接触发
- onConfirmReject (done, props) {
- if (props) {
- const { item, review } = props
- this.$item = item
- this.review = review
- }
- const reason =
- this.review.type === 'reject' ? this.review.reason : this.review.type
- if (!reason) {
- this.$message({
- type: 'warning',
- message: '请选择或填写驳回原因'
- })
- return
- }
- const rejectInfo = {
- id: this.$item.id,
- name: this.$item.name || this.$item.originalName,
- remark: reason
- }
- if (this.showTempReject) {
- this.$confirm(`驳回 ${rejectInfo.name} ?`, {
- type: 'warning'
- }).then(() => {
- // 缓存驳回数据
- done()
- this.tempRejectInfo.push(rejectInfo)
- this.refreshStatus(this.$item, State.REJECTED, {
- type: this.review.type,
- reason: this.review.reason
- })
- })
- } else {
- // 取最新
- done()
- this.reject([rejectInfo], rejectInfo.name)
- }
- },
- // 流程驳回
- reject (
- rejectInfo = this.tempRejectInfo,
- name = data2label[this.backDataType]
- ) {
- return calendarPublishReject(
- this.id,
- {
- type: data2type[this.backDataType],
- rejectInfo
- },
- name
- )
- .then(() => {
- this.$router.push({ name: 'workflow-list' })
- })
- .catch(err => {
- console.log(err)
- })
- },
- // 确认发布
- onPublish () {
- resolvePublish({
- name: this.tableData[0].programCalendarName,
- id: this.tableData[0].id
- }).then(() => {
- this.nextStep()
- })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .o-card {
- display: flex;
- align-items: center;
- flex-direction: column;
- width: 100%;
- padding-top: 100px;
- &__icon {
- color: #04a681;
- font-size: 48px;
- }
- &__title {
- font-size: 16px;
- font-weight: 500;
- color: #333333;
- line-height: 36px;
- }
- &__desc {
- font-weight: 400;
- color: #d5d9e4;
- line-height: 36px;
- font-size: 14px;
- padding-left: 15px;
- }
- }
- .o-title {
- font-size: 18px;
- }
- .fl-end {
- justify-content: flex-end;
- }
- </style>
|