Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
S
SuperMan
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
罗超
SuperMan
Commits
c61dfa23
Commit
c61dfa23
authored
Jul 08, 2025
by
罗超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
b7b69832
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
442 additions
and
3 deletions
+442
-3
RequirementDetail.vue
src/pages/requirements/components/RequirementDetail.vue
+135
-3
TdTemplateDialog.vue
src/pages/requirements/components/TdTemplateDialog.vue
+299
-0
itinerary.js
src/services/itinerary.js
+8
-0
No files found.
src/pages/requirements/components/RequirementDetail.vue
View file @
c61dfa23
...
...
@@ -46,11 +46,39 @@
<el-table-column
prop=
"title"
label=
"标题"
></el-table-column>
<el-table-column
prop=
"recommendReason"
label=
"推荐理由"
width=
"200"
></el-table-column>
<el-table-column
prop=
"creationTime"
label=
"创建时间"
width=
"180"
></el-table-column>
<el-table-column
label=
"操作"
width=
"200"
>
<el-table-column
label=
"TD行程"
width=
"100"
>
<template
slot-scope=
"scope"
>
<span
v-if=
"scope.row.tdId == 0"
style=
"color: #f56c6c;"
>
未创建
</span>
<span
v-else
class=
"td-created"
@
click=
"previewTD(scope.row)"
style=
"cursor:pointer;"
>
已创建
</span>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
width=
"250"
>
<
template
slot-scope=
"scope"
>
<el-button
type=
"text"
size=
"small"
@
click=
"handleEdit(scope.row)"
>
修改
</el-button>
<el-button
type=
"text"
size=
"small"
style=
"color:#f56c6c;margin-right: 10px;"
@
click=
"handleDelete(scope.row)"
>
删除
</el-button>
<el-button
type=
"text"
size=
"small"
@
click=
"openPublishDialog(scope.row)"
>
发布行程
</el-button>
<template
v-if=
"scope.row.tdId == 0"
>
<el-button
type=
"text"
size=
"small"
style=
"margin-left:8px;"
@
click=
"openTdDialog(scope.row)"
>
创建TD
</el-button>
</
template
>
<
template
v-else
>
<el-dropdown
style=
"margin-left:8px;"
@
command=
"cmd => handleTdDropdown(cmd, scope.row)"
>
<el-button
type=
"text"
size=
"small"
>
TD操作
<i
class=
"el-icon-arrow-down el-icon--right"
></i></el-button>
<el-dropdown-menu
slot=
"dropdown"
>
<el-dropdown-item
command=
"change"
>
更换模版
</el-dropdown-item>
<!--
<el-dropdown-item
command=
"delete"
>
删除行程
</el-dropdown-item>
-->
<el-dropdown-item
command=
"edit"
>
编辑行程
</el-dropdown-item>
<el-dropdown-item
command=
"view"
>
查看行程
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</
template
>
</template>
</el-table-column>
</el-table>
...
...
@@ -116,6 +144,12 @@
</el-input>
<div
style=
"height: 30px;"
></div>
</el-dialog>
<TdTemplateDialog
:visible=
"tdDialogVisible"
:isEdit=
"tdDialogRow && tdDialogRow.tdId > 0"
@
close=
"tdDialogVisible=false"
@
confirm=
"onTdTemplateConfirm"
/>
</el-drawer>
</template>
...
...
@@ -124,11 +158,13 @@ import { requirementService } from '@/services/requirement';
import
{
itineraryService
}
from
'@/services/itinerary'
;
import
InfoCard
from
'./InfoCard.vue'
;
import
QRCode
from
'qrcode'
import
TdTemplateDialog
from
'./TdTemplateDialog.vue'
;
export
default
{
name
:
'RequirementDetail'
,
components
:
{
InfoCard
InfoCard
,
TdTemplateDialog
},
props
:
{
value
:
{
...
...
@@ -158,7 +194,9 @@ export default {
],
currentPublishOption
:
'wechatH5'
,
qrcodeUrl
:
''
,
createQrcode
:
false
createQrcode
:
false
,
tdDialogVisible
:
false
,
tdDialogRow
:
null
}
},
computed
:
{
...
...
@@ -393,6 +431,88 @@ export default {
'Closed'
:
'danger'
// 已关闭
};
return
typeMap
[
state
]
||
'info'
;
},
previewTD
(
row
)
{
// 先请求接口获取uid,再拼接PPT预览链接
if
(
row
.
tdId
>
0
)
{
this
.
apipost
&&
this
.
apipost
(
"travel_temp_token"
,
{},
res
=>
{
if
(
res
.
data
&&
res
.
data
.
resultCode
==
1
)
{
let
href
=
this
.
domainManager
().
PptUrl
;
const
pageUrl
=
`/play/
${
row
.
tdId
}
/0/2`
let
url
=
`
${
href
}
/autoLogin?uid=
${
res
.
data
.
data
}
&model=1001&redict=
${
encodeURIComponent
(
pageUrl
)}
`
;
window
.
open
(
url
,
'_blank'
);
}
else
{
this
.
$message
.
error
(
'获取TD行程token失败'
);
}
},
err
=>
{
this
.
$message
.
error
(
'获取TD行程token失败'
);
}
);
}
},
editTD
(
row
)
{
// 先请求接口获取uid,再拼接PPT预览链接
if
(
row
.
tdId
>
0
)
{
this
.
apipost
&&
this
.
apipost
(
"travel_temp_token"
,
{},
res
=>
{
if
(
res
.
data
&&
res
.
data
.
resultCode
==
1
)
{
let
href
=
this
.
domainManager
().
PptUrl
;
const
pageUrl
=
`/editor/
${
row
.
tdId
}
/1/1/0/e/1/c/1`
let
url
=
`
${
href
}
/autoLogin?uid=
${
res
.
data
.
data
}
&model=1001&redict=
${
encodeURIComponent
(
pageUrl
)}
`
;
window
.
open
(
url
,
'_blank'
);
}
else
{
this
.
$message
.
error
(
'获取TD行程token失败'
);
}
},
err
=>
{
this
.
$message
.
error
(
'获取TD行程token失败'
);
}
);
}
},
openTdDialog
(
row
)
{
this
.
tdDialogRow
=
row
;
this
.
tdDialogVisible
=
true
;
},
async
onTdTemplateConfirm
(
tempId
)
{
if
(
!
this
.
tdDialogRow
)
return
;
const
loading
=
this
.
$loading
({
lock
:
true
,
text
:
'正在为你创建TD行程,请稍等'
,
spinner
:
'el-icon-loading'
,
background
:
'rgba(0, 0, 0, 0.7)'
});
try
{
await
itineraryService
.
setTravelTemplateAsync
(
this
.
tdDialogRow
.
id
,
tempId
);
this
.
$message
.
success
(
'TD行程创建成功'
);
this
.
tdDialogVisible
=
false
;
this
.
getDetail
&&
this
.
getDetail
();
}
catch
(
e
)
{
this
.
$message
.
error
(
'TD行程创建失败'
);
}
finally
{
loading
.
close
();
}
},
handleTdDropdown
(
cmd
,
row
)
{
if
(
cmd
===
'change'
)
{
this
.
$confirm
(
'此操作将会解除现有的关联设计,重新创建新设计是否执行?'
,
'提示'
,
{
type
:
'warning'
}).
then
(()
=>
{
this
.
openTdDialog
(
row
);
});
}
else
if
(
cmd
===
'delete'
)
{
// 空方法
}
else
if
(
cmd
===
'edit'
)
{
// 空方法
this
.
editTD
(
row
)
}
else
if
(
cmd
===
'view'
)
{
// 空方法
this
.
previewTD
(
row
)
}
}
},
activated
()
{
...
...
@@ -480,4 +600,16 @@ export default {
color
:
#333
;
font-weight
:
500
;
}
.td-created
{
display
:
inline-block
;
padding
:
2px
10px
;
border-radius
:
8px
;
background
:
#e6f7ff
;
color
:
#409EFF
;
font-weight
:
500
;
transition
:
background
0.2s
;
}
.td-created
:hover
{
background
:
#bae7ff
;
}
</
style
>
src/pages/requirements/components/TdTemplateDialog.vue
0 → 100644
View file @
c61dfa23
<
template
>
<div
class=
"td-template-dialog-mask"
v-if=
"visible"
>
<div
class=
"td-template-dialog"
>
<div
class=
"td-template-header"
>
<span>
{{
isEdit
?
'修改TD模版'
:
'创建TD模版'
}}
</span>
<span
class=
"td-template-close"
@
click=
"$emit('close')"
>
×
</span>
</div>
<div
class=
"td-template-filter"
>
<input
v-model=
"filterTitle"
placeholder=
"关键字"
class=
"td-template-input"
@
input=
"onFilterChange"
/>
<select
v-model=
"filterType"
class=
"td-template-select"
@
change=
"onFilterChange"
>
<option
value=
"0"
>
全部版型
</option>
<option
value=
"1"
>
横版
</option>
<option
value=
"2"
>
竖版
</option>
</select>
</div>
<!--
<div
class=
"td-template-list-title"
>
全部模版
</div>
-->
<div
class=
"td-template-content"
>
<div
class=
"td-template-masonry"
>
<div
v-for=
"item in sortedTemplates"
:key=
"item.TempId"
class=
"td-template-card"
:class=
"
{'vertical': item.TempType==2, 'selected': selectedId===item.TempId}" @click="selectTemplate(item)">
<img
:src=
"item.CoverImg"
:alt=
"item.Title"
loading=
"lazy"
/>
<!--
<div
class=
"td-template-title"
>
{{
item
.
Title
}}
</div>
-->
<!--
<div
class=
"td-template-type"
>
{{
item
.
TempType
==
1
?
'横版'
:
'竖版'
}}
</div>
-->
<div
v-if=
"item.isAiRecommend"
class=
"td-template-ai-tag"
>
AI推荐
</div>
</div>
</div>
</div>
<div
class=
"td-template-footer"
>
<button
class=
"td-template-btn"
:disabled=
"!selectedId"
@
click=
"onCreate"
>
创建
</button>
</div>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
'TdTemplateDialog'
,
props
:
{
visible
:
Boolean
,
isEdit
:
Boolean
},
data
()
{
return
{
filterTitle
:
''
,
filterType
:
'0'
,
templates
:
[],
sources
:[],
selectedId
:
null
}
},
computed
:
{
hasFilter
()
{
return
this
.
filterTitle
.
trim
()
||
this
.
filterType
!==
'0'
;
},
sortedTemplates
()
{
// AI推荐优先
return
[...
this
.
templates
].
sort
((
a
,
b
)
=>
(
b
.
isAiRecommend
?
1
:
0
)
-
(
a
.
isAiRecommend
?
1
:
0
));
}
},
watch
:
{
visible
(
val
)
{
if
(
val
)
{
this
.
loadTemplates
();
}
}
},
mounted
()
{
this
.
loadTemplates
()
},
methods
:
{
onFilterChange
()
{
let
temps
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
sources
))
if
(
this
.
filterTitle
&&
this
.
filterTitle
!=
''
)
temps
=
temps
.
filter
(
x
=>
x
.
Title
.
indexOf
(
this
.
filterTitle
)
!=-
1
)
if
(
this
.
filterType
>
0
){
temps
=
temps
.
filter
(
x
=>
x
.
TempType
==
this
.
filterType
)
}
this
.
templates
=
temps
},
loadTemplates
()
{
// API参数
const
msg
=
{
pageIndex
:
1
,
pageSize
:
1000
,
LineId
:
0
,
Title
:
this
.
filterTitle
,
TagJsonStr
:
''
,
CountryList
:
[],
SeasonList
:
[],
ColorList
:
[],
pageCount
:
1
,
TempType
:
Number
(
this
.
filterType
),
TemplateType
:
1
,
type
:
0
,
OrderByType
:
1
};
if
(
this
.
apipost
)
{
this
.
apipost
(
'triptemplate_GetTripTemplatePage'
,
msg
,
res
=>
{
console
.
log
(
res
)
if
(
res
.
data
.
resultCode
===
1
)
{
this
.
templates
=
res
.
data
.
data
.
pageData
||
[];
this
.
sources
=
res
.
data
.
data
.
pageData
||
[];
}
else
{
this
.
templates
=
[];
}
});
}
else
{
// mock
this
.
templates
=
[
{
TempId
:
1427
,
Title
:
'日本红叶狩'
,
CoverImg
:
'https://im.oytour.com/pptist/desgin/250704145047901_tpl_00.jpg'
,
TempType
:
1
,
isAiRecommend
:
true
},
{
TempId
:
1428
,
Title
:
'北海道雪景'
,
CoverImg
:
'https://im.oytour.com/pptist/desgin/250704145047901_tpl_01.jpg'
,
TempType
:
2
,
isAiRecommend
:
false
},
{
TempId
:
1429
,
Title
:
'东京樱花季'
,
CoverImg
:
'https://im.oytour.com/pptist/desgin/250704145047901_tpl_02.jpg'
,
TempType
:
1
,
isAiRecommend
:
true
}
];
return
;
}
},
selectTemplate
(
item
)
{
this
.
selectedId
=
item
.
TempId
;
},
onCreate
()
{
if
(
this
.
selectedId
)
{
this
.
$emit
(
'confirm'
,
this
.
selectedId
);
}
}
}
}
</
script
>
<
style
scoped
>
.td-template-dialog-mask
{
position
:
fixed
;
z-index
:
9999
;
left
:
0
;
top
:
0
;
right
:
0
;
bottom
:
0
;
background
:
rgba
(
0
,
0
,
0
,
0.35
);
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
.td-template-dialog
{
background
:
#fff
;
border-radius
:
16px
;
min-width
:
700px
;
max-width
:
900px
;
min-height
:
480px
;
box-shadow
:
0
8px
32px
rgba
(
0
,
0
,
0
,
0.18
);
padding
:
0
0
24px
0
;
position
:
relative
;
overflow
:
hidden
;
}
.td-template-header
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
font-size
:
20px
;
font-weight
:
bold
;
padding
:
20px
32px
10px
32px
;
border-bottom
:
1px
solid
#f0f0f0
;
}
.td-template-close
{
font-size
:
28px
;
cursor
:
pointer
;
color
:
#888
;
transition
:
color
0.2s
;
}
.td-template-close
:hover
{
color
:
#f56c6c
;
}
.td-template-filter
{
display
:
flex
;
gap
:
16px
;
padding
:
18px
32px
0
32px
;
align-items
:
center
;
}
.td-template-input
{
flex
:
1
;
padding
:
8px
12px
;
border
:
1px
solid
#e0e0e0
;
border-radius
:
6px
;
font-size
:
15px
;
}
.td-template-select
{
padding
:
8px
12px
;
border
:
1px
solid
#e0e0e0
;
border-radius
:
6px
;
font-size
:
15px
;
}
.td-template-list-title
{
font-size
:
16px
;
font-weight
:
500
;
margin
:
18px
32px
8px
32px
;
}
.td-template-content
{
height
:
70vh
;
overflow
:
hidden
;
overflow-y
:
auto
;
margin-top
:
18px
;
}
.td-template-masonry
{
column-count
:
3
;
column-gap
:
18px
;
margin
:
0
32px
;
min-height
:
180px
;
}
.td-template-card
{
break-inside
:
avoid
;
margin-bottom
:
18px
;
width
:
100%
;
background
:
#f7fafd
;
border-radius
:
10px
;
box-shadow
:
0
1px
4px
rgba
(
64
,
158
,
255
,
0.06
);
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
cursor
:
pointer
;
transition
:
box-shadow
0.2s
,
background
0.2s
,
border
0.2s
;
border
:
2px
solid
transparent
;
padding
:
10px
8px
10px
8px
;
position
:
relative
;
}
.td-template-card.selected
{
border
:
2px
solid
#409EFF
;
background
:
#e6f7ff
;
}
.td-template-card.vertical
{
min-height
:
260px
;
}
.td-template-card
img
{
width
:
100%
;
/* height: 110px; */
object-fit
:
cover
;
border-radius
:
6px
;
/* margin-bottom: 8px; */
background
:
#eee
;
}
.td-template-title
{
font-size
:
15px
;
font-weight
:
500
;
margin-bottom
:
4px
;
text-align
:
center
;
color
:
#333
;
}
.td-template-type
{
font-size
:
13px
;
color
:
#888
;
text-align
:
center
;
}
.td-template-ai-tag
{
position
:
absolute
;
top
:
8px
;
right
:
8px
;
background
:
linear-gradient
(
90deg
,
#1a1a1a
80%
,
#bfa14a
100%
);
color
:
#FFD700
;
font-size
:
13px
;
/* font-weight: bold; */
padding
:
2px
10px
;
border-radius
:
10px
10px
10px
0
;
box-shadow
:
0
2px
8px
rgba
(
0
,
0
,
0
,
0.08
);
letter-spacing
:
1px
;
z-index
:
2
;
}
.td-template-footer
{
padding
:
20px
32px
;
text-align
:
right
;
}
.td-template-btn
{
padding
:
10px
20px
;
background-color
:
#409EFF
;
color
:
#fff
;
border
:
none
;
border-radius
:
6px
;
cursor
:
pointer
;
transition
:
background-color
0.2s
;
}
.td-template-btn
:hover
{
background-color
:
#66b1ff
;
}
.td-template-btn
:disabled
{
background-color
:
#d3d3d3
;
cursor
:
not-allowed
;
}
</
style
>
src/services/itinerary.js
View file @
c61dfa23
...
...
@@ -62,5 +62,13 @@ export const itineraryService = {
*/
getItineraryDetail
:
(
id
)
=>
{
return
rwRequest
.
get
(
'/travel/'
+
id
);
},
/**
* 获取所有的模版
* @returns
*/
setTravelTemplateAsync
:(
id
,
tempId
)
=>
{
return
rwRequest
.
post
(
`/travel/
${
id
}
/td-asnyc/
${
tempId
}
`
);
}
};
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