Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
W
wangxiaolu-sfa-ui
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
sfa
wangxiaolu-sfa-ui
Commits
ae47d23f
提交
ae47d23f
authored
8月 18, 2025
作者:
lidongxu
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat(scm/logistics_receipt): 新增:供应链模块-物流回单菜单:对勤策物流回单数据统一管理查询和修改状态等功能
上级
7c1dcb3e
隐藏空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
503 行增加
和
13 行删除
+503
-13
index.js
src/api/index.js
+1
-0
logistics_receipt.js
src/api/scm/logistics_receipt.js
+19
-0
Navbar.vue
src/layout/components/Navbar.vue
+4
-2
permission.js
src/permission.js
+10
-9
dict.js
src/utils/dict.js
+1
-0
index.vue
src/views/promotion/task/index.vue
+4
-2
index.vue
src/views/scm/logistics_receipt/index.vue
+464
-0
没有找到文件。
src/api/index.js
浏览文件 @
ae47d23f
...
...
@@ -25,6 +25,7 @@ export * from './monitor/online'
export
*
from
'./monitor/server'
export
*
from
'./promotion/plan'
export
*
from
'./promotion/task'
export
*
from
'./scm/logistics_receipt'
export
*
from
'./system/dict/data'
export
*
from
'./system/dict/type'
export
*
from
'./system/attendance'
...
...
src/api/scm/logistics_receipt.js
0 → 100644
浏览文件 @
ae47d23f
import
request
from
'@/utils/request'
// 勤策发货单列表查询
export
const
getLogisticsReceiptListAPI
=
(
params
)
=>
{
return
request
({
url
:
'/bi/ordersent/query/page'
,
params
})
}
// 勤策发货单-回单照片是否完整&物流状态设置
export
const
setLogisticsReceiptStatusAPI
=
(
data
)
=>
{
return
request
({
url
:
'/bi/ordersent/core/update'
,
method
:
'PUT'
,
data
})
}
src/layout/components/Navbar.vue
浏览文件 @
ae47d23f
...
...
@@ -105,8 +105,9 @@ const showQuit = !window.h5sdk; // 判断飞书客户端内,则不显示退出
const
showVersionNoticeVisible
=
ref
(
false
)
// 判断版本通知是否出现
const
nowVersion
=
ref
(
''
)
// 当前最新版本
// 判断是否有新版本出现
onMounted
(()
=>
{
// 判断是否有新版本出现(监听 pinia 值的变化)
watch
(()
=>
versionStore
.
version
,
(
newVal
,
oldVal
)
=>
{
console
.
log
(
'versionStore.version'
,
versionStore
.
version
)
const
oldVersion
=
proxy
.
$cache
.
local
.
get
(
'version'
)
const
versionObj
=
versionStore
.
version
[
0
]
nowVersion
.
value
=
versionObj
.
version
...
...
@@ -114,6 +115,7 @@ onMounted(() => {
handleVersionList
()
}
})
// 展示版本通知弹框
const
showVersionFn
=
()
=>
{
handleVersionList
()
...
...
src/permission.js
浏览文件 @
ae47d23f
...
...
@@ -36,23 +36,24 @@ router.beforeEach((to, from, next) => {
useUserStore
().
getInfo
().
then
(()
=>
{
isRelogin
.
show
=
false
usePermissionStore
().
generateRoutes
().
then
(
accessRoutes
=>
{
// 生成可访问路由表
accessRoutes
.
forEach
(
route
=>
{
if
(
!
isHttp
(
route
.
path
))
{
router
.
addRoute
(
route
)
}
// 获取版本信息
useVersionStore
().
getVersion
().
then
((
res
)
=>
{
// 生成可访问路由表
accessRoutes
.
forEach
(
route
=>
{
if
(
!
isHttp
(
route
.
path
))
{
router
.
addRoute
(
route
)
}
})
next
({
...
to
,
replace
:
true
})
})
next
({
...
to
,
replace
:
true
})
})
}).
catch
(
err
=>
{
useUserStore
().
logOut
().
then
(()
=>
{
ElMessage
.
error
(
err
)
next
({
path
:
'/'
})
})
})
// 获取版本信息
useVersionStore
().
getVersion
()
}
else
{
next
()
}
...
...
src/utils/dict.js
浏览文件 @
ae47d23f
...
...
@@ -14,6 +14,7 @@ export function useDict(...args) {
res
.
value
[
dictType
]
=
dicts
;
}
else
{
getDicts
(
dictType
).
then
(
resp
=>
{
console
.
log
(
'字典数据'
,
resp
.
data
)
res
.
value
[
dictType
]
=
resp
.
data
.
map
(
p
=>
({
label
:
p
.
dictLabel
,
value
:
p
.
dictValue
,
elTagType
:
p
.
listClass
,
elTagClass
:
p
.
cssClass
}))
useDictStore
().
setDict
(
dictType
,
res
.
value
[
dictType
]);
})
...
...
src/views/promotion/task/index.vue
浏览文件 @
ae47d23f
...
...
@@ -106,7 +106,8 @@
<el-dialog
:title=
"photoLookInfoObj.storeName"
v-model=
"photoDialogVisible"
width=
"60%"
draggable
overflow
>
draggable
overflow
>
<p>
活动记录 ID :{{ photoLookInfoObj.id }}
</p>
<p>
活动时间 :{{ photoLookInfoObj.createDate }}
</p>
<el-card
v-for=
"obj in photoDialogList"
...
...
@@ -115,9 +116,10 @@
<div
class=
"content"
>
<el-result
:title=
"item.time"
:sub-title=
"item.title"
v-for=
"item in obj.list"
>
v-for=
"item
, index
in obj.list"
>
<
template
#
icon
>
<el-image
:src=
"item.photoUrl"
:initial-index=
"index"
:preview-src-list=
"[...obj.list.map(o => o.photoUrl)]"
/>
</
template
>
</el-result>
...
...
src/views/scm/logistics_receipt/index.vue
0 → 100644
浏览文件 @
ae47d23f
<
template
>
<div
class=
"app-container"
>
<div
class=
"container"
>
<!-- 查询表单 -->
<el-form
:model=
"queryParams"
inline
label-position=
"left"
>
<el-row>
<el-form-item
label=
"DD 单号查询"
prop=
"ddNo"
>
<el-input
v-model=
"queryParams.ddNo"
clearable
placeholder=
"输入要查询的 DD 单号"
@
input=
"getLogisticsReceiptList"
/>
</el-form-item>
<el-form-item
label=
"安徽/北京单据编号"
prop=
"sentNo"
>
<el-input
v-model=
"queryParams.sentNo"
clearable
placeholder=
"输入要查询的安徽/北京单独单号"
@
input=
"getLogisticsReceiptList"
style=
"width: 250px;"
/>
</el-form-item>
<el-form-item
label=
"物流公司编码"
prop=
"transport"
>
<el-input
v-model=
"queryParams.transport"
clearable
placeholder=
"输入要查询的物流公司编码"
@
input=
"getLogisticsReceiptList"
style=
"width: 220px;"
/>
</el-form-item>
<el-form-item
label=
"快递单号"
prop=
"expressNo"
>
<el-input
v-model=
"queryParams.expressNo"
clearable
placeholder=
"输入要查询的快递单号"
@
input=
"getLogisticsReceiptList"
/>
</el-form-item>
<el-form-item
label=
"订单状态"
prop=
"isOperateEnd"
>
<el-select
v-model=
"queryParams.isOperateEnd"
placeholder=
"查询订单状态"
clearable
@
change=
"getLogisticsReceiptList"
>
<el-option
label=
"已完成"
value=
"true"
/>
<el-option
label=
"未完成"
value=
"false"
/>
</el-select>
</el-form-item>
</el-row>
</el-form>
<!-- 数据表格 -->
<el-table
:data=
"tableList"
border
style=
"width: 100%"
class=
"table-container"
>
<el-table-column
v-for=
"item in columns"
:key=
"item.label"
:prop=
"item.prop"
:label=
"item.label"
:width=
"item.width"
:fixed=
"item.fixed"
:class-name=
"item.className"
>
<template
#
header=
"
{ column }"
v-if="item.prop === 'receiptPhoto'">
<div
class=
"header-container"
>
<span>
{{
column
.
label
}}
</span>
<el-button
@
click=
"showPhoto = !showPhoto"
style=
"margin-left: 10px;"
>
{{
showPhoto
?
'隐藏'
:
'显示'
}}
图片
</el-button>
</div>
</
template
>
<
template
#
default=
"scope"
>
<template
v-if=
"item.prop === 'receiptPhoto'"
>
<div
class=
"receipt-photo-container"
v-if=
"showPhoto"
>
<span
v-if=
"JSON.parse(scope.row[item.prop] || '[]').length === 0"
>
暂无图片
</span>
<el-image
v-else
v-for=
"(urlStr, index) in JSON.parse(scope.row[item.prop] || '[]')"
:key=
"index"
:initial-index=
"index"
:preview-src-list=
"JSON.parse(scope.row[item.prop] || '[]')"
preview-teleported
:src=
"urlStr"
alt=
"图片"
class=
"receipt-photo-item"
fit=
"cover"
style=
"width: 80px; height: 50px; "
/>
</div>
</
template
>
<
template
v-else-if=
"item.prop === 'logisticsTrack'"
>
<el-button
type=
"primary"
@
click=
"handleLogisticsTrack(scope.row)"
text
>
查看物流轨迹
</el-button>
</
template
>
<
template
v-else-if=
"item.prop === 'receiptPhotoCompleteFlag'"
>
<el-select
v-model=
"scope.row[item.prop]"
placeholder=
"请选择"
style=
"width: 100%"
@
change=
"handleReceiptPhotoChangeStatus(scope.row)"
>
<el-option
v-for=
"item in receiptPhotoCompleteFlagOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</
template
>
<
template
v-else-if=
"item.prop === 'sentStatus'"
>
<el-select
v-model=
"scope.row[item.prop]"
placeholder=
"请选择"
filterable
style=
"width: 100%"
@
change=
"handleSentStatusChange(scope.row)"
>
<el-option
v-for=
"item in sentStatusOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</
template
>
<
template
v-else
>
<!-- 其他字段显示原始值 -->
{{
formatter
(
scope
.
row
,
scope
.
column
,
scope
.
row
[
item
.
prop
])
}}
</
template
>
</template>
</el-table-column>
<!-- <el-table-column label="操作"
width="200"
fixed="right">
<template #default="scope">
<el-button type="danger"
@click="deleteView(scope.row)"
text>
删除
</el-button>
</template>
</el-table-column> -->
</el-table>
<!-- 分页 -->
<pagination
:total=
"total"
v-model:page=
"queryParams.pageNum"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getLogisticsReceiptList"
/>
</div>
</div>
</template>
<
script
setup
>
import
{
getLogisticsReceiptListAPI
,
setLogisticsReceiptStatusAPI
}
from
'@/api'
import
{
parseTime
,
isExternal
}
from
'@/utils'
const
{
proxy
}
=
getCurrentInstance
()
const
{
supply_logistics_shipping_order_type
:
typeDict
}
=
proxy
.
useDict
(
"supply_logistics_shipping_order_type"
)
/******************** 发货单列表 ********************/
const
queryParams
=
reactive
({
pageNum
:
1
,
pageSize
:
10
})
const
showPhoto
=
ref
(
false
)
const
total
=
ref
(
0
)
const
tableList
=
ref
([])
// 物流轨迹链接:对应编码和地址列表
const
logisticsTrack
=
ref
([
{
code
:
[
134
,
109
],
url
:
'#/logistics?sentNo='
,
// 拼接 AHSD 安徽单据编号跳转项目路由页面查看
dataKey
:
'ahSentNo'
},
{
code
:
[
132
],
url
:
'https://gps.rrswl.com/GPSTrackWeb/sqmmap.jsp?orderno='
,
// 拼接物流单号(DD 单号)
dataKey
:
'expressNo'
},
{
code
:
[
104
],
url
:
'https://cloud.region2.qince.com/openplat/app/dingzhi/wangxiaolu/delivery_url/redirect.do?sentNo='
,
// DD 单号
dataKey
:
'ddNo'
}
])
const
columns
=
ref
([
{
label
:
'发货单 ID'
,
prop
:
'sendId'
,
width
:
100
,
fixed
:
'left'
},
{
label
:
'DD 单号'
,
prop
:
'ddNo'
,
width
:
170
,
fixed
:
'left'
},
{
label
:
'安徽单据编号'
,
prop
:
'ahSentNo'
,
width
:
180
,
},
{
label
:
'北京单据编号'
,
prop
:
'bjSentNo'
,
width
:
180
,
},
{
label
:
'快递单号'
,
prop
:
'expressNo'
,
width
:
150
},
{
label
:
'版本号'
,
prop
:
'bjSentVersion'
,
width
:
80
},
{
label
:
'单据类型'
,
prop
:
'type'
,
// X06: 销售出库单,N02:杂发单
width
:
100
},
{
label
:
'过账日期'
,
prop
:
'postDate'
,
width
:
180
},
{
label
:
'运输公司编码'
,
prop
:
'transport'
,
width
:
120
},
{
label
:
'运输公司'
,
prop
:
'transportName'
,
width
:
100
},
{
label
:
'签收时间'
,
prop
:
'operateEndDateTime'
,
width
:
180
},
{
label
:
'回单状态'
,
prop
:
'receiptFlag'
,
// 有/无/回单异常
width
:
100
},
{
label
:
'回单照片'
,
prop
:
'receiptPhoto'
,
width
:
200
,
className
:
'col-receipt-photo'
,
// 根据图片数量动态计算宽度,确保图片能两列显示
// width: computed(() => {
// const maxPhotos = Math.max(...tableList.value.map(row => {
// try {
// const photos = JSON.parse(row.receiptPhoto || '[]')
// return photos.length
// } catch {
// return 0
// }
// }))
// console.log(maxPhotos, 'maxphotos')
// // 计算需要的列数,每列最多2张图片
// const columns = Math.ceil(maxPhotos / 2)
// if (columns === 0) return 200
// // 每列宽度:80px + 5px gap 间距 + 外层容器左右 padding 共 30px
// return Math.max(columns * 80 + 5 + 30)
// })
},
{
label
:
'创建时间'
,
prop
:
'createTime'
,
width
:
180
},
{
label
:
'更新时间'
,
prop
:
'updateTime'
,
width
:
180
},
{
label
:
'物流轨迹'
,
prop
:
'logisticsTrack'
,
width
:
140
,
fixed
:
'right'
},
{
label
:
'回单照片是否完整'
,
prop
:
'receiptPhotoCompleteFlag'
,
// 完整/不完整
width
:
150
,
fixed
:
'right'
},
{
label
:
'物流状态'
,
prop
:
'sentStatus'
,
width
:
180
,
fixed
:
'right'
}
])
// 回单图片是否完整选项组
const
receiptPhotoCompleteFlagOptions
=
ref
([
{
value
:
'完整'
,
label
:
'完整'
},
{
value
:
'不完整'
,
label
:
'不完整'
}
])
// 物流状态选项组
const
sentStatusOptions
=
ref
([
{
value
:
'整单签收'
,
label
:
'整单签收'
},
{
value
:
'整单拒收'
,
label
:
'整单拒收'
},
{
value
:
'部分退回在途'
,
label
:
'部分退回在途'
},
{
value
:
'部分退回已完结'
,
label
:
'部分退回已完结'
},
{
value
:
'整单退回在途'
,
label
:
'整单退回在途'
},
{
value
:
'整单退回完结'
,
label
:
'整单退回完结'
},
{
value
:
'发货在途'
,
label
:
'发货在途'
},
{
value
:
'部分滞留'
,
label
:
'部分滞留'
},
{
value
:
'整单滞留'
,
label
:
'整单滞留'
}
])
// 获取发货单列表
const
getLogisticsReceiptList
=
async
()
=>
{
const
{
data
:
{
rows
,
total
:
totalNum
}
}
=
await
getLogisticsReceiptListAPI
(
queryParams
)
tableList
.
value
=
rows
total
.
value
=
totalNum
}
getLogisticsReceiptList
()
// 查看物流轨迹
const
handleLogisticsTrack
=
(
row
)
=>
{
const
obj
=
logisticsTrack
.
value
.
find
(
item
=>
item
.
code
.
includes
(
row
.
transport
*
1
))
console
.
log
(
obj
)
if
(
isExternal
(
obj
?.
url
))
{
window
.
open
(
obj
.
url
+
row
[
obj
.
dataKey
],
'_blank'
)
}
else
{
window
.
open
(
window
.
location
.
href
.
split
(
'/'
)[
0
]
+
obj
.
url
+
row
[
obj
.
dataKey
],
'_blank'
)
}
}
// 格式化表格列
const
formatter
=
(
row
,
columns
,
value
)
=>
{
// 判断有值再转换
if
(
columns
.
property
===
'type'
)
{
return
typeDict
.
value
.
find
(
item
=>
item
.
value
===
value
)?.
label
}
else
if
(
columns
.
property
===
'createTime'
||
columns
.
property
===
'updateTime'
)
{
return
parseTime
(
value
,
'{y}-{m}-{d} {h}:{i}:{s}'
)
}
else
{
return
value
}
}
// 修改回单照片是否完整
const
handleReceiptPhotoChangeStatus
=
async
(
row
)
=>
{
await
setLogisticsReceiptStatusAPI
({
sendId
:
row
.
sendId
,
receiptPhotoCompleteFlag
:
row
.
receiptPhotoCompleteFlag
})
proxy
.
$modal
.
msgSuccess
(
'修改成功'
)
getLogisticsReceiptList
()
}
// 修改物流状态
const
handleSentStatusChange
=
async
(
row
)
=>
{
await
setLogisticsReceiptStatusAPI
({
sendId
:
row
.
sendId
,
sentStatus
:
row
.
sentStatus
})
proxy
.
$modal
.
msgSuccess
(
'修改成功'
)
getLogisticsReceiptList
()
}
</
script
>
<
style
scoped
lang=
"scss"
>
.table-container
{
margin-top
:
20px
;
.header-container
{
display
:
flex
;
align-items
:
center
;
}
::v-deep
(
.el-image
)
{
img
{
width
:
80px
!
important
;
height
:
50px
!
important
;
}
}
}
.receipt-photo-container
{
padding
:
0
15px
;
display
:
flex
;
flex-wrap
:
wrap
;
gap
:
10px
;
min-width
:
200px
;
/* justify-content: center; // 内容整体居中
align-items: flex-start; // 顶部对齐 */
justify-content
:
flex-start
;
// 改为左对齐,让每行都从左边开始
align-items
:
flex-start
;
// 顶部对齐
.receipt-photo-item
{
border-radius
:
4px
;
border
:
1px
solid
#e4e7ed
;
transition
:
all
0
.3s
;
flex
:
0
0
80px
;
// 固定宽度,不伸缩
&
:hover
{
border-color
:
#409eff
;
box-shadow
:
0
2px
8px
rgba
(
64
,
158
,
255
,
0
.2
);
}
}
}
// 让表格列宽自适应内容
::v-deep
(
.el-table
)
{
.el-table__body-wrapper
{
.el-table__body
{
.el-table__row
{
.cell
{
white-space
:
nowrap
;
overflow
:
visible
;
}
}
td
.el-table__cell.col-receipt-photo
{
.cell
{
padding-right
:
0px
;
// 给回单照片列补充右内边距
padding-left
:
0px
;
// 给回单照片列补充左内边距
text-align
:
center
;
// 内容居中
}
}
}
}
}
</
style
>
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论