Skip to content
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation
This project
Loading...
Sign in
李宁
/
Activity
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Settings
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit 528665ef
authored
Nov 13, 2025
by
李宁
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
1
1 parent
5abfbfa7
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
372 additions
and
53 deletions
zhiJianBusi/zjbPc/src/assets/js/api/interface/business/index.js
zhiJianBusi/zjbPc/src/router/index.js
zhiJianBusi/zjbPc/src/views/DashboardLayout.vue
zhiJianBusi/zjbPc/src/views/OpportunityDetail.vue
zhiJianBusi/zjbPc/src/views/OpportunityManagement.vue
zhiJianBusi/zjbPhone/.claude/settings.local.json
zhiJianBusi/zjbPhone/busiDetail.html
zhiJianBusi/zjbPhone/css/busiDetail.css
zhiJianBusi/zjbPhone/js/addBusi.js
zhiJianBusi/zjbPhone/js/busiDetail.js
zhiJianBusi/zjbPc/src/assets/js/api/interface/business/index.js
View file @
528665e
...
...
@@ -141,6 +141,16 @@ export function queryBusiCloseReansonList(data) {
}
/**
* 商机关闭原因:根据区域列表查询
*/
export
function
queryAreaCloseReansonList
(
data
)
{
return
request
({
url
:
'/compass/api/common/close-reason/page'
,
data
,
})
}
/**
* 商机关闭原因添加和更新
*/
export
function
busiCloseReasonUpdate
(
data
)
{
...
...
zhiJianBusi/zjbPc/src/router/index.js
View file @
528665e
...
...
@@ -29,7 +29,7 @@ const routes = [
component
:
OpportunityManagement
},
{
path
:
'/opportunities
/:id
'
,
path
:
'/opportunities
Detail
'
,
name
:
'OpportunityDetail'
,
component
:
OpportunityDetail
},
...
...
zhiJianBusi/zjbPc/src/views/DashboardLayout.vue
View file @
528665e
...
...
@@ -186,6 +186,7 @@ const menuItems = [
// 面包屑配置
const
breadcrumbMap
=
{
"/opportunities"
:
"商机管理"
,
"/opportunitiesDetail"
:
"商机详情"
,
"/grid-query"
:
"网格查询"
,
"/system"
:
"系统管理"
,
"/system/personnel"
:
"人员管理"
,
...
...
zhiJianBusi/zjbPc/src/views/OpportunityDetail.vue
View file @
528665e
...
...
@@ -17,7 +17,7 @@
<el-col
:span=
"8"
>
<div
class=
"info-item"
>
<span
class=
"info-label"
>
商机ID:
</span>
<span
class=
"info-value"
>
{{
opportunity
.
id
}}
</span>
<span
class=
"info-value"
>
{{
opportunity
.
opportunityCode
}}
</span>
</div>
</el-col>
<el-col
:span=
"8"
>
...
...
@@ -220,7 +220,7 @@
icon=
"el-icon-circle-close"
class=
"action-btn"
@
click=
"shutBusi"
:disabled=
"
(opportunity.status==5 || opportunity.status==4)
|| ifCanOperate"
:disabled=
"
opportunity.status==5 || opportunity.status==4
|| ifCanOperate"
>
关闭商机
</el-button>
...
...
@@ -422,10 +422,7 @@ export default {
name
:
'OpportunityDetail'
,
data
()
{
return
{
picArr
:
[
'https://testznzl.lgyzpt.com/activity/zjbPc/static/img/ad61df2f28f6b51d5f386829473ab1b592fd14e0.47afcfd0.png'
,
'https://testznzl.lgyzpt.com/activity/zjbPc/static/img/1b66793397a66bf54212d266505eb98e3377a354.fb5fc9cc.png'
],
detailId
:
''
,
opportunity
:
{},
followList
:
[],
...
...
@@ -463,20 +460,31 @@ export default {
}
},
created
()
{
this
.
detailId
=
localStorage
.
getItem
(
'detailId'
)
this
.
queryDetail
()
this
.
queryFollow
()
this
.
queryCloseList
()
},
methods
:
{
computed
:
{
ifCanOperate
(){
let
ui
=
JSON
.
parse
(
localStorage
.
getItem
(
'accountInfo'
))
return
this
.
opportunity
.
opportunityType
==
2
&&
ui
.
gridCode
},
if
(
this
.
opportunity
.
opportunityType
==
2
&&
ui
.
gridCode
){
return
true
}
return
false
}
},
methods
:
{
queryCloseList
(){
this
.
apiReq
.
queryBusiCloseReansonList
({
let
ui
=
JSON
.
parse
(
localStorage
.
getItem
(
'accountInfo'
))
this
.
apiReq
.
queryAreaCloseReansonList
({
pageNum
:
1
,
pageSize
:
1000
pageSize
:
1000
,
areaCode
:
ui
.
areaCode
}).
then
(
res
=>
{
if
(
res
.
code
==
200
){
this
.
closeBusiStore
.
reasonsList
=
res
.
data
.
records
...
...
@@ -535,7 +543,7 @@ export default {
},
queryFollow
(){
this
.
apiReq
.
queryBusiFollowList
({
opportunityId
:
this
.
$route
.
params
.
i
d
,
opportunityId
:
this
.
detailI
d
,
pageNum
:
1
,
pageSize
:
1000
}).
then
(
res
=>
{
...
...
@@ -580,7 +588,7 @@ export default {
},
queryDetail
(){
this
.
apiReq
.
queryBusiDetail
({
opportunityId
:
this
.
$route
.
params
.
i
d
opportunityId
:
this
.
detailI
d
}).
then
(
res
=>
{
if
(
res
.
code
==
200
){
if
(
res
.
data
.
voiceDescriptionUrl
){
...
...
zhiJianBusi/zjbPc/src/views/OpportunityManagement.vue
View file @
528665e
...
...
@@ -848,7 +848,9 @@ export default {
this
.
currentPage
=
1
},
checkDetail
(
row
){
this
.
$router
.
push
(
`/opportunities/
${
row
.
id
}
`
)
localStorage
.
setItem
(
'detailId'
,
row
.
id
)
this
.
$router
.
push
(
`/opportunitiesDetail`
)
},
checkAudio
(
row
){
this
.
handleOpenAudit
(
row
.
id
)
...
...
zhiJianBusi/zjbPhone/.claude/settings.local.json
View file @
528665e
...
...
@@ -19,7 +19,11 @@
"mcp__figma__get_metadata"
,
"Bash(python3 -m http.server 8080)"
,
"Bash(open
\"
http://localhost:8080/zjbPhone/busiDetail.html
\"
)"
,
"Bash(open
\"
http://localhost:8080/myBusi.html
\"
)"
"Bash(open
\"
http://localhost:8080/myBusi.html
\"
)"
,
"Bash(lsof -ti:8080)"
,
"Bash(python3 -m http.server 8081)"
,
"Bash(open
\"
http://localhost:8081/zjbPhone/busiDetail.html
\"
)"
,
"Bash(open
\"
http://localhost:8081/zjbPhone/addBusi.html
\"
)"
],
"deny"
:
[],
"ask"
:
[]
...
...
zhiJianBusi/zjbPhone/busiDetail.html
View file @
528665e
...
...
@@ -162,7 +162,9 @@
<p
class=
"progress-time"
>
{{ switchTime(item.createTime) }}
</p>
<p
class=
"progress-desc"
>
{{ item.followPersonName }}:{{ item.followContent }}
</p>
<div
class=
"progress-img"
v-if=
"followImgArr(item.followImages).length > 0"
>
<img
v-for=
"iitem in followImgArr(item.followImages)"
:src=
"iitem"
>
<img
v-for=
"(iitem, imgIndex) in followImgArr(item.followImages)"
:src=
"iitem"
@
click=
"showImagePreview(followImgArr(item.followImages), imgIndex)"
>
</div>
</div>
</div>
...
...
@@ -250,18 +252,36 @@
</div>
</div>
<!-- <div class="outAlertBg">
<div class="imgAlertCon">
<!-- 图片预览弹窗 -->
<div
class=
"outAlertBg"
v-if=
"imagePreview.show"
@
click=
"closeImagePreview"
>
<div
class=
"imgAlertCon"
@
click
.
stop
>
<div
class=
"imgDiv"
>
<img src="https://pic1.arkoo.com/56D0B40F99F841DF8A2425762AE2565D/picture/o_1i4qop009177v1tgf14db15he1iaj1is.jpg" alt="">
<img
:src=
"imagePreview.images[imagePreview.currentIndex]"
alt=
""
@
load=
"onImageLoad"
@
error=
"onImageError"
>
</div>
<div class="choButt">
<div class="prev">prev</div>
<div class="next">next</div>
<!-- 图片索引指示器 -->
<div
class=
"imgIndicator"
v-if=
"imagePreview.images.length > 1"
>
{{ imagePreview.currentIndex + 1 }} / {{ imagePreview.images.length }}
</div>
<!-- 切换按钮 -->
<div
class=
"choButt"
v-if=
"imagePreview.images.length > 1"
>
<div
class=
"prev"
:class=
"{ disabled: imagePreview.currentIndex === 0 }"
@
click=
"prevImage"
>
上一张
</div>
<div
class=
"next"
:class=
"{ disabled: imagePreview.currentIndex === imagePreview.images.length - 1 }"
@
click=
"nextImage"
>
下一张
</div>
</div>
<!-- 关闭按钮 -->
<div
class=
"closePreview"
@
click=
"closeImagePreview"
>
<img
src=
"images/close.png"
alt=
""
>
</div>
</div>
</div>
-->
</div>
</div>
<!-- 引入Vue.js -->
...
...
zhiJianBusi/zjbPhone/css/busiDetail.css
View file @
528665e
...
...
@@ -182,32 +182,6 @@ body {
}
/* .imgAlertCon .imgDiv{
width: 6.5rem;
height: 9rem;
margin-bottom: .3rem;
display: flex;
align-items: center;
justify-content: center;
}
.imgAlertCon .imgDiv img{
max-width: 100%;
max-height: 100%;
}
.imgAlertCon .choButt{
width: 100%;
display: flex;
color: #fff;
font-size: .4rem;
justify-content: space-around;
}
.imgAlertCon .choButt div{
background: #0068EE;
padding: .1rem .3rem;
border-radius: .08rem;
} */
/* 通用卡片样式 */
.business-info-section
,
.business-detail-section
,
...
...
@@ -544,4 +518,157 @@ body {
.back-icon
:focus
{
outline
:
0.04rem
solid
rgba
(
0
,
122
,
255
,
0.3
);
outline-offset
:
0.04rem
;
}
/* 图片预览弹窗样式 */
.outAlertBg
[
style
*=
"display: block"
],
.outAlertBg
:not
([
style
*=
"none"
])
{
position
:
fixed
;
top
:
0
;
left
:
0
;
width
:
100%
;
height
:
100%
;
background
:
rgba
(
0
,
0
,
0
,
0.9
);
z-index
:
99999
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
.imgAlertCon
{
position
:
relative
;
width
:
90%
;
height
:
80%
;
display
:
flex
;
flex-direction
:
column
;
align-items
:
center
;
justify-content
:
center
;
}
.imgDiv
{
flex
:
1
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
overflow
:
hidden
;
width
:
100%
;
}
.imgDiv
img
{
max-width
:
100%
;
max-height
:
100%
;
object-fit
:
contain
;
border-radius
:
0.1rem
;
}
/* 图片索引指示器 */
.imgIndicator
{
position
:
absolute
;
top
:
1rem
;
background
:
rgba
(
0
,
0
,
0
,
0.7
);
color
:
white
;
padding
:
0.2rem
0.4rem
;
border-radius
:
0.2rem
;
font-size
:
0.3rem
;
z-index
:
10
;
}
/* 切换按钮组 */
.choButt
{
display
:
flex
;
justify-content
:
space-between
;
width
:
80%
;
margin-top
:
1rem
;
gap
:
1rem
;
}
.choButt
.prev
,
.choButt
.next
{
flex
:
1
;
padding
:
0.3rem
0.6rem
;
background
:
rgba
(
255
,
255
,
255
,
0.2
);
color
:
white
;
border-radius
:
0.3rem
;
text-align
:
center
;
cursor
:
pointer
;
font-size
:
0.3rem
;
transition
:
all
0.3s
ease
;
border
:
0.02rem
solid
rgba
(
255
,
255
,
255
,
0.3
);
}
.choButt
.prev
:hover
,
.choButt
.next
:hover
{
background
:
rgba
(
255
,
255
,
255
,
0.3
);
}
.choButt
.prev.disabled
,
.choButt
.next.disabled
{
opacity
:
0.3
;
cursor
:
not-allowed
;
}
.choButt
.prev.disabled
:hover
,
.choButt
.next.disabled
:hover
{
background
:
rgba
(
255
,
255
,
255
,
0.2
);
}
/* 关闭按钮 */
.closePreview
{
position
:
absolute
;
top
:
1rem
;
right
:
1rem
;
width
:
0.8rem
;
height
:
0.8rem
;
background
:
rgba
(
0
,
0
,
0
,
0.5
);
border-radius
:
50%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
cursor
:
pointer
;
z-index
:
10
;
}
.closePreview
img
{
width
:
0.4rem
;
height
:
0.4rem
;
object-fit
:
contain
;
}
/* 跟进图片样式 */
.progress-img
{
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
0.2rem
;
margin-top
:
0.2rem
;
}
.progress-img
img
{
width
:
1.5rem
;
height
:
1.5rem
;
object-fit
:
cover
;
border-radius
:
0.1rem
;
cursor
:
pointer
;
transition
:
transform
0.2s
ease
;
}
.progress-img
img
:hover
{
transform
:
scale
(
1.05
);
}
.progress-img
img
:active
{
transform
:
scale
(
0.95
);
}
/* 动画效果 */
@keyframes
fadeIn
{
from
{
opacity
:
0
;
}
to
{
opacity
:
1
;
}
}
.imgAlertCon
{
animation
:
fadeIn
0.3s
ease-out
;
}
\ No newline at end of file
zhiJianBusi/zjbPhone/js/addBusi.js
View file @
528665e
...
...
@@ -56,6 +56,10 @@ new Vue({
mounted
()
{
this
.
isAlone
=
utils
.
getUrlParam
(
'source'
)
!=
'zhijian'
// 获取用户信息并反写地址
this
.
getUserInfoAndInitAddress
();
if
(
!
this
.
isAlone
){
this
.
initData
()
this
.
queryHaZjLabel
()
...
...
@@ -73,6 +77,61 @@ new Vue({
},
methods
:
{
/**
* 获取用户信息并初始化地址
*/
getUserInfoAndInitAddress
()
{
// 从localStorage获取用户信息
const
userInfoStr
=
localStorage
.
getItem
(
'userInfo'
);
if
(
userInfoStr
)
{
this
.
userInfo
=
JSON
.
parse
(
userInfoStr
);
// 如果有区域代码,则进行地址反写
if
(
this
.
userInfo
.
areaCode
)
{
this
.
initAddressByAreaCode
(
this
.
userInfo
.
areaCode
);
}
}
},
/**
* 根据区域代码初始化地址选择
*/
initAddressByAreaCode
(
areaCode
)
{
const
province
=
this
.
addressData
.
provinces
[
0
];
// 江苏省
// 搜索所有城市和区县
for
(
let
i
=
0
;
i
<
province
.
cities
.
length
;
i
++
)
{
const
city
=
province
.
cities
[
i
];
// 搜索该城市的所有区县
for
(
let
j
=
0
;
j
<
city
.
districts
.
length
;
j
++
)
{
const
district
=
city
.
districts
[
j
];
// 如果找到匹配的区县代码
if
(
district
.
code
===
areaCode
)
{
// 设置选中的省市区
this
.
addressSelector
.
selectedProvince
=
province
;
this
.
addressSelector
.
selectedCity
=
city
;
this
.
addressSelector
.
selectedDistrict
=
district
;
this
.
addressSelector
.
selectedStreet
=
null
;
// 更新显示的地址文本
this
.
selectedAddressText
=
`
${
province
.
name
}
${
city
.
name
}
${
district
.
name
}
`
;
this
.
selectedAddressCode
=
areaCode
;
// 设置地址选择器当前步骤为街道选择(步骤3)
this
.
addressSelector
.
currentStep
=
3
;
console
.
log
(
`地址反写成功:
${
this
.
selectedAddressText
}
`
);
return
;
}
}
}
// 如果没有找到对应的区县代码
console
.
log
(
`未找到区域代码
${
areaCode
}
对应的地址信息`
);
},
goZj
(){
location
.
href
=
'result.html'
},
...
...
@@ -771,7 +830,14 @@ new Vue({
*/
openAddressSelector
()
{
this
.
addressSelector
.
show
=
true
;
this
.
addressSelector
.
currentStep
=
0
;
// 如果已经反写了地址(已选择省市区),直接跳到街道选择
if
(
this
.
addressSelector
.
selectedDistrict
)
{
this
.
addressSelector
.
currentStep
=
3
;
}
else
{
// 否则从省开始选择
this
.
addressSelector
.
currentStep
=
0
;
}
},
/**
...
...
zhiJianBusi/zjbPhone/js/busiDetail.js
View file @
528665e
...
...
@@ -56,7 +56,14 @@ new Vue({
},
timeWriteStr
:
''
,
nIndex
:
'--'
nIndex
:
'--'
,
// 图片预览相关数据
imagePreview
:
{
show
:
false
,
images
:
[],
currentIndex
:
0
}
},
created
()
{
...
...
@@ -605,6 +612,62 @@ new Vue({
},
/**
* 显示图片预览
*/
showImagePreview
(
images
,
index
=
0
)
{
this
.
imagePreview
.
images
=
images
;
this
.
imagePreview
.
currentIndex
=
index
;
this
.
imagePreview
.
show
=
true
;
// 禁止背景滚动
document
.
body
.
style
.
overflow
=
'hidden'
;
},
/**
* 关闭图片预览
*/
closeImagePreview
()
{
this
.
imagePreview
.
show
=
false
;
this
.
imagePreview
.
images
=
[];
this
.
imagePreview
.
currentIndex
=
0
;
// 恢复背景滚动
document
.
body
.
style
.
overflow
=
'auto'
;
},
/**
* 上一张图片
*/
prevImage
()
{
if
(
this
.
imagePreview
.
currentIndex
>
0
)
{
this
.
imagePreview
.
currentIndex
--
;
}
},
/**
* 下一张图片
*/
nextImage
()
{
if
(
this
.
imagePreview
.
currentIndex
<
this
.
imagePreview
.
images
.
length
-
1
)
{
this
.
imagePreview
.
currentIndex
++
;
}
},
/**
* 图片加载完成
*/
onImageLoad
()
{
console
.
log
(
'图片加载完成'
);
},
/**
* 图片加载错误
*/
onImageError
()
{
utils
.
toast
(
'图片加载失败'
);
},
/**
* 清理资源
*/
cleanup
()
{
...
...
@@ -618,6 +681,9 @@ new Vue({
clearTimeout
(
this
.
cleanupTimer
);
this
.
cleanupTimer
=
null
;
}
// 关闭图片预览
this
.
closeImagePreview
();
}
},
...
...
@@ -663,6 +729,21 @@ new Vue({
// 监听器
watch
:
{
// 监听ESC键关闭图片预览
'imagePreview.show'
(
newVal
)
{
if
(
newVal
)
{
const
handleKeyDown
=
(
e
)
=>
{
if
(
e
.
key
===
'Escape'
)
{
this
.
closeImagePreview
();
document
.
removeEventListener
(
'keydown'
,
handleKeyDown
);
}
else
if
(
e
.
key
===
'ArrowLeft'
)
{
this
.
prevImage
();
}
else
if
(
e
.
key
===
'ArrowRight'
)
{
this
.
nextImage
();
}
};
document
.
addEventListener
(
'keydown'
,
handleKeyDown
);
}
}
}
});
\ No newline at end of file
Write
Preview
Markdown
is supported
Attach a file
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 post a comment