Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
B
biz-trina5-app
Project
Project
Details
Activity
Releases
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
贺双
biz-trina5-app
Commits
bf0b8600
Commit
bf0b8600
authored
Jun 09, 2025
by
贺世双
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
上传问题提交
parent
eba987bb
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
334 additions
and
37 deletions
+334
-37
bs-uploader.vue
components/baseComponents/bs-uploader/bs-uploader.vue
+14
-4
uploadBehavior.js
mixins/uploadBehavior.js
+316
-28
abnormalEvent.vue
subpkg/abnormalEvent/abnormalEvent.vue
+2
-2
abnormalEventDetail.vue
subpkg/abnormalEventDetail/abnormalEventDetail.vue
+2
-3
No files found.
components/baseComponents/bs-uploader/bs-uploader.vue
View file @
bf0b8600
...
...
@@ -9,12 +9,15 @@
<template
v-if=
"item.type === 'image'"
>
<image
mode=
"aspectFill"
:src=
"item.url"
:data-index=
"index"
@
click=
"previewImage"
class=
"previewImg"
/>
</
template
>
<
template
v-if=
"item.type === 'file'"
>
<image
src=
"../../../static/img/fileIcon/file.png"
:data-index=
"index"
class=
"previewImg"
/>
</
template
>
<
template
v-if=
"item.type === 'video'"
>
<video
class=
"previewImg"
:src=
"item.url"
:page-gesture=
"true"
:show-mute-btn=
"true"
:enable-play-gesture=
"true"
/>
</
template
>
<u-icon
v-if=
"isShowDelete"
name=
"close-circle-fill"
class=
"clearIcon"
size=
"30"
@
click=
"deleteFile"
:index=
'index'
/>
</view>
<
template
v-if=
"
isIos || cameraType
"
>
<
template
v-if=
"
(isIos || cameraType) && fileDetailList.length < maxCount
"
>
<view
class=
"uploadeBtn flex_col"
@
click=
"onUpLoad"
>
<view
class=
"t-icon t-icon-picture"
/>
<text
style=
"margin-top:10rpx"
>
{{
btnTitle
}}
</text>
...
...
@@ -35,7 +38,14 @@
</
template
>
</view>
<!-- 自定义相机 -->
<bs-customCamera
:visible=
"visible"
:cameraType=
"cameraType"
@
uploadFinish=
"customCameraFinish"
@
uploadCancel=
"visible=false"
/>
<bs-customCamera
:visible=
"visible"
:cameraType=
"cameraType"
@
uploadFinish=
"customCameraFinish"
@
uploadCancel=
"visible=false"
/>
<!-- 水印 -->
<!-- #ifdef MP-WEIXIN -->
<canvas
type=
"2d"
id=
"upload-canvas"
class=
"uploadCanvas"
:style=
"{'width':width+'px','height':height+'px','position':'absolute','z-index':'-999','top':'0px','left':'-1000000px'}"
/>
<!-- #endif -->
<!-- #ifdef H5 -->
<canvas
canvas-id=
"upload-canvas"
class=
"uploadCanvas"
:style=
"{'width':width+'px','height':height+'px','position':'absolute','z-index':'-9999999','top':'0px','left':'-1000000px'}"
/>
<!-- #endif -->
</view>
</template>
...
...
@@ -52,7 +62,7 @@
},
uploadAccept
:
{
type
:
String
,
//接受的文件类型: image | video | file | all | media; file只支持H5(all、media仅小程序支持)
default
:
"
image
"
default
:
"
all
"
},
maxDuration
:
{
type
:
[
String
,
Number
],
//当accept为video时生效,拍摄视频最长拍摄时间,单位秒
...
...
@@ -118,7 +128,7 @@
background-color
:
#fff
;
color
:
#D81E06
!
important
;
position
:
absolute
;
top
:
4rpx
;
top
:
25rpx
!
important
;
right
:
4rpx
;
}
}
...
...
mixins/uploadBehavior.js
View file @
bf0b8600
import
{
uploadImg
}
from
'../api/apiList'
;
import
{
uploadImg
,
userMobileOperation
,
getUserInfoName
,
getWaterMark
}
from
'../api/apiList'
;
const
getUserLocation
=
require
(
'../mixins/getUserLocation'
)
import
{
formatGMT
}
from
"../utils/util.js"
;
import
AMap
from
"../utils/AMapUtil.js"
import
compress
from
'../utils/compress'
module
.
exports
=
{
data
()
{
return
{
...
...
@@ -6,10 +10,19 @@ module.exports = {
fileDetailList
:
[],
//文件列表, 含文件名等
isIos
:
false
,
visible
:
false
,
//是否显示自定义相机
//水印相关
userInfo
:
{},
locationInfo
:
{},
isShowWaterMark
:
false
,
width
:
uni
.
getSystemInfoSync
().
windowWidth
,
height
:
uni
.
getSystemInfoSync
().
windowHeight
,
};
},
created
()
{
//引入地址混入
mixins
:
[
getUserLocation
],
created
()
{
this
.
judgeAddWaterMark
();
// #ifdef H5
const
platform
=
uni
.
getSystemInfoSync
().
platform
if
(
platform
===
'ios'
)
{
...
...
@@ -19,10 +32,9 @@ module.exports = {
},
//事件处理函数
methods
:
{
//图片上传 IOS兼容
onUpLoad
()
{
if
(
this
.
cameraType
)
{
if
(
this
.
cameraType
)
{
this
.
visible
=
true
//跳转自定义相机
}
else
if
(
this
.
$jwx
)
{
const
_this
=
this
...
...
@@ -49,7 +61,7 @@ module.exports = {
success
:
function
(
res
)
{
const
localData
=
res
.
localData
_this
.
fileList
=
_this
.
fileList
.
concat
(
localData
)
resolve
(
'done!'
)
setTimeout
(()
=>
resolve
(
'done!'
),
0
)
}
});
})
...
...
@@ -57,10 +69,9 @@ module.exports = {
//上传图片
uploadImage
(
callback
)
{
let
{
fileList
}
=
this
;
if
(
!
fileList
.
length
&&
!
this
.
required
)
return
callback
(
''
);
if
(
!
fileList
.
length
)
{
let
{
fileDetailList
}
=
this
;
if
(
!
fileDetailList
.
length
&&
!
this
.
required
)
return
callback
(
''
);
if
(
!
fileDetailList
.
length
)
{
uni
.
showToast
({
title
:
`请选择
${
this
.
uploadTitle
}
`
,
icon
:
'error'
,
...
...
@@ -68,28 +79,73 @@ module.exports = {
});
return
;
}
let
images
=
[];
fileList
.
forEach
(
item
=>
{
const
file
=
this
.
fileDetailList
.
find
(
file
=>
file
.
url
===
item
)
uploadImg
(
item
,
file
.
type
).
then
(
res
=>
{
//微信小程序仅支持单文件上传,传多个文件需要反复调用本API。所以跨端的写法就是循环调用本API。
uni
.
hideLoading
();
let
data
=
JSON
.
parse
(
res
).
data
;
images
.
push
(
data
.
path
);
if
(
images
.
length
===
fileList
.
length
)
{
return
callback
(
images
.
join
(
'|'
));
}
})
fileDetailList
.
forEach
(
item
=>
{
if
(
item
.
type
===
"image"
){
uploadImg
(
item
.
url
).
then
(
res
=>
{
uni
.
hideLoading
();
let
data
=
JSON
.
parse
(
res
).
data
;
images
.
push
(
data
.
path
);
if
(
images
.
length
===
fileDetailList
.
length
)
{
return
callback
(
images
.
join
(
'|'
));
}
})
}
else
{
uploadImg
(
item
.
url
,
"file"
).
then
(
res
=>
{
uni
.
hideLoading
();
let
data
=
JSON
.
parse
(
res
).
data
;
images
.
push
(
data
.
path
);
if
(
images
.
length
===
fileDetailList
.
length
)
{
return
callback
(
images
.
join
(
'|'
));
}
})
}
});
},
//上传图片
async
uploadImageSync
()
{
let
{
fileList
}
=
this
;
if
(
!
fileList
.
length
&&
!
this
.
required
)
return
""
;
if
(
!
fileList
.
length
)
{
uni
.
showToast
({
title
:
'请上传图片'
,
icon
:
'error'
,
duration
:
3000
});
return
;
}
let
images
=
""
;
for
(
const
imageFile
of
fileList
)
{
const
res
=
await
uploadImg
(
imageFile
)
uni
.
hideLoading
();
let
data
=
JSON
.
parse
(
res
).
data
;
if
(
images
===
""
)
{
images
=
data
.
path
}
else
{
images
=
images
+
"|"
+
data
.
path
}
}
return
images
},
// 上传文件回调
uploadAfterRead
(
info
)
{
async
uploadAfterRead
(
info
)
{
let
{
file
}
=
info
;
const
newFile
=
file
.
map
(
item
=>
item
.
url
);
this
.
fileList
=
[...
this
.
fileList
,
...
newFile
]
this
.
fileDetailList
=
[...
this
.
fileDetailList
,
...
file
]
this
.
fileDetailList
=
[...
this
.
fileDetailList
,
...
file
];
let
type
=
file
[
0
].
type
//判断是否需要添加水印
if
(
this
.
isShowWaterMark
&&
type
===
"image"
)
{
let
fileList
=
[]
for
(
let
i
=
0
;
i
<
file
.
length
;
i
++
)
{
const
res
=
await
this
.
addWatermark
(
file
[
i
].
url
);
fileList
.
push
(
res
)
}
this
.
fileList
=
[...
this
.
fileList
,
...
fileList
]
}
else
{
const
newFile
=
file
.
map
(
item
=>
item
.
url
);
this
.
fileList
=
[...
this
.
fileList
,
...
newFile
];
}
},
//拍照确认回调
...
...
@@ -116,11 +172,243 @@ module.exports = {
content
:
'是否确认删除?'
,
success
:
(
res
)
=>
{
if
(
res
.
confirm
)
{
this
.
fileList
=
this
.
fileList
.
filter
((
item
,
idx
)
=>
idx
!==
index
)
this
.
fileDetailList
=
this
.
fileDetailList
.
filter
((
item
,
idx
)
=>
idx
!==
index
)
this
.
fileList
=
this
.
fileList
.
filter
((
item
,
idx
)
=>
idx
!==
index
)
this
.
fileDetailList
=
this
.
fileDetailList
.
filter
((
item
,
idx
)
=>
idx
!==
index
)
}
else
if
(
res
.
cancel
)
{}
}
});
},
//获取用户信息
getUserInfo
()
{
userMobileOperation
(
'getUserInfo'
).
then
(
res
=>
{
let
data
=
res
.
data
.
data
data
.
mobile
=
data
.
userExt
.
mobile
||
'暂无'
this
.
userInfo
=
{...
data
}
})
},
//是否添加水印
judgeAddWaterMark
()
{
const
_this
=
this
getWaterMark
().
then
(({
data
:
res
})
=>
{
const
isShowWaterMark
=
res
.
data
.
preference
[
"client.add.photo.watermark"
]
_this
.
isShowWaterMark
=
isShowWaterMark
if
(
isShowWaterMark
){
_this
.
getSiteName
();
_this
.
getUserInfo
();
}
})
},
//添加水印
addWatermark
(
fileUrl
)
{
let
that
=
this
;
const
markDate
=
formatGMT
(
this
.
locationInfo
.
time
,
"D"
);
const
markTime
=
formatGMT
(
this
.
locationInfo
.
time
,
"H"
)?.
slice
(
0
,
5
);
const
arr
=
[
"日"
,
"一"
,
"二"
,
"三"
,
"四"
,
"五"
,
"六"
];
let
address
=
""
;
this
.
locationInfo
.
address
?.
split
(
""
).
forEach
((
item
,
index
)
=>
{
if
(
index
===
12
||
index
===
30
)
{
address
+=
"
\n
"
;
}
address
+=
item
;
})
const
week
=
`星期
${
arr
[
new
Date
(
this
.
locationInfo
.
time
)?.
getDay
()]}
`;
const waterMarkInfo =
`
$
{
markTime
}
\
n$
{
markDate
}
\
n$
{
week
}
\
n
地点:
$
{
address
}
\
n
司机名:
$
{
this
.
userInfo
.
userExt
.
driverName
}
`.split(
'\n');
let platform = uni.getSystemInfoSync().platform;
return new Promise((resolve, reject) => {
uni.getImageInfo({
src: fileUrl,
fail: (error) => {}, // 替换为你的图片路径
success: async (res) => {
let imageWidth = res.width;
let imageHeight = res.height;
// #ifdef H5
const ctx = uni.createCanvasContext('upload-canvas', that);
//计算图片比例
const pw = imageWidth >= uni.getSystemInfoSync().windowWidth ? uni
.getSystemInfoSync().windowWidth / imageWidth : imageWidth / uni
.getSystemInfoSync().windowWidth;
const py = imageHeight >= uni.getSystemInfoSync().windowHeight ? uni
.getSystemInfoSync().windowHeight / imageHeight : imageHeight / uni
.getSystemInfoSync().windowHeight;
const p = pw >= py ? py : pw;
const drawX = pw >= py ? uni.getSystemInfoSync().windowWidth -
imageWidth * p : 0;
const drawY = pw <= py ? uni.getSystemInfoSync().windowHeight -
imageHeight * p : 0;
ctx.drawImage(res.path, drawX / 2, drawY / 2, imageWidth * p,
imageHeight * p);
const multiple = 0.5;
ctx.fillStyle = 'rgba(255, 255, 255, 1.0)';
const x = 15 * multiple + drawX / 2; // 水印左上角 x 坐标
let y = 50 * multiple + drawY / 2; // 水印左上角 y 坐标
const lines = waterMarkInfo;
// 添加水印图标
// const lineHeight = 80; // 水印文字行高
ctx.setFontSize(40 * multiple);
ctx.fillText(lines[0], x, y);
// 绘制竖线
ctx.strokeStyle = 'yellow'; // 设置线条颜色为白色
ctx.lineWidth = 4 * multiple; // 设置线条宽度
ctx.beginPath(); // 开始路径
ctx.moveTo(x + multiple * 107, y - multiple * 30); // 移动到起点坐标 (x, y)
ctx.lineTo(x + multiple * 107, y); // 画一条竖线到终点坐标 (x, y)
ctx.stroke();
ctx.setFontSize(15 * multiple);
ctx.fillText(lines[1], x + multiple * 120, y - multiple * 20);
ctx.fillText(lines[2], x + multiple * 120, y);
y += multiple * 25;
const lineHeight = multiple * 25;
lines.forEach((line, index) => {
if (index >= 3) {
ctx.setFontSize(14 * multiple);
ctx.fillText(line, x, y);
y += lineHeight;
}
});
console.log("开始画", ctx)
ctx.draw(false, () => {
console.log("进来了")
uni.canvasToTempFilePath({
canvasId: "upload-canvas",
success: (res) => {
// resolve(res.tempFilePath)
let arr = res.tempFilePath.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
const blob = new Blob([u8arr], {
type: mime
});
const blobUrl = URL.createObjectURL(
blob);
setTimeout(() => resolve(blobUrl), 0)
},
fail: (error) => {
debugger
console.error('Failed to save canvas:',
error);
}
}, this);
});
// #endif
// #ifdef MP-WEIXIN
console.log(2, "123abc-tang")
let filePath = res?.path;
// 获取文件系统管理器
let canvas = wx.createOffscreenCanvas({
type: '2d',
width: imageWidth,
height: imageHeight
})
let img = canvas.createImage(); // 注意是使用canvas实例 不是ctx
// 等待图片加载
await new Promise(resolve => {
img.onload = resolve
img.src = filePath; // 要加载的图片 url
})
canvas.width = imageWidth;
canvas.height = imageHeight;
const ctx = canvas.getContext('2d')
ctx.drawImage(img, 0, 0, imageWidth, imageHeight);
const multiple = 2;
ctx.fillStyle = 'rgba(255, 255, 255, 1.0)';
const x = 15 * multiple; // 水印左上角 x 坐标
let y = 50 * multiple; // 水印左上角 y 坐标
const lines = waterMarkInfo;
// 添加水印图标
// const lineHeight = 80; // 水印文字行高
ctx.font = `
$
{
40
*
multiple
}
px
arial
`;
ctx.fillText(lines[0], x, y);
// 绘制竖线
ctx.strokeStyle = 'yellow'; // 设置线条颜色为白色
ctx.lineWidth = 4 * multiple; // 设置线条宽度
ctx.beginPath(); // 开始路径
ctx.moveTo(x + multiple * 107, y - multiple * 30); // 移动到起点坐标 (x, y)
ctx.lineTo(x + multiple * 107, y); // 画一条竖线到终点坐标 (x, y)
ctx.stroke();
ctx.font = `
$
{
15
*
multiple
}
px
arial
`;
ctx.fillText(lines[1], x + multiple * 120, y - multiple * 20);
ctx.fillText(lines[2], x + multiple * 120, y);
y += multiple * 25;
const lineHeight = multiple * 25;
lines.forEach((line, index) => {
if (index >= 3) {
ctx.font = `
$
{
14
*
multiple
}
px
arial
`;
ctx.fillText(line, x, y);
y += lineHeight;
}
});
uni.canvasToTempFilePath({
canvas: canvas,
x: 0,
y: 0,
width: imageWidth,
height: imageHeight,
destWidth: imageWidth,
destHeight: imageHeight,
// fileType: 'png', //目标文件类型,默认为png
// quality: 0.8, //图片的压缩质量, 仅对 jpg 有效
success: file => {
resolve(file.tempFilePath)
},
fail: e => {
reject({
code: -3,
msg: 'canvas转图片错误',
data: e
})
}
})
// 保存Canvas绘制结果为临时文件
// let base64 = canvas.toDataURL("image/png", 0.8);
// const time = new Date().getTime();
// const imgPath = wx.env.USER_DATA_PATH + "/poster" + time + "upload" +
// ".png";
//如果图片字符串不含要清空的前缀,可以不执行下行代码.
// const imageData = base64.replace(/^data:image\/\w+;base64,/, "");
// const fs = wx.getFileSystemManager();
// fs.writeFileSync(imgPath, imageData, "base64");
// fs.close()
// wx.getImageInfo({
// src: imgPath,
// success: (res) => {
// console.log(3, "123abc-tang")
// setTimeout(async () => {
// console.log("res.path", res.path)
// uni.getFileInfo({
// filePath: res.path,
// success: imgInfo => {
// console.log(
// "imgInfo.size",
// imgInfo
// .size)
// }
// })
// resolve(res.path)
// }, 0)
// },
// fail: (res) => {
// console.log("读取写入的文件失败", res)
// }
// })
// #endif
}
})
})
},
}
};
subpkg/abnormalEvent/abnormalEvent.vue
View file @
bf0b8600
...
...
@@ -345,8 +345,8 @@
const
nowDate
=
new
Date
(
timestamp
)
var
year
=
nowDate
.
getFullYear
();
var
month
=
nowDate
.
getMonth
()
<
10
?
'0'
+
(
nowDate
.
getMonth
()
+
1
)
:
nowDate
.
getMonth
()
+
1
;
var
date
=
nowDate
.
getDate
();
const
hour
=
nowDate
.
getHours
();
var
date
=
nowDate
.
getDate
()
<
10
?
'0'
+
nowDate
.
getDate
()
:
nowDate
.
getDate
()
;
const
hour
=
nowDate
.
getHours
()
<
10
?
'0'
+
nowDate
.
getHours
()
:
nowDate
.
getHours
()
;
const
minute
=
nowDate
.
getMinutes
()
<
10
?
'0'
+
nowDate
.
getMinutes
()
:
nowDate
.
getMinutes
()
;
var
seconds
=
nowDate
.
getSeconds
()
<
10
?
'0'
+
nowDate
.
getSeconds
()
:
nowDate
.
getSeconds
();
if
(
this
.
dateType
===
'date'
)
{
...
...
subpkg/abnormalEventDetail/abnormalEventDetail.vue
View file @
bf0b8600
...
...
@@ -295,6 +295,8 @@
const
allData
=
getApp
().
globalData
.
all
;
//所有的明细
var
totle
=
0
;
if
(
allData
.
length
>
0
){
console
.
log
(
'222========='
)
console
.
log
(
allData
.
length
)
allData
.
map
(
item
=>
{
//费用项+币种是唯一的
if
(
item
.
rate_item
==
this
.
formData
.
rate_item
&&
item
.
currency
==
this
.
formData
.
currency
){
...
...
@@ -419,9 +421,6 @@
const
aa
=
[
'940507a5acc6ed1771b8f411d749d20586f96ac6.pdf'
,
]
console
.
log
(
'111================='
)
console
.
log
(
aa
)
console
.
log
(
datas
)
uni
.
showLoading
({
title
:
'下载中'
,
})
...
...
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