123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- <!-- 创意列表页 -->
- <template>
- <el-form :inline="true">
- <el-form-item label="名称">
- <el-input v-model="page.keyword" placeholder="输入创意关键词" clearable />
- </el-form-item>
- <el-form-item label="广告主">
- <el-select
- filterable
- v-model="page.advertiserId"
- placeholder="选择广告主"
- clearable
- style="width: 240px"
- >
- <el-option
- v-for="item in AdvertiserList"
- :key="item.advertiserId"
- :label="item.enterpriseName"
- :value="item.advertiserId"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="getOriginality">搜索</el-button>
- <el-button type="primary" link @click="() => creatEditPlan()">创建</el-button>
- </el-form-item>
- </el-form>
- <el-table :data="tableData" stripe style="width: 100%">
- <el-table-column prop="creativeName" label="名称">
- <template #default="scope">
- <el-button text @click="() => linkSourceMaterial(scope.row.creativeId, true)">{{
- scope.row.creativeName
- }}</el-button>
- </template>
- </el-table-column>
- <el-table-column prop="statusDesc" label="排期状态" width="80" />
- <el-table-column prop="publishStatusDesc" label="发布状态" width="80" />
- <el-table-column prop="startDate" label="生效日期" width="120" />
- <el-table-column prop="endDate" label="结束日期" width="120" />
- <el-table-column label="操作">
- <template #default="scope">
- <el-button
- v-if="scope.row.creativeId"
- link
- size="small"
- type="primary"
- @click="() => linkSourceMaterial(scope.row.creativeId)"
- >
- 创建素材
- </el-button>
- <el-popconfirm
- title="确定删除该创意吗?"
- @confirm="deleteOriginalityFun(scope.row.creativeId)"
- >
- <template #reference>
- <el-button link type="primary" size="small">删除</el-button>
- </template>
- </el-popconfirm>
- <div v-if="scope.row.status !== 7" style="display: inline-block">
- <el-popconfirm
- title="确定上线该创意吗?"
- v-if="scope.row.publishStatus == 6 || scope.row.publishStatus == 0"
- @confirm="publishAsTreeFunc(scope.row.creativeId)"
- >
- <template #reference>
- <el-button link type="primary" size="small">上线</el-button>
- </template>
- </el-popconfirm>
- <el-popconfirm
- title="确定下线该创意吗?"
- v-if="scope.row.publishStatus == 10"
- @confirm="changeStatus(scope.row.creativeId, 6, '下线成功')"
- >
- <template #reference>
- <el-button link type="primary" size="small">下线</el-button>
- </template>
- </el-popconfirm>
- </div>
- <el-button link type="primary" size="small" @click="() => creatEditPlan(scope.row)">
- 修改
- </el-button>
- </template>
- </el-table-column>
- </el-table>
- <br />
- <el-pagination
- background
- layout="prev, pager, next"
- :default-page-size="page.pageSize"
- :total="page.total"
- @current-change="changePage"
- />
- <el-dialog v-model="dialogVisible" title="创意" width="700">
- <el-form :model="form" label-width="auto" ref="ruleFormRef" :rules="rules">
- <el-form-item label="创意名称" prop="creativeName">
- <el-input v-model="form.creativeName" prop="creativeName" />
- </el-form-item>
- <el-form-item label="广告主" prop="advertiserId">
- <el-select filterable clearable v-model="form.advertiserId" placeholder="选择广告主">
- <el-option
- v-for="item in AdvertiserList"
- :key="item.advertiserId"
- :label="item.enterpriseName"
- :value="item.advertiserId"
- />
- </el-select>
- </el-form-item>
- <el-form-item label="周期" prop="dates">
- <el-date-picker
- v-model="form.dates"
- type="daterange"
- @change="() => getAs()"
- format="YYYY-MM-DD"
- value-format="YYYY-MM-DD"
- range-separator="到"
- start-placeholder="开始时间"
- end-placeholder="结束时间"
- />
- </el-form-item>
- <el-form-item label="站点" prop="mediaIds">
- <el-checkbox-group @change="() => getAs()" v-model="form.mediaIds">
- <el-checkbox
- :value="v.mediaId"
- disabled
- size="large"
- v-for="v in siteList"
- :key="v.mediaId"
- >{{ v.mediaName }}</el-checkbox
- >
- </el-checkbox-group>
- </el-form-item>
- <el-form-item label="投放形式" prop="showType">
- <el-select filterable v-model="form.showType">
- <el-option
- v-for="item in typeOptions"
- :key="item.value"
- :label="item.label"
- :value="item.value"
- />
- </el-select>
- </el-form-item>
- <el-form-item
- v-if="form.showType !== 3"
- :label="form.showType == 1 ? '轮播间隔' : '交替时长'"
- prop="showIntervalTime"
- >
- <el-input-number v-model="form.showIntervalTime" :min="0" />
- {{ form.showType == 1 ? '秒' : '分钟' }}
- </el-form-item>
- <el-form-item label="创意排期" prop="intervalType">
- <div>
- <el-radio-group
- v-model="form.intervalType"
- @change="(val: number) => changeIntervalType(val)"
- >
- <el-radio :value="1" size="large">全时段</el-radio>
- <el-radio :value="2" size="large">自定义</el-radio>
- </el-radio-group>
- <el-table v-if="form.intervalType === 2" :data="tableSchedulingData" style="width: 500px">
- <el-table-column fixed="left" prop="weekName" label="" width="60" />
- <el-table-column fixed="left" prop="selectAll" label="全选" width="60">
- <template #default="scope">
- <el-checkbox
- @change="(val: boolean) => selectAll(val, scope.row, scope.$index)"
- v-model="scope.row.selectAll"
- size="large"
- />
- </template>
- </el-table-column>
- <el-table-column :label="i - 1 + '时'" v-for="i in 24" center :key="i" width="60">
- <template #default="scope">
- <el-checkbox
- @change="(val: boolean) => select(val, scope.row, scope.$index)"
- v-model="scope.row[i - 1]"
- size="large"
- />
- </template>
- </el-table-column>
- </el-table>
- </div>
- </el-form-item>
- <el-form-item label="广告位" prop="slot">
- <el-select
- filterable
- multiple
- collapse-tags
- v-model="form.slot"
- placeholder="选择广告位"
- clearable
- >
- <el-option
- v-for="item in options"
- :key="item.slotId"
- :label="item.slotName"
- :value="item.slotId"
- />
- </el-select>
- </el-form-item>
- <el-form-item>
- <el-button type="primary" @click="() => createOrUpdate(ruleFormRef)">确定</el-button>
- </el-form-item>
- </el-form>
- </el-dialog>
- </template>
- <script setup lang="ts">
- import type {
- OriginalityItem,
- OriginalityList,
- TimeInterval,
- TimeIntervalList,
- AdvertiserItem,
- } from '@/types/AdListPage'
- import type { AsSpaceItem } from '@/types/AsSpace'
- import type { Pages } from '@/types/Tool'
- import type { SiteList } from '@/types/Site'
- import {
- getOriginalityList,
- getSiteList,
- getOriginalityDetail,
- getAsList,
- deleteOriginality,
- getAdvertiserList,
- createOriginality,
- updateOriginality,
- updateOriginalityStatus,
- onlineOriginality,
- } from '@/api/index'
- import { ElLoading, ElMessage } from 'element-plus'
- import { ref } from 'vue'
- import { useRouter } from 'vue-router'
- import type { FormInstance } from 'element-plus'
- import { formatDate } from '@/tool/index'
- const router = useRouter()
- const dialogVisible = ref(false)
- const form = ref<OriginalityItem>({})
- const page = ref<Pages>({
- pageNum: 1,
- pageSize: 20,
- total: 0,
- keyword: '',
- })
- const ruleFormRef = ref<FormInstance>()
- const AdvertiserList = ref<AdvertiserItem[]>()
- const options = ref<AsSpaceItem[]>([])
- const tableSchedulingData = ref<TimeIntervalList>([])
- const typeOptions = [
- {
- value: 1,
- label: '轮播',
- },
- {
- value: 2,
- label: '交替',
- },
- {
- value: 3,
- label: '单素材投放',
- },
- ]
- const tableData = ref<OriginalityList>([])
- const siteList = ref<SiteList>([])
- const rules = {
- creativeName: [
- {
- required: true,
- message: '请输入创意名称',
- trigger: 'blur',
- },
- ],
- advertiserId: [
- {
- required: true,
- message: '请输选择广告主',
- trigger: 'change',
- },
- ],
- dates: [
- {
- required: true,
- message: '请输选择广告主',
- trigger: 'change',
- },
- ],
- mediaIds: [
- {
- required: true,
- message: '请输选择站点',
- trigger: 'change',
- },
- ],
- showType: [
- {
- required: true,
- message: '请输选择投放形式',
- trigger: 'change',
- },
- ],
- intervalType: [
- {
- required: true,
- message: '请输选择广告位排期',
- trigger: 'change',
- },
- ],
- slot: [
- {
- required: true,
- message: '请输选择广告位',
- trigger: 'change',
- },
- ],
- }
- // 获取站点信息
- getSiteList().then((res) => {
- siteList.value = res.data
- })
- // 广告主列表
- getAdvertiserList({
- pageNum: 1,
- pageSize: 999999,
- }).then(({ data }) => {
- AdvertiserList.value = data && data.records && data.records.length ? data.records : []
- })
- // 获取广告位
- const getAs = () => {
- const data = form.value
- let timeInterval = ''
- for (let i = 0; i < tableSchedulingData.value.length; i++) {
- const v = tableSchedulingData.value[i]
- for (let i = 0; i < 24; i++) {
- timeInterval += v[i] ? '1' : '0'
- }
- }
- getAsList({
- mediaIds: data.mediaIds ? data.mediaIds : [],
- startDate: data.dates ? data.dates[0] : '',
- endDate: data.dates ? data.dates[1] : '',
- intervalType: data.intervalType ? data.intervalType : undefined,
- creativeId: data.creativeId,
- timeInterval,
- }).then(({ data }) => {
- options.value = data
- })
- }
- const changeIntervalType = (val: number) => {
- if (val === 2) return
- tableSchedulingData.value = new Array(7).fill(new Array(24).fill(true))
- getAs()
- }
- const deleteOriginalityFun = (id: number) => {
- deleteOriginality(id).then(() => {
- getOriginality()
- })
- }
- const changePage = (val: number) => {
- page.value.pageNum = val
- getOriginality()
- }
- const selectAll = (val: boolean, item: TimeInterval, index: number) => {
- const v: TimeInterval = tableSchedulingData.value[index]
- for (let i = 0; i < 24; i++) {
- v[i] = val
- }
- getAs()
- }
- const select = (val: boolean, item: TimeInterval, index: number) => {
- const v: TimeInterval = tableSchedulingData.value[index]
- let all = true
- for (let i = 0; i < 24; i++) {
- const iV = v[i] ? true : false
- all = all && iV
- if (!all) break
- }
- if (all !== v.selectAll) v.selectAll = all
- getAs()
- }
- const creatEditPlan = async (data?: OriginalityItem) => {
- const date_ = formatDate(new Date().getTime())
- let D: OriginalityItem = {
- intervalType: 1,
- dates: [
- date_.fmtYear + '-' + date_.fmtMonth + '-' + date_.fmtDay,
- date_.fmtYear + '-' + date_.fmtMonth + '-' + date_.fmtDay,
- ],
- timeInterval:
- '111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111',
- }
- if (data != undefined) {
- const loading = ElLoading.service({
- lock: true,
- text: '加载中',
- background: 'rgba(0, 0, 0, 0.7)',
- })
- try {
- const res = await getOriginalityDetail(Number(data.creativeId))
- D = res.data || {}
- loading.close()
- const slot = D.slotsList ? D.slotsList.map((v) => v.slotId) : D.slotIds ? D.slotIds : []
- form.value = {
- ...D,
- slot,
- showIntervalTime: 1,
- dates: [D.startDate ? D.startDate : '', D.endDate ? D.endDate : ''],
- mediaIds:
- D.mediaList && typeof D.mediaList == 'object'
- ? D.mediaList.map((v) => (typeof v !== 'number' ? v.mediaId : -1))
- : [],
- }
- } catch (err) {
- console.error(err)
- loading.close()
- form.value = {
- ...D,
- }
- }
- } else {
- form.value = {
- ...D,
- showIntervalTime: 1,
- showType: 3,
- }
- if (typeof siteList.value[0].mediaId === 'number')
- form.value.mediaIds = [siteList.value[0].mediaId]
- }
- const weeks: string[] = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
- const scheduling: TimeIntervalList = []
- for (let i = 0; i < 7; i++) {
- const times = (D.timeInterval || '').slice(i * 24, i * 24 + 24).split('')
- const p: TimeInterval = {
- selectAll: true,
- weekName: weeks[i],
- }
- for (let i = 0; i < 24; i++) {
- p[i] = times[i] === '1' ? true : false
- if (!p[i]) p.selectAll = false
- }
- scheduling.push(p)
- }
- tableSchedulingData.value = scheduling
- dialogVisible.value = !dialogVisible.value
- getAs()
- }
- const getOriginality = () => {
- getOriginalityList(page.value).then((res) => {
- const data = res.data || {}
- page.value.total = data.total
- tableData.value = data.records
- })
- }
- // 创建或更新创意
- const createOrUpdate = (formEl: FormInstance | undefined) => {
- if (!formEl) return
- formEl.validate((valid) => {
- if (valid) {
- const Func = form.value.creativeId ? updateOriginality : createOriginality
- let timeInterval = ''
- for (let i = 0; i < tableSchedulingData.value.length; i++) {
- const v = tableSchedulingData.value[i]
- for (let i = 0; i < 24; i++) {
- timeInterval += v[i] ? '1' : '0'
- }
- }
- const p: OriginalityItem = {
- creativeId: form.value.creativeId,
- advertiserId: form.value.advertiserId,
- creativeName: form.value.creativeName,
- intervalType: form.value.intervalType,
- timeInterval,
- startDate: form.value.dates ? form.value.dates[0] : '',
- endDate: form.value.dates ? form.value.dates[1] : '',
- showType: form.value.showType,
- mediaIds: form.value.mediaIds,
- slotIds: form.value.slot,
- showIntervalTime: form.value.showIntervalTime || 1,
- }
- Func(p).then(() => {
- ElMessage.success(form.value.creativeId ? '更新成功' : '创建成功')
- dialogVisible.value = false
- getOriginality()
- })
- }
- })
- }
- const changeStatus = (id: number, status: number, text: string) => {
- updateOriginalityStatus({ id, status }).then(() => {
- ElMessage.success(text)
- getOriginality()
- })
- }
- const linkSourceMaterial = (id: string | number, show = false) => {
- // 跳转到相关素材
- router.push('/authorized/sourceMaterial?creativeId=' + id + '&show=' + show)
- }
- const publishAsTreeFunc = (id: number) => {
- onlineOriginality(id).then(() => {
- ElMessage({
- message: '发布成功',
- type: 'success',
- })
- getOriginality()
- })
- }
- getOriginality()
- </script>
- <style></style>
|