This commit is contained in:
hongchao 2025-08-31 11:04:13 +08:00
commit 848e0c6456
9 changed files with 258 additions and 49 deletions

View File

@ -1,17 +1,18 @@
<template> <template>
<view <view
class="whole canvas-autograph flexc" class="whole canvas-autograph flex"
@touchmove.prevent.stop @touchmove.prevent.stop
@wheel.prevent.stop @wheel.prevent.stop
v-show="modelValue" v-show="modelValue"
style="overflow: hidden"
> >
<canvas <canvas
class="scroll-view" class="scroll-view"
id="mycanvas" id="mycanvas"
canvas-id="mycanvas" canvas-id="mycanvas"
@touchstart="touchstart" @touchstart.prevent.stop="touchstart"
@touchmove="touchmove" @touchmove.prevent.stop="touchmove"
@touchend="touchend" @touchend.prevent.stop="touchend"
disable-scroll="true" disable-scroll="true"
/> />
<view class="fun-box"> <view class="fun-box">
@ -38,6 +39,7 @@
<script setup> <script setup>
import { ref, reactive, watch, getCurrentInstance } from 'vue' import { ref, reactive, watch, getCurrentInstance } from 'vue'
import { useMemberStore } from '@/stores'
const emits = defineEmits(['update:modelValue', 'complete']) const emits = defineEmits(['update:modelValue', 'complete'])
const props = defineProps({ const props = defineProps({
@ -57,46 +59,157 @@ let hasDrawn = ref(false)
// //
const showToast = ref(false) const showToast = ref(false)
const toastMsg = ref('') const toastMsg = ref('')
const memberStore = useMemberStore()
console.log('🚀 ~ memberStore:', memberStore.userInfo.nickName)
const nickName = ref('')
if (memberStore.userInfo.nickName && memberStore.userInfo.nickName.length < 5) {
nickName.value = memberStore.userInfo.nickName.split('').join(' ')
console.log('🚀 ~ nickName.value:', nickName.value)
} else {
nickName.value = '正楷字书写'
}
const paths = ref([]) //
const PEN = { width: 6, color: '#000000' } //
watch(
() => props.modelValue,
(val) => {
if (val) {
// canvas
setTimeout(() => {
uni
.createSelectorQuery()
.in(_this)
.select('#mycanvas')
.fields({ size: true, rect: true }, (data) => {
if (data) {
const { width, height } = data
drawBackground(canvaCtx, width, height)
}
})
.exec()
}, 50) // 30~100ms
}
},
)
const showRotateToast = (msg) => { const showRotateToast = (msg) => {
toastMsg.value = msg toastMsg.value = msg
showToast.value = true showToast.value = true
setTimeout(() => (showToast.value = false), 2000) setTimeout(() => (showToast.value = false), 2000)
} }
// +
const drawBackground = (ctx, width = 100, height = 100) => {
ctx.save()
ctx.setStrokeStyle('#e0e0e0')
ctx.setLineWidth(1)
const gridSize = 120
//
for (let y = gridSize; y < height; y += gridSize) {
ctx.moveTo(0, y)
ctx.lineTo(width, y)
}
for (let x = gridSize; x < width; x += gridSize) {
ctx.moveTo(x, 0)
ctx.lineTo(x, height)
}
//
for (let x = 0; x < width; x += gridSize) {
for (let y = 0; y < height; y += gridSize) {
ctx.moveTo(x, y)
ctx.lineTo(x + gridSize, y + gridSize)
ctx.moveTo(x + gridSize, y)
ctx.lineTo(x, y + gridSize)
}
}
ctx.stroke()
//
const fontSize = nickName.value.length == 5 ? 140 : 190
ctx.setFontSize(fontSize)
ctx.setFillStyle('rgba(180,180,180,0.25)')
ctx.setTextAlign('center')
ctx.setTextBaseline('middle')
ctx.translate(width / 2, height / 2)
ctx.rotate(Math.PI / 2)
ctx.fillText(nickName.value, 0, 0)
ctx.restore()
// draw()
ctx.draw(false, () => {
console.log('背景绘制完成')
})
}
// //
const touchstart = (e) => { const touchstart = (e) => {
let startX = e.changedTouches[0].x const x = e.changedTouches[0].x
let startY = e.changedTouches[0].y const y = e.changedTouches[0].y
let startPoint = { X: startX, Y: startY } const p = { X: x, Y: y }
points.push(startPoint)
//
paths.value.push([p])
// 便
canvaCtx.setLineWidth(PEN.width)
canvaCtx.setStrokeStyle(PEN.color)
canvaCtx.setLineCap('round')
canvaCtx.setLineJoin('round')
canvaCtx.beginPath() canvaCtx.beginPath()
hasDrawn.value = true // canvaCtx.moveTo(x, y)
} // 线
// canvaCtx.lineTo(x + 0.1, y + 0.1)
const touchmove = (e) => {
let moveX = e.changedTouches[0].x
let moveY = e.changedTouches[0].y
let movePoint = { X: moveX, Y: moveY }
points.push(movePoint)
if (points.length >= 2) {
draw()
}
}
//
const draw = () => {
if (points.length < 2) return
canvaCtx.beginPath()
canvaCtx.moveTo(points[0].X, points[0].Y)
for (let i = 1; i < points.length; i++) {
canvaCtx.lineTo(points[i].X, points[i].Y)
}
canvaCtx.stroke() canvaCtx.stroke()
canvaCtx.draw(true) canvaCtx.draw(true)
points = [points[points.length - 1]]
} }
//
let isDrawing = false
let lastMoveTime = 0
const throttleInterval = 6 // 50ms
const touchmove = (e) => {
const now = Date.now()
if (now - lastMoveTime > throttleInterval) {
lastMoveTime = now
const x = e.changedTouches[0].x
const y = e.changedTouches[0].y
const p = { X: x, Y: y }
const cur = paths.value[paths.value.length - 1]
if (cur) cur.push(p)
if (cur && cur.length >= 2) {
const prev = cur[cur.length - 2]
canvaCtx.setLineWidth(PEN.width)
canvaCtx.setStrokeStyle(PEN.color)
canvaCtx.setLineCap('round')
canvaCtx.setLineJoin('round')
canvaCtx.beginPath()
canvaCtx.moveTo(prev.X, prev.Y)
canvaCtx.lineTo(p.X, p.Y)
canvaCtx.stroke()
//
if (!isDrawing) {
isDrawing = true
canvaCtx.draw(true, () => {
isDrawing = false //
})
}
}
}
}
const touchend = () => { const touchend = () => {
// paths便 points points
points = [] points = []
hasDrawn.value = paths.value.length > 0
} }
// //
const clear = () => { const clear = () => {
@ -111,25 +224,95 @@ const clear = () => {
return return
} }
const { width, height } = data const { width, height } = data
//
canvaCtx.clearRect(0, 0, width, height) canvaCtx.clearRect(0, 0, width, height)
canvaCtx.draw(true) // flush drawBackground ctx.draw
canvaCtx.draw(false, () => {
// drawBackground ctx.draw
drawBackground(canvaCtx, width, height)
//
paths.value = []
hasDrawn.value = false hasDrawn.value = false
resolve() resolve()
}) })
})
.exec() .exec()
}) })
} }
// //
const confirm = () => { const confirm = () => {
if (!hasDrawn.value) { if (!hasDrawn.value) {
showRotateToast('请先签名再确认') showRotateToast('请先签名再确认')
return return
} }
uni.canvasToTempFilePath({ canvasId: 'mycanvas' }, _this, _this.parent).then((res) => {
uni
.createSelectorQuery()
.in(_this)
.select('#mycanvas')
.fields({ size: true, rect: true }, (data) => {
if (!data) return
const { width, height } = data
// 1)
canvaCtx.clearRect(0, 0, width, height)
// 2)
canvaCtx.setLineWidth(PEN.width)
canvaCtx.setStrokeStyle(PEN.color)
canvaCtx.setLineCap('round')
canvaCtx.setLineJoin('round')
canvaCtx.setFillStyle(PEN.color)
paths.value.forEach((path) => {
if (!path || !path.length) return
if (path.length === 1) {
//
const p = path[0]
canvaCtx.beginPath()
canvaCtx.arc(p.X, p.Y, Math.max(1, PEN.width / 2), 0, Math.PI * 2)
canvaCtx.fill()
} else {
canvaCtx.beginPath()
canvaCtx.moveTo(path[0].X, path[0].Y)
for (let i = 1; i < path.length; i++) {
canvaCtx.lineTo(path[i].X, path[i].Y)
}
canvaCtx.stroke()
}
})
// 3) flush
canvaCtx.draw(false, () => {
uni
.canvasToTempFilePath(
{
canvasId: 'mycanvas',
width,
height,
destWidth: width,
destHeight: height,
fileType: 'png',
quality: 1,
},
_this,
_this.parent,
)
.then((res) => {
emits('complete', res.tempFilePath) emits('complete', res.tempFilePath)
//
cancel() cancel()
}) })
.catch((err) => {
console.error('导出签名失败', err)
showRotateToast('导出失败,请重试')
})
})
})
.exec()
} }
// //
const cancel = () => { const cancel = () => {
clear().then(() => emits('update:modelValue', false)) clear().then(() => emits('update:modelValue', false))

View File

@ -288,6 +288,7 @@ const submitNum = () => {
"backApplyInfo":taskInfo.value, "backApplyInfo":taskInfo.value,
"backApplyDetailsList":typeList.value "backApplyDetailsList":typeList.value
} }
if (obj.backApplyInfo.signUrl) delete obj.backApplyInfo.signUrl
insertApp(obj).then(res => { insertApp(obj).then(res => {
console.log(res) console.log(res)
if(res.code==200){ if(res.code==200){

View File

@ -178,6 +178,8 @@ const pluginCheckRetries = ref(0)
const maxRetries = ref(5) const maxRetries = ref(5)
const focusTimeout = ref(null) const focusTimeout = ref(null)
const systemInfo = ref(null) const systemInfo = ref(null)
const screenHeight=ref(null)
const screenWidth=ref(null)
const currentDate = ref('') const currentDate = ref('')
const minDate = ref('') const minDate = ref('')
@ -263,6 +265,11 @@ const getDeviceInfo = () => {
const systemInfoData = uni.getSystemInfoSync(); const systemInfoData = uni.getSystemInfoSync();
console.log('设备信息:', systemInfoData); console.log('设备信息:', systemInfoData);
systemInfo.value = systemInfoData; systemInfo.value = systemInfoData;
//
const screenHeight = systemInfoData.screenHeight;
const screenWidth = systemInfoData.screenWidth;
this.screenHeight = screenHeight;
this.screenWidth = screenWidth;
} catch (error) { } catch (error) {
console.error('获取设备信息失败:', error); console.error('获取设备信息失败:', error);
} }
@ -639,7 +646,7 @@ const takePicture = async () => {
if (!CameraPreview) { if (!CameraPreview) {
throw new Error('相机插件不可用'); throw new Error('相机插件不可用');
} }
CameraPreview.takePicture({width:640, height:540, quality: 50}, async (base64PictureData) => { CameraPreview.takePicture({width:this.screenWidth, height:this.screenHeight, quality: 50}, async (base64PictureData) => {
console.log('拍照返回数据',base64PictureData); console.log('拍照返回数据',base64PictureData);
await processImage(base64PictureData); await processImage(base64PictureData);
}); });

View File

@ -179,7 +179,9 @@ export default {
focusTimeout: null, focusTimeout: null,
// //
systemInfo: null, systemInfo: null,
isOverToday: false isOverToday: false,
screenHeight: null,
screenWidth: null,
} }
}, },
onBackPress(options) { onBackPress(options) {
@ -230,6 +232,11 @@ export default {
const systemInfo = uni.getSystemInfoSync(); const systemInfo = uni.getSystemInfoSync();
console.log('设备信息:', systemInfo); console.log('设备信息:', systemInfo);
this.systemInfo = systemInfo; this.systemInfo = systemInfo;
//
const screenHeight = systemInfo.screenHeight; // 1000
const screenWidth = systemInfo.screenWidth; // 600
this.screenHeight = screenHeight;
this.screenWidth = screenWidth;
} catch (error) { } catch (error) {
console.error('获取设备信息失败:', error); console.error('获取设备信息失败:', error);
} }
@ -510,7 +517,7 @@ export default {
// //
console.log('拍照前聚焦...'); console.log('拍照前聚焦...');
console.log('开始拍照...'); console.log('开始拍照...');
CameraPreview.takePicture({width:640, height:540, quality: 50}, async (base64PictureData) => { CameraPreview.takePicture({width:this.screenWidth, height:this.screenHeight, quality: 50}, async (base64PictureData) => {
console.log('拍照返回数据',base64PictureData); console.log('拍照返回数据',base64PictureData);
await this.processImage(base64PictureData); await this.processImage(base64PictureData);
}); });

View File

@ -34,6 +34,7 @@ import { ref } from 'vue'
import { getInfoByIdApi } from '@/services/materialsStation' import { getInfoByIdApi } from '@/services/materialsStation'
const itemId = ref(null) const itemId = ref(null)
const publishTask = ref(null)
const tableList = ref([]) const tableList = ref([])
onShow(() => { onShow(() => {
@ -43,6 +44,7 @@ onShow(() => {
onLoad((opt) => { onLoad((opt) => {
console.log('🚀 ~ onLoad ~ opt:', opt) console.log('🚀 ~ onLoad ~ opt:', opt)
itemId.value = opt.id itemId.value = opt.id
publishTask.value = opt.publishTask
console.log('🚀 ~ itemId.value:', itemId.value) console.log('🚀 ~ itemId.value:', itemId.value)
// getList() // getList()
}) })
@ -54,7 +56,7 @@ const onScrollTolower = () => {
const getList = async () => { const getList = async () => {
try { try {
const res = await getInfoByIdApi({ id: itemId.value }) const res = await getInfoByIdApi({ id: itemId.value, publishTask: publishTask.value })
tableList.value = res.data tableList.value = res.data
} catch (error) { } catch (error) {
console.log('🚀 ~ getList ~ error:', error) console.log('🚀 ~ getList ~ error:', error)

View File

@ -116,7 +116,7 @@ const getList = async () => {
const handleDetails = (item) => { const handleDetails = (item) => {
console.log('🚀 ~ handleDetails ~ item:', item) console.log('🚀 ~ handleDetails ~ item:', item)
uni.navigateTo({ uni.navigateTo({
url: `/pages/materialsStation/materialClerkConfirms/detailsList?id=${item.id}`, url: `/pages/materialsStation/materialClerkConfirms/detailsList?id=${item.id}&publishTask=${item.publishTask}`,
}) })
} }
</script> </script>

View File

@ -176,9 +176,11 @@ const boxInBound = async () => {
confirmText: '确定', confirmText: '确定',
cancelText: '取消', cancelText: '取消',
success: async (res) => { success: async (res) => {
if (res.confirm) {
if (boxInfo.value.successMaTotal > 0) { if (boxInfo.value.successMaTotal > 0) {
confirmBoxInBound() confirmBoxInBound()
} }
}
}, },
}) })
} else { } else {

View File

@ -76,12 +76,12 @@
</div> </div>
</div> </div>
<view class="line"></view> <view class="line"></view>
<!-- <uni-row :gutter="24"> <uni-row :gutter="24">
<uni-col :span="8">入库单号</uni-col> <uni-col :span="8">退料单号</uni-col>
<uni-col :span="16"> <uni-col :span="16">
<view class="cont">{{ item.inputCode }}</view> <view class="cont">{{ item.backCode }}</view>
</uni-col> </uni-col>
</uni-row> --> </uni-row>
<uni-row :gutter="24"> <uni-row :gutter="24">
<uni-col :span="8">维修单号</uni-col> <uni-col :span="8">维修单号</uni-col>
<uni-col :span="16"> <uni-col :span="16">

View File

@ -174,6 +174,8 @@ const pluginCheckRetries = ref(0)
const maxRetries = ref(5) const maxRetries = ref(5)
const focusTimeout = ref(null) const focusTimeout = ref(null)
const systemInfo = ref(null) const systemInfo = ref(null)
const screenHeight = ref(null)
const screenWidth = ref(null)
const getCodeList = () => { const getCodeList = () => {
console.log(boxInfo.value) console.log(boxInfo.value)
@ -351,6 +353,11 @@ const getDeviceInfo = () => {
const systemInfoData = uni.getSystemInfoSync(); const systemInfoData = uni.getSystemInfoSync();
console.log('设备信息:', systemInfoData); console.log('设备信息:', systemInfoData);
systemInfo.value = systemInfoData; systemInfo.value = systemInfoData;
//
const screenHeight = systemInfoData.screenHeight; // 1000
const screenWidth = systemInfoData.screenWidth; // 600
this.screenHeight = screenHeight;
this.screenWidth = screenWidth;
} catch (error) { } catch (error) {
console.error('获取设备信息失败:', error); console.error('获取设备信息失败:', error);
} }
@ -523,7 +530,7 @@ const takePicture = async () => {
if (!CameraPreview) { if (!CameraPreview) {
throw new Error('相机插件不可用'); throw new Error('相机插件不可用');
} }
CameraPreview.takePicture({width:640, height:540, quality: 50}, async (base64PictureData) => { CameraPreview.takePicture({width:this.screenWidth, height:this.screenHeight, quality: 50}, async (base64PictureData) => {
console.log('拍照返回数据',base64PictureData); console.log('拍照返回数据',base64PictureData);
await processImage(base64PictureData); await processImage(base64PictureData);
}); });