Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Sign in / Register
Toggle navigation
Z
zxn-adputin
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lijin
zxn-adputin
Commits
12f14c4b
Commit
12f14c4b
authored
Mar 03, 2025
by
lijin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加计划模板管理页面
parent
15fa7902
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
875 additions
and
1 deletion
+875
-1
campaignTemplate.js
src/api/campaignTemplate.js
+38
-0
AppGroupSelector.vue
src/components/GroupSelectors/AppGroupSelector.vue
+62
-0
DescriptionGroupSelector.vue
src/components/GroupSelectors/DescriptionGroupSelector.vue
+62
-0
LocationGroupSelector.vue
src/components/GroupSelectors/LocationGroupSelector.vue
+62
-0
MaterialGroupSelector.vue
src/components/GroupSelectors/MaterialGroupSelector.vue
+62
-0
TitleGroupSelector.vue
src/components/GroupSelectors/TitleGroupSelector.vue
+62
-0
index.js
src/router/index.js
+9
-1
CampaignTemplateManage.vue
src/views/campaignTemplate/CampaignTemplateManage.vue
+517
-0
Layout.vue
src/views/layout/Layout.vue
+1
-0
No files found.
src/api/campaignTemplate.js
0 → 100644
View file @
12f14c4b
import
request
from
'@/utils/request'
export
function
getCampaignTemplateList
()
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
'/campaign-templates'
,
method
:
'get'
})
}
export
function
getCampaignTemplateById
(
id
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
`/campaign-templates/
${
id
}
`
,
method
:
'get'
})
}
export
function
createCampaignTemplate
(
data
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
'/campaign-templates'
,
method
:
'post'
,
data
})
}
export
function
updateCampaignTemplate
(
data
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
'/campaign-templates'
,
method
:
'put'
,
data
})
}
export
function
deleteCampaignTemplate
(
id
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
`/campaign-templates/
${
id
}
`
,
method
:
'delete'
})
}
src/components/GroupSelectors/AppGroupSelector.vue
0 → 100644
View file @
12f14c4b
<
template
>
<el-select
v-model=
"selectedValues"
multiple
filterable
clearable
placeholder=
"请选择应用组"
@
change=
"handleChange"
>
<el-option
v-for=
"item in options"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
script
>
import
axios
from
'axios'
export
default
{
name
:
'AppGroupSelector'
,
props
:
{
value
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
()
{
return
{
options
:
[],
selectedValues
:
[]
}
},
watch
:
{
value
:
{
handler
(
newVal
)
{
this
.
selectedValues
=
newVal
},
immediate
:
true
}
},
created
()
{
this
.
fetchOptions
()
},
methods
:
{
async
fetchOptions
()
{
try
{
const
response
=
await
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/app-groups'
)
this
.
options
=
response
.
data
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch app groups:'
,
error
)
}
},
handleChange
(
values
)
{
this
.
$emit
(
'input'
,
values
)
this
.
$emit
(
'change'
,
values
)
}
}
}
</
script
>
src/components/GroupSelectors/DescriptionGroupSelector.vue
0 → 100644
View file @
12f14c4b
<
template
>
<el-select
v-model=
"selectedValues"
multiple
filterable
clearable
placeholder=
"请选择描述组"
@
change=
"handleChange"
>
<el-option
v-for=
"item in options"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
script
>
import
axios
from
'axios'
export
default
{
name
:
'DescriptionGroupSelector'
,
props
:
{
value
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
()
{
return
{
options
:
[],
selectedValues
:
[]
}
},
watch
:
{
value
:
{
handler
(
newVal
)
{
this
.
selectedValues
=
newVal
},
immediate
:
true
}
},
created
()
{
this
.
fetchOptions
()
},
methods
:
{
async
fetchOptions
()
{
try
{
const
response
=
await
axios
.
get
(
'http://localhost:8567/description-groups'
)
this
.
options
=
response
.
data
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch description groups:'
,
error
)
}
},
handleChange
(
values
)
{
this
.
$emit
(
'input'
,
values
)
this
.
$emit
(
'change'
,
values
)
}
}
}
</
script
>
src/components/GroupSelectors/LocationGroupSelector.vue
0 → 100644
View file @
12f14c4b
<
template
>
<el-select
v-model=
"selectedValues"
multiple
filterable
clearable
placeholder=
"请选择地域组"
@
change=
"handleChange"
>
<el-option
v-for=
"item in options"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
script
>
import
axios
from
'axios'
export
default
{
name
:
'LocationGroupSelector'
,
props
:
{
value
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
()
{
return
{
options
:
[],
selectedValues
:
[]
}
},
watch
:
{
value
:
{
handler
(
newVal
)
{
this
.
selectedValues
=
newVal
},
immediate
:
true
}
},
created
()
{
this
.
fetchOptions
()
},
methods
:
{
async
fetchOptions
()
{
try
{
const
response
=
await
axios
.
get
(
'http://localhost:8567/location-groups'
)
this
.
options
=
response
.
data
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch location groups:'
,
error
)
}
},
handleChange
(
values
)
{
this
.
$emit
(
'input'
,
values
)
this
.
$emit
(
'change'
,
values
)
}
}
}
</
script
>
src/components/GroupSelectors/MaterialGroupSelector.vue
0 → 100644
View file @
12f14c4b
<
template
>
<el-select
v-model=
"selectedValues"
multiple
filterable
clearable
placeholder=
"请选择素材组"
@
change=
"handleChange"
>
<el-option
v-for=
"item in options"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
script
>
import
axios
from
'axios'
export
default
{
name
:
'MaterialGroupSelector'
,
props
:
{
value
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
()
{
return
{
options
:
[],
selectedValues
:
[]
}
},
watch
:
{
value
:
{
handler
(
newVal
)
{
this
.
selectedValues
=
newVal
},
immediate
:
true
}
},
created
()
{
this
.
fetchOptions
()
},
methods
:
{
async
fetchOptions
()
{
try
{
const
response
=
await
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/material-groups'
)
this
.
options
=
response
.
data
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch material groups:'
,
error
)
}
},
handleChange
(
values
)
{
this
.
$emit
(
'input'
,
values
)
this
.
$emit
(
'change'
,
values
)
}
}
}
</
script
>
src/components/GroupSelectors/TitleGroupSelector.vue
0 → 100644
View file @
12f14c4b
<
template
>
<el-select
v-model=
"selectedValues"
multiple
filterable
clearable
placeholder=
"请选择标题组"
@
change=
"handleChange"
>
<el-option
v-for=
"item in options"
:key=
"item.id"
:label=
"item.name"
:value=
"item.id"
/>
</el-select>
</
template
>
<
script
>
import
axios
from
'axios'
export
default
{
name
:
'TitleGroupSelector'
,
props
:
{
value
:
{
type
:
Array
,
default
:
()
=>
[]
}
},
data
()
{
return
{
options
:
[],
selectedValues
:
[]
}
},
watch
:
{
value
:
{
handler
(
newVal
)
{
this
.
selectedValues
=
newVal
},
immediate
:
true
}
},
created
()
{
this
.
fetchOptions
()
},
methods
:
{
async
fetchOptions
()
{
try
{
const
response
=
await
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/title-groups'
)
this
.
options
=
response
.
data
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch title groups:'
,
error
)
}
},
handleChange
(
values
)
{
this
.
$emit
(
'input'
,
values
)
this
.
$emit
(
'change'
,
values
)
}
}
}
</
script
>
src/router/index.js
View file @
12f14c4b
...
@@ -69,6 +69,13 @@ export const constantRouterMap = [
...
@@ -69,6 +69,13 @@ export const constantRouterMap = [
component
:
()
=>
import
(
"@/views/createDelivery"
),
component
:
()
=>
import
(
"@/views/createDelivery"
),
meta
:
{
title
:
"创意投放"
,
icon
:
"chart"
}
meta
:
{
title
:
"创意投放"
,
icon
:
"chart"
}
},
},
{
path
:
'/intelligentDelivery/campaign-template'
,
name
:
"intelligentDelivery.campaign-template"
,
component
:
()
=>
import
(
'@/views/campaignTemplate/CampaignTemplateManage'
),
meta
:
{
title
:
'计划模板管理'
}
}
]
]
},
},
{
{
...
@@ -102,7 +109,8 @@ export const constantRouterMap = [
...
@@ -102,7 +109,8 @@ export const constantRouterMap = [
name
:
"assetManagement.YoutubeVideoManage"
,
name
:
"assetManagement.YoutubeVideoManage"
,
component
:
()
=>
import
(
"@/views/uploadYoutube/YoutubeVideoManage"
),
component
:
()
=>
import
(
"@/views/uploadYoutube/YoutubeVideoManage"
),
meta
:
{
title
:
"Youtube视频管理"
,
icon
:
"chart"
}
meta
:
{
title
:
"Youtube视频管理"
,
icon
:
"chart"
}
}
},
]
]
},
},
...
...
src/views/campaignTemplate/CampaignTemplateManage.vue
0 → 100644
View file @
12f14c4b
<
template
>
<div
class=
"campaign-template-container"
>
<!-- Filter section -->
<div
class=
"filter-section"
>
<el-form
:inline=
"true"
:model=
"condition"
class=
"filter-form"
>
<el-form-item
label=
"模板名称"
>
<el-input
v-model=
"condition.name"
placeholder=
"请输入模板名称"
class=
"filter-input"
@
change=
"fetchData"
>
</el-input>
</el-form-item>
<el-form-item
label=
"应用组"
>
<app-group-selector
v-model=
"condition.appGroups"
@
change=
"handleAppGroupChange"
/>
</el-form-item>
<el-form-item
label=
"地域组"
>
<location-group-selector
v-model=
"condition.locationGroups"
@
change=
"handleLocationGroupChange"
/>
</el-form-item>
<el-form-item
label=
"素材组"
>
<material-group-selector
v-model=
"condition.materialGroups"
@
change=
"handleMaterialGroupChange"
/>
</el-form-item>
<el-form-item
label=
"标题组"
>
<title-group-selector
v-model=
"condition.titleGroups"
@
change=
"handleTitleGroupChange"
/>
</el-form-item>
<el-form-item
label=
"描述组"
>
<description-group-selector
v-model=
"condition.descriptionGroups"
@
change=
"handleDescriptionGroupChange"
/>
</el-form-item>
</el-form>
</div>
<el-divider></el-divider>
<!-- Table Header actions -->
<div
class=
"header-actions"
>
<el-button
type=
"primary"
@
click=
"showAddDialog"
>
新增模板
</el-button>
<div
class=
"header-right"
>
<el-button
icon=
"el-icon-refresh"
@
click=
"fetchData"
>
刷新
</el-button>
</div>
</div>
<!-- Main table -->
<el-table
:data=
"tableData"
border
style=
"width: 100%"
v-loading=
"loading"
>
<el-table-column
prop=
"id"
label=
"ID"
width=
"80"
></el-table-column>
<el-table-column
prop=
"name"
label=
"模板名称"
width=
"150"
></el-table-column>
<el-table-column
prop=
"daily_budget"
label=
"日预算"
width=
"120"
>
<template
slot-scope=
"scope"
>
{{
scope
.
row
.
daily_budget
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"target_roas"
label=
"目标考核ROAS"
width=
"150"
>
<
template
slot-scope=
"scope"
>
{{
scope
.
row
.
target_roas
}}
</
template
>
</el-table-column>
<el-table-column
label=
"应用组"
width=
"200"
>
<
template
slot-scope=
"scope"
>
<el-tag
v-for=
"group in JSON.parse(scope.row.app_groups || '[]')"
:key=
"group"
size=
"small"
style=
"margin: 2px"
>
{{
getAppGroupName
(
group
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"地域组"
width=
"200"
>
<
template
slot-scope=
"scope"
>
<el-tag
v-for=
"group in JSON.parse(scope.row.location_groups || '[]')"
:key=
"group"
size=
"small"
style=
"margin: 2px"
>
{{
getLocationGroupName
(
group
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"素材组"
width=
"200"
>
<
template
slot-scope=
"scope"
>
<el-tag
v-for=
"group in JSON.parse(scope.row.material_groups || '[]')"
:key=
"group"
size=
"small"
style=
"margin: 2px"
>
{{
getMaterialGroupName
(
group
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"标题组"
width=
"200"
>
<
template
slot-scope=
"scope"
>
<el-tag
v-for=
"group in JSON.parse(scope.row.title_groups || '[]')"
:key=
"group"
size=
"small"
style=
"margin: 2px"
>
{{
getTitleGroupName
(
group
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"描述组"
width=
"200"
>
<
template
slot-scope=
"scope"
>
<el-tag
v-for=
"group in JSON.parse(scope.row.description_groups || '[]')"
:key=
"group"
size=
"small"
style=
"margin: 2px"
>
{{
getDescriptionGroupName
(
group
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"150"
fixed=
"right"
>
<
template
slot-scope=
"scope"
>
<el-button
size=
"mini"
type=
"primary"
@
click=
"handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
size=
"mini"
type=
"danger"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- Pagination -->
<div
class=
"pagination-container"
>
<el-pagination
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
:current-page=
"currentPage"
:page-sizes=
"[10, 20, 50, 100]"
:page-size=
"pageSize"
layout=
"total, sizes, prev, pager, next, jumper"
:total=
"total"
>
</el-pagination>
</div>
<!-- Add/Edit Dialog -->
<el-dialog
:title=
"dialogTitle"
:visible
.
sync=
"dialogVisible"
width=
"50%"
>
<el-form
:model=
"form"
:rules=
"rules"
ref=
"form"
label-width=
"120px"
>
<el-form-item
label=
"模板名称"
prop=
"name"
>
<el-input
v-model=
"form.name"
></el-input>
</el-form-item>
<el-form-item
label=
"广告系列类型"
prop=
"campaign_type"
>
<el-select
v-model=
"form.campaign_type"
placeholder=
"请选择"
>
<el-option
label=
"应用安装"
:value=
"1"
></el-option>
<el-option
label=
"应用互动"
:value=
"2"
></el-option>
<el-option
label=
"应用预注册"
:value=
"3"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"移动应用平台"
prop=
"appStore"
>
<el-select
v-model=
"form.appStore"
placeholder=
"请选择"
>
<el-option
label=
"iOS"
:value=
"2"
></el-option>
<el-option
label=
"Android"
:value=
"3"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"日预算"
prop=
"daily_budget"
>
<el-input-number
v-model=
"form.daily_budget"
:min=
"0"
></el-input-number>
</el-form-item>
<el-form-item
label=
"转化目标"
prop=
"bidding_type"
>
<el-select
v-model=
"form.bidding_type"
placeholder=
"请选择"
>
<el-option
label=
"安装量"
:value=
"2"
></el-option>
<el-option
label=
"应用内操作次数"
:value=
"3"
></el-option>
<el-option
label=
"biddingStrategyGoalType"
:value=
"5"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"目标考核ROAS"
prop=
"target_roas"
>
<el-input-number
v-model=
"form.target_roas"
:min=
"0"
></el-input-number>
</el-form-item>
<el-form-item
label=
"应用组"
prop=
"app_groups"
>
<app-group-selector
v-model=
"form.app_groups"
/>
</el-form-item>
<el-form-item
label=
"地域组"
prop=
"location_groups"
>
<location-group-selector
v-model=
"form.location_groups"
/>
</el-form-item>
<el-form-item
label=
"素材组"
prop=
"material_groups"
>
<material-group-selector
v-model=
"form.material_groups"
/>
</el-form-item>
<el-form-item
label=
"标题组"
prop=
"title_groups"
>
<title-group-selector
v-model=
"form.title_groups"
/>
</el-form-item>
<el-form-item
label=
"描述组"
prop=
"description_groups"
>
<description-group-selector
v-model=
"form.description_groups"
/>
</el-form-item>
</el-form>
<div
slot=
"footer"
class=
"dialog-footer"
>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
<el-button
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
</div>
</el-dialog>
</div>
</template>
<
script
>
import
AppGroupSelector
from
'@/components/GroupSelectors/AppGroupSelector'
import
LocationGroupSelector
from
'@/components/GroupSelectors/LocationGroupSelector'
import
MaterialGroupSelector
from
'@/components/GroupSelectors/MaterialGroupSelector'
import
TitleGroupSelector
from
'@/components/GroupSelectors/TitleGroupSelector'
import
DescriptionGroupSelector
from
'@/components/GroupSelectors/DescriptionGroupSelector'
import
{
getCampaignTemplateList
,
createCampaignTemplate
,
updateCampaignTemplate
,
deleteCampaignTemplate
}
from
'@/api/campaignTemplate'
export
default
{
name
:
'CampaignTemplateManage'
,
components
:
{
AppGroupSelector
,
LocationGroupSelector
,
MaterialGroupSelector
,
TitleGroupSelector
,
DescriptionGroupSelector
},
data
()
{
return
{
condition
:
{
name
:
''
,
appGroups
:
[],
locationGroups
:
[],
materialGroups
:
[],
titleGroups
:
[],
descriptionGroups
:
[]
},
loading
:
false
,
tableData
:
[],
currentPage
:
1
,
pageSize
:
10
,
total
:
0
,
dialogVisible
:
false
,
dialogTitle
:
''
,
form
:
{
name
:
''
,
campaign_type
:
1
,
appStore
:
3
,
daily_budget
:
0
,
bidding_type
:
3
,
target_roas
:
0
,
app_groups
:
[],
location_groups
:
[],
material_groups
:
[],
title_groups
:
[],
description_groups
:
[]
},
rules
:
{
name
:
[
{
required
:
true
,
message
:
'请输入模板名称'
,
trigger
:
'blur'
}
],
campaign_type
:
[
{
required
:
true
,
message
:
'请选择广告系列类型'
,
trigger
:
'change'
}
],
appStore
:
[
{
required
:
true
,
message
:
'请选择移动应用平台'
,
trigger
:
'change'
}
],
daily_budget
:
[
{
required
:
true
,
message
:
'请输入日预算'
,
trigger
:
'blur'
}
],
bidding_type
:
[
{
required
:
true
,
message
:
'请选择转化目标'
,
trigger
:
'change'
}
]
},
groupNameMaps
:
{
app
:
new
Map
(),
location
:
new
Map
(),
material
:
new
Map
(),
title
:
new
Map
(),
description
:
new
Map
()
}
}
},
created
()
{
this
.
fetchData
()
this
.
fetchGroupNames
()
},
methods
:
{
async
fetchData
()
{
this
.
loading
=
true
try
{
const
response
=
await
getCampaignTemplateList
()
if
(
response
.
status
===
200
)
{
this
.
tableData
=
response
.
result
.
data
this
.
total
=
response
.
result
.
total
}
else
{
this
.
$message
.
error
(
response
.
msg
||
'获取数据失败'
)
}
}
catch
(
error
)
{
console
.
error
(
'获取数据失败:'
,
error
)
this
.
$message
.
error
(
'获取数据失败'
)
}
this
.
loading
=
false
},
async
fetchGroupNames
()
{
try
{
const
[
app
,
location
,
material
,
title
,
description
]
=
await
Promise
.
all
([
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/app-groups'
),
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/location-groups'
),
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/material-groups'
),
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/title-groups'
),
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/description-groups'
)
])
app
.
data
.
forEach
(
item
=>
this
.
groupNameMaps
.
app
.
set
(
item
.
id
,
item
.
name
))
location
.
data
.
forEach
(
item
=>
this
.
groupNameMaps
.
location
.
set
(
item
.
id
,
item
.
name
))
material
.
data
.
forEach
(
item
=>
this
.
groupNameMaps
.
material
.
set
(
item
.
id
,
item
.
name
))
title
.
data
.
forEach
(
item
=>
this
.
groupNameMaps
.
title
.
set
(
item
.
id
,
item
.
name
))
description
.
data
.
forEach
(
item
=>
this
.
groupNameMaps
.
description
.
set
(
item
.
id
,
item
.
name
))
}
catch
(
error
)
{
console
.
error
(
'获取组名称失败:'
,
error
)
}
},
getAppGroupName
(
id
)
{
return
this
.
groupNameMaps
.
app
.
get
(
id
)
||
id
},
getLocationGroupName
(
id
)
{
return
this
.
groupNameMaps
.
location
.
get
(
id
)
||
id
},
getMaterialGroupName
(
id
)
{
return
this
.
groupNameMaps
.
material
.
get
(
id
)
||
id
},
getTitleGroupName
(
id
)
{
return
this
.
groupNameMaps
.
title
.
get
(
id
)
||
id
},
getDescriptionGroupName
(
id
)
{
return
this
.
groupNameMaps
.
description
.
get
(
id
)
||
id
},
handleSizeChange
(
val
)
{
this
.
pageSize
=
val
this
.
currentPage
=
1
this
.
fetchData
()
},
handleCurrentChange
(
val
)
{
this
.
currentPage
=
val
this
.
fetchData
()
},
showAddDialog
()
{
this
.
dialogTitle
=
'新增模板'
this
.
form
=
{
name
:
''
,
campaign_type
:
1
,
appStore
:
3
,
daily_budget
:
0
,
bidding_type
:
3
,
target_roas
:
0
,
app_groups
:
[],
location_groups
:
[],
material_groups
:
[],
title_groups
:
[],
description_groups
:
[]
}
this
.
dialogVisible
=
true
},
handleEdit
(
row
)
{
this
.
dialogTitle
=
'编辑模板'
this
.
form
=
{
...
row
,
app_groups
:
JSON
.
parse
(
row
.
app_groups
||
'[]'
),
location_groups
:
JSON
.
parse
(
row
.
location_groups
||
'[]'
),
material_groups
:
JSON
.
parse
(
row
.
material_groups
||
'[]'
),
title_groups
:
JSON
.
parse
(
row
.
title_groups
||
'[]'
),
description_groups
:
JSON
.
parse
(
row
.
description_groups
||
'[]'
)
}
this
.
dialogVisible
=
true
},
async
handleDelete
(
row
)
{
try
{
await
this
.
$confirm
(
'确认删除该模板吗?'
,
'提示'
,
{
type
:
'warning'
})
const
response
=
await
deleteCampaignTemplate
(
row
.
id
)
if
(
response
.
status
===
200
)
{
this
.
$message
.
success
(
'删除成功'
)
this
.
fetchData
()
}
else
{
this
.
$message
.
error
(
response
.
msg
||
'删除失败'
)
}
}
catch
(
error
)
{
if
(
error
!==
'cancel'
)
{
console
.
error
(
'删除失败:'
,
error
)
this
.
$message
.
error
(
'删除失败'
)
}
}
},
async
submitForm
()
{
this
.
$refs
.
form
.
validate
(
async
(
valid
)
=>
{
if
(
valid
)
{
const
formData
=
{
...
this
.
form
,
app_groups
:
JSON
.
stringify
(
this
.
form
.
app_groups
),
location_groups
:
JSON
.
stringify
(
this
.
form
.
location_groups
),
material_groups
:
JSON
.
stringify
(
this
.
form
.
material_groups
),
title_groups
:
JSON
.
stringify
(
this
.
form
.
title_groups
),
description_groups
:
JSON
.
stringify
(
this
.
form
.
description_groups
)
}
try
{
let
response
if
(
formData
.
id
)
{
response
=
await
updateCampaignTemplate
(
formData
)
}
else
{
response
=
await
createCampaignTemplate
(
formData
)
}
if
(
response
.
status
===
200
)
{
this
.
$message
.
success
(
formData
.
id
?
'更新成功'
:
'创建成功'
)
this
.
dialogVisible
=
false
this
.
fetchData
()
}
else
{
this
.
$message
.
error
(
response
.
msg
||
(
formData
.
id
?
'更新失败'
:
'创建失败'
))
}
}
catch
(
error
)
{
console
.
error
(
formData
.
id
?
'更新失败:'
:
'创建失败:'
,
error
)
this
.
$message
.
error
(
formData
.
id
?
'更新失败'
:
'创建失败'
)
}
}
})
},
handleAppGroupChange
()
{
this
.
fetchData
()
},
handleLocationGroupChange
()
{
this
.
fetchData
()
},
handleMaterialGroupChange
()
{
this
.
fetchData
()
},
handleTitleGroupChange
()
{
this
.
fetchData
()
},
handleDescriptionGroupChange
()
{
this
.
fetchData
()
}
}
}
</
script
>
<
style
scoped
>
.campaign-template-container
{
padding
:
20px
;
}
.filter-section
{
background-color
:
#fff
;
padding
:
20px
;
border-radius
:
4px
;
}
.filter-form
{
display
:
flex
;
flex-wrap
:
wrap
;
}
.filter-input
{
width
:
200px
;
}
.header-actions
{
margin
:
20px
0
;
display
:
flex
;
justify-content
:
space-between
;
}
.header-right
{
display
:
flex
;
gap
:
10px
;
}
.pagination-container
{
margin-top
:
20px
;
display
:
flex
;
justify-content
:
center
;
}
.el-tag
{
margin-right
:
5px
;
margin-bottom
:
5px
;
}
</
style
>
src/views/layout/Layout.vue
View file @
12f14c4b
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
<el-submenu
index=
"2"
>
<el-submenu
index=
"2"
>
<template
slot=
"title"
>
推广管理
</
template
>
<template
slot=
"title"
>
推广管理
</
template
>
<el-menu-item
index=
"/intelligentDelivery/createDelivery"
>
创建计划
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/createDelivery"
>
创建计划
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/campaign-template"
>
计划模板
</el-menu-item>
</el-submenu>
</el-submenu>
<el-submenu
index=
"3"
>
<el-submenu
index=
"3"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment