数据库: - 新增 odf_checkin/odf_cables/odf_cable_faults/odf_cable_fault_images/odf_user_modules 5张表 - 新增菜单权限和角色分配 SQL 脚本 后台 API (.NET/SqlSugar): - 新增实体模型、DTO、Service、Controller (签到/光缆/故障/图片/用户模块) 前端 APP (UniApp): - 新增 portal/checkin/trunk/cable/fault-list/fault-detail/fault-add/trunk-search/route-plan 9个页面 - 新增 permission/checkin/trunk 服务层 - 新增 navigation/watermark 工具函数 后台管理前端 (ZR.Vue): - 新增光缆管理/干线故障管理/签到记录管理/用户模块权限 4个管理页面 - 新增对应 API 模块和表单组件
109 lines
3.4 KiB
JavaScript
109 lines
3.4 KiB
JavaScript
/**
|
||
* 在照片左下角叠加水印文字
|
||
* @param {string} imagePath - 原始图片路径
|
||
* @param {string} text - 水印文字(如 "2025/06/15 12:00 张三")
|
||
* @returns {Promise<string>} 带水印的临时文件路径
|
||
*/
|
||
export function addWatermark(imagePath, text) {
|
||
return new Promise((resolve, reject) => {
|
||
uni.getImageInfo({
|
||
src: imagePath,
|
||
success(imgInfo) {
|
||
const canvasId = 'watermarkCanvas'
|
||
const width = imgInfo.width
|
||
const height = imgInfo.height
|
||
|
||
// 使用 OffscreenCanvas(APP-PLUS 和 H5 均支持)
|
||
// #ifdef APP-PLUS
|
||
const bitmap = new plus.nativeObj.Bitmap('watermark')
|
||
bitmap.load(imagePath, () => {
|
||
const canvas = new plus.nativeObj.View('watermarkView', {
|
||
left: '0px', top: '0px',
|
||
width: width + 'px', height: height + 'px'
|
||
})
|
||
|
||
// 绘制原图
|
||
canvas.drawBitmap(bitmap, {}, { left: '0px', top: '0px', width: width + 'px', height: height + 'px' })
|
||
|
||
// 水印参数
|
||
const fontSize = Math.max(Math.floor(width * 0.03), 14)
|
||
const padding = Math.floor(fontSize * 0.8)
|
||
const textX = padding
|
||
const textY = height - padding
|
||
|
||
// 绘制半透明背景
|
||
const bgHeight = fontSize + padding * 2
|
||
canvas.drawRect(
|
||
{ color: 'rgba(0,0,0,0.4)' },
|
||
{ left: '0px', top: (height - bgHeight) + 'px', width: width + 'px', height: bgHeight + 'px' }
|
||
)
|
||
|
||
// 绘制水印文字
|
||
canvas.drawText(text, {
|
||
left: textX + 'px',
|
||
top: (height - bgHeight + padding) + 'px',
|
||
width: (width - textX * 2) + 'px',
|
||
height: fontSize + 'px'
|
||
}, {
|
||
size: fontSize + 'px',
|
||
color: '#ffffff'
|
||
})
|
||
|
||
// 导出
|
||
const tempPath = `_doc/watermark_${Date.now()}.jpg`
|
||
canvas.toBitmap(tempPath, {}, () => {
|
||
bitmap.clear()
|
||
resolve(tempPath)
|
||
}, (err) => {
|
||
bitmap.clear()
|
||
reject(err)
|
||
})
|
||
}, (err) => {
|
||
reject(err)
|
||
})
|
||
// #endif
|
||
|
||
// #ifndef APP-PLUS
|
||
// H5 / 小程序端使用 Canvas 2D
|
||
const canvas = uni.createOffscreenCanvas({ type: '2d', width, height })
|
||
const ctx = canvas.getContext('2d')
|
||
const img = canvas.createImage()
|
||
|
||
img.onload = () => {
|
||
// 绘制原图
|
||
ctx.drawImage(img, 0, 0, width, height)
|
||
|
||
// 水印参数
|
||
const fontSize = Math.max(Math.floor(width * 0.03), 14)
|
||
const padding = Math.floor(fontSize * 0.8)
|
||
|
||
// 绘制半透明背景
|
||
const bgHeight = fontSize + padding * 2
|
||
ctx.fillStyle = 'rgba(0,0,0,0.4)'
|
||
ctx.fillRect(0, height - bgHeight, width, bgHeight)
|
||
|
||
// 绘制水印文字
|
||
ctx.fillStyle = '#ffffff'
|
||
ctx.font = `${fontSize}px sans-serif`
|
||
ctx.textBaseline = 'middle'
|
||
ctx.fillText(text, padding, height - bgHeight / 2)
|
||
|
||
// 导出为临时文件
|
||
const tempFilePath = canvas.toDataURL('image/jpeg', 0.9)
|
||
resolve(tempFilePath)
|
||
}
|
||
|
||
img.onerror = (err) => {
|
||
reject(err || new Error('图片加载失败'))
|
||
}
|
||
|
||
img.src = imagePath
|
||
// #endif
|
||
},
|
||
fail(err) {
|
||
reject(err)
|
||
}
|
||
})
|
||
})
|
||
}
|