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
1ef1a1fa
Commit
1ef1a1fa
authored
Mar 04, 2025
by
lijin
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
增加计划投放任务管理
parent
2f7301db
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
573 additions
and
0 deletions
+573
-0
campaignTask.js
src/api/campaignTask.js
+39
-0
CampaignTemplateSelector.vue
src/components/GroupSelectors/CampaignTemplateSelector.vue
+63
-0
index.js
src/router/index.js
+7
-0
CampaignTaskManage.vue
src/views/campaignTask/CampaignTaskManage.vue
+453
-0
Layout.vue
src/views/layout/Layout.vue
+11
-0
No files found.
src/api/campaignTask.js
0 → 100644
View file @
1ef1a1fa
import
request
from
'@/utils/request'
export
function
getCampaignTaskList
(
params
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
'/campaign-tasks'
,
method
:
'get'
,
params
})
}
export
function
getCampaignTaskById
(
id
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
`/campaign-tasks/
${
id
}
`
,
method
:
'get'
})
}
export
function
createCampaignTask
(
data
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
'/campaign-tasks'
,
method
:
'post'
,
data
})
}
export
function
updateCampaignTask
(
data
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
'/campaign-tasks'
,
method
:
'put'
,
data
})
}
export
function
deleteCampaignTask
(
id
)
{
return
request
({
url
:
process
.
env
.
PUTIN_API
+
`/campaign-tasks/
${
id
}
`
,
method
:
'delete'
})
}
src/components/GroupSelectors/CampaignTemplateSelector.vue
0 → 100644
View file @
1ef1a1fa
<
template
>
<el-select
v-model=
"selectedValues"
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
:
'CampaignTemplateSelector'
,
props
:
{
value
:
{
type
:
[
Number
,
String
,
null
],
default
:
null
}
},
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
+
'/campaign-templates'
)
if
(
response
.
data
&&
response
.
data
.
result
&&
response
.
data
.
result
.
data
)
{
this
.
options
=
response
.
data
.
result
.
data
.
value
||
[]
}
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch campaign templates:'
,
error
)
}
},
handleChange
(
values
)
{
this
.
$emit
(
'input'
,
values
)
this
.
$emit
(
'change'
,
values
)
}
}
}
</
script
>
src/router/index.js
View file @
1ef1a1fa
...
@@ -70,6 +70,13 @@ export const constantRouterMap = [
...
@@ -70,6 +70,13 @@ export const constantRouterMap = [
meta
:
{
title
:
"创意投放"
,
icon
:
"chart"
}
meta
:
{
title
:
"创意投放"
,
icon
:
"chart"
}
},
},
{
path
:
'/intelligentDelivery/campaign-task'
,
name
:
"intelligentDelivery.campaign-task"
,
component
:
()
=>
import
(
'@/views/campaignTask/CampaignTaskManage'
),
meta
:
{
title
:
'计划投放'
}
},
{
{
path
:
'/intelligentDelivery/campaign-template'
,
path
:
'/intelligentDelivery/campaign-template'
,
name
:
"intelligentDelivery.campaign-template"
,
name
:
"intelligentDelivery.campaign-template"
,
...
...
src/views/campaignTask/CampaignTaskManage.vue
0 → 100644
View file @
1ef1a1fa
<
template
>
<div
class=
"campaign-task-container"
>
<!-- Filter section -->
<div
class=
"filter-section"
>
<el-form
:inline=
"true"
:model=
"condition"
class=
"filter-form"
>
<el-form-item
label=
"计划模板"
>
<campaign-template-selector
v-model=
"condition.campaignTemplateId"
@
change=
"handleTemplateChange"
/>
</el-form-item>
<el-form-item
label=
"状态"
>
<el-select
v-model=
"condition.status"
placeholder=
"请选择状态"
clearable
@
change=
"handleStatusChange"
>
<el-option
label=
"未执行"
:value=
"1"
></el-option>
<el-option
label=
"执行中"
:value=
"2"
></el-option>
<el-option
label=
"执行成功"
:value=
"3"
></el-option>
<el-option
label=
"执行失败"
:value=
"4"
></el-option>
</el-select>
</el-form-item>
<el-form-item
label=
"日期范围"
>
<el-date-picker
v-model=
"dateRange"
type=
"daterange"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
value-format=
"yyyy-MM-dd"
@
change=
"handleDateChange"
>
</el-date-picker>
</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=
"campaignTemplateId"
label=
"计划模板"
width=
"250"
>
<template
slot-scope=
"scope"
>
{{
getTemplateName
(
scope
.
row
.
campaignTemplateId
)
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"status"
label=
"状态"
width=
"120"
>
<
template
slot-scope=
"scope"
>
<el-tag
:type=
"getStatusType(scope.row.status)"
>
{{
getStatusText
(
scope
.
row
.
status
)
}}
</el-tag>
</
template
>
</el-table-column>
<el-table-column
prop=
"start_time"
label=
"开始时间"
width=
"180"
>
<
template
slot-scope=
"scope"
>
{{
scope
.
row
.
start_time
}}
</
template
>
</el-table-column>
<el-table-column
prop=
"finish_time"
label=
"结束时间"
width=
"180"
>
<
template
slot-scope=
"scope"
>
{{
scope
.
row
.
finish_time
}}
</
template
>
</el-table-column>
<el-table-column
label=
"执行时间"
width=
"150"
>
<
template
slot-scope=
"scope"
>
{{
calculateDuration
(
scope
.
row
)
}}
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
>
<
template
slot-scope=
"scope"
>
<el-button
size=
"mini"
type=
"primary"
@
click=
"handleEdit(scope.row)"
>
编辑
</el-button>
<el-button
size=
"mini"
type=
"info"
@
click=
"handleDetail(scope.row)"
>
详情
</el-button>
<el-button
v-if=
"scope.row.status === 1"
size=
"mini"
type=
"success"
@
click=
"handleStart(scope.row)"
>
开始
</el-button>
<el-button
v-if=
"scope.row.status === 4"
size=
"mini"
type=
"warning"
@
click=
"handleRetry(scope.row)"
>
重试
</el-button>
</
template
>
</el-table-column>
</el-table>
<div
class=
"pagination-container"
>
<el-pagination
@
size-change=
"handleSizeChange"
@
current-change=
"handleCurrentChange"
:current-page=
"currentPage"
:page-sizes=
"[10, 20, 50, 100]"
:page-size=
"pageSize"
:total=
"total"
layout=
"total, prev, pager, next, sizes"
>
</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=
"campaignTemplateId"
>
<campaign-template-selector
v-model=
"form.campaignTemplateId"
/>
</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
CampaignTemplateSelector
from
'@/components/GroupSelectors/CampaignTemplateSelector'
import
{
getCampaignTaskList
,
createCampaignTask
,
updateCampaignTask
}
from
'@/api/campaignTask'
import
axios
from
'axios'
import
dayjs
from
'dayjs'
import
duration
from
'dayjs/plugin/duration'
dayjs
.
extend
(
duration
)
export
default
{
name
:
'CampaignTaskManage'
,
components
:
{
CampaignTemplateSelector
},
data
()
{
const
end
=
dayjs
()
const
start
=
end
.
subtract
(
7
,
'day'
)
return
{
loading
:
false
,
condition
:
{
templateId
:
null
,
status
:
null
,
},
dateRange
:
[
start
.
format
(
'YYYY-MM-DD'
),
end
.
format
(
'YYYY-MM-DD'
)],
tableData
:
[],
currentPage
:
1
,
pageSize
:
10
,
total
:
0
,
dialogVisible
:
false
,
dialogTitle
:
''
,
form
:
{
campaignTemplateId
:
null
},
rules
:
{
campaignTemplateId
:
[
{
required
:
true
,
message
:
'请选择计划模板'
,
trigger
:
'change'
}
]
},
templateMap
:
new
Map
()
}
},
created
()
{
this
.
fetchTemplates
()
this
.
fetchData
()
},
methods
:
{
async
fetchData
()
{
this
.
loading
=
true
try
{
const
[
startDate
,
endDate
]
=
this
.
dateRange
||
[]
const
response
=
await
getCampaignTaskList
({
page
:
this
.
currentPage
,
size
:
this
.
pageSize
,
...
this
.
condition
,
startDate
,
endDate
})
if
(
response
.
status
===
200
)
{
this
.
tableData
=
response
.
result
.
data
.
value
this
.
total
=
response
.
result
.
count
}
else
{
this
.
$message
.
error
(
response
.
msg
||
'获取数据失败'
)
}
}
catch
(
error
)
{
console
.
error
(
'获取数据失败:'
,
error
)
this
.
$message
.
error
(
'获取数据失败'
)
}
this
.
loading
=
false
},
getStatusText
(
status
)
{
const
statusMap
=
{
1
:
'未执行'
,
2
:
'执行中'
,
3
:
'执行成功'
,
4
:
'执行失败'
}
return
statusMap
[
status
]
||
status
},
getStatusType
(
status
)
{
const
typeMap
=
{
1
:
'info'
,
2
:
'warning'
,
3
:
'success'
,
4
:
'danger'
}
return
typeMap
[
status
]
||
''
},
calculateDuration
(
row
)
{
const
startTime
=
dayjs
(
row
.
start_time
)
const
endTime
=
row
.
finish_time
?
dayjs
(
row
.
finish_time
)
:
dayjs
()
const
diff
=
endTime
.
diff
(
startTime
)
const
duration
=
dayjs
.
duration
(
diff
)
if
(
duration
.
asHours
()
>=
1
)
{
return
Math
.
floor
(
duration
.
asHours
())
+
'小时'
}
else
if
(
duration
.
asMinutes
()
>=
1
)
{
return
Math
.
floor
(
duration
.
asMinutes
())
+
'分钟'
}
else
{
return
Math
.
floor
(
duration
.
asSeconds
())
+
'秒'
}
},
async
fetchTemplates
()
{
try
{
const
response
=
await
axios
.
get
(
process
.
env
.
PUTIN_API
+
'/campaign-templates'
)
if
(
response
.
data
&&
response
.
data
.
result
&&
response
.
data
.
result
.
data
)
{
const
templates
=
response
.
data
.
result
.
data
.
value
||
[]
this
.
templateMap
=
new
Map
(
templates
.
map
(
t
=>
[
t
.
id
,
t
.
name
]))
}
}
catch
(
error
)
{
console
.
error
(
'Failed to fetch templates:'
,
error
)
}
},
getTemplateName
(
id
)
{
return
this
.
templateMap
.
get
(
id
)
||
id
},
handleTemplateChange
()
{
this
.
fetchData
()
},
handleStatusChange
()
{
this
.
fetchData
()
},
handleDateChange
()
{
this
.
fetchData
()
},
handleSizeChange
(
val
)
{
this
.
pageSize
=
val
this
.
currentPage
=
1
this
.
fetchData
()
},
handleCurrentChange
(
val
)
{
this
.
currentPage
=
val
this
.
fetchData
()
},
showAddDialog
()
{
this
.
dialogTitle
=
'创建任务'
this
.
form
=
{
campaignTemplateId
:
null
}
this
.
dialogVisible
=
true
},
handleEdit
(
row
)
{
this
.
dialogTitle
=
'编辑任务'
this
.
form
=
{
...
row
}
this
.
dialogVisible
=
true
},
handleDetail
(
row
)
{
// TODO: 实现详情查看功能
console
.
log
(
'查看详情:'
,
row
)
},
async
handleStart
(
row
)
{
try
{
const
response
=
await
axios
.
post
(
process
.
env
.
PUTIN_API
+
`/campaign-tasks/start?campaignTaskId=
${
row
.
id
}
`
)
if
(
response
.
status
==
200
&&
response
.
data
&&
response
.
data
.
result
&&
response
.
data
.
result
.
data
)
{
this
.
$message
.
success
(
'任务开始成功'
)
}
}
catch
(
error
)
{
console
.
error
(
'Failed to start task:'
,
error
)
this
.
$message
.
success
(
'任务开始失败:'
+
error
.
message
)
}
},
handleRetry
(
row
)
{
// TODO: 实现重试功能
console
.
log
(
'重试任务:'
,
row
)
},
async
submitForm
()
{
this
.
$refs
.
form
.
validate
(
async
(
valid
)
=>
{
if
(
valid
)
{
try
{
let
response
if
(
this
.
form
.
id
)
{
response
=
await
updateCampaignTask
(
this
.
form
)
}
else
{
response
=
await
createCampaignTask
(
this
.
form
)
}
if
(
response
.
status
===
200
)
{
this
.
$message
.
success
(
this
.
form
.
id
?
'更新成功'
:
'创建成功'
)
this
.
dialogVisible
=
false
this
.
fetchData
()
}
else
{
this
.
$message
.
error
(
response
.
msg
||
(
this
.
form
.
id
?
'更新失败'
:
'创建失败'
))
}
}
catch
(
error
)
{
console
.
error
(
this
.
form
.
id
?
'更新失败:'
:
'创建失败:'
,
error
)
this
.
$message
.
error
(
this
.
form
.
id
?
'更新失败'
:
'创建失败'
)
}
}
})
}
}
}
</
script
>
<
style
scoped
>
.campaign-task-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
;
}
.el-tag
{
margin-right
:
5px
;
margin-bottom
:
5px
;
}
.el-table--enable-row-hover
.el-table__body
tr
:hover
>
td
{
background-color
:
#f5f7fa
;
}
.el-button--primary
{
background-color
:
#1890ff
;
border-color
:
#1890ff
;
}
.el-button--primary
:hover
,
.el-button--primary
:focus
{
background-color
:
#40a9ff
;
border-color
:
#40a9ff
;
}
.el-link
{
color
:
#1890ff
;
}
.el-link
:hover
{
color
:
#40a9ff
;
}
.el-select
.el-input__inner
,
.el-input__inner
{
border-radius
:
2px
;
}
.pagination-container
{
margin-top
:
20px
;
display
:
flex
;
justify-content
:
flex-end
;
padding
:
10px
0
;
}
.el-pagination
{
font-weight
:
normal
;
}
.el-pagination
.el-select
.el-input
{
width
:
110px
;
}
.el-pagination
.el-select
.el-input__inner
{
padding-right
:
25px
;
}
.el-pagination
.btn-prev
,
.el-pagination
.btn-next
{
background
:
transparent
;
}
.el-pagination
.el-pager
li
{
background
:
transparent
;
border
:
none
;
}
.el-pagination
.el-pager
li
.active
{
color
:
#1890ff
;
background-color
:
#e6f7ff
;
border-radius
:
2px
;
}
.el-pagination__total
{
margin-right
:
10px
;
}
.el-pagination__sizes
{
margin-left
:
10px
;
}
</
style
>
src/views/layout/Layout.vue
View file @
1ef1a1fa
...
@@ -19,9 +19,20 @@
...
@@ -19,9 +19,20 @@
<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-task"
>
计划投放
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/campaign-template"
>
计划模板
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/campaign-template"
>
计划模板
</el-menu-item>
</el-submenu>
</el-submenu>
<!-- 带子菜单的导航项 -->
<el-submenu
index=
"4"
>
<
template
slot=
"title"
>
资产管理
</
template
>
<el-menu-item
index=
"/intelligentDelivery/campaign-template"
>
产品组
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/createDelivery"
>
地域组
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/createDelivery"
>
素材组
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/createDelivery"
>
标题组
</el-menu-item>
<el-menu-item
index=
"/intelligentDelivery/createDelivery"
>
描述组
</el-menu-item>
</el-submenu>
<el-submenu
index=
"3"
>
<el-submenu
index=
"3"
>
<
template
slot=
"title"
>
工具
</
template
>
<
template
slot=
"title"
>
工具
</
template
>
<el-menu-item
index=
"/assetManagement/googleOauthYoutube"
>
Youtube账号管理
</el-menu-item>
<el-menu-item
index=
"/assetManagement/googleOauthYoutube"
>
Youtube账号管理
</el-menu-item>
...
...
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