优化
This commit is contained in:
283
pagesMine/audit.vue
Normal file
283
pagesMine/audit.vue
Normal file
@@ -0,0 +1,283 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
<z-paging ref="pagingRef" class="containerBox" v-model="listData" :default-page-size="queryParams.pageSize" @query="queryList">
|
||||
<template #top>
|
||||
<!-- 项目号/项目描述/物料号/物料描述/供应商编码/供应商名称/订单编号 -->
|
||||
<uv-search v-model="queryParams.keyword" placeholder="请输入" :showAction="true" actionText="搜索" @search="searchList" @custom="searchList"></uv-search>
|
||||
<uv-drop-down ref="dropDown" sign="dropDown_1" text-active-color="#3c9cff"
|
||||
:extra-icon="{ name: 'arrow-down-fill', color: '#666', size: '26rpx' }"
|
||||
:extra-active-icon="{ name: 'arrow-up-fill', color: '#3c9cff', size: '26rpx' }" :defaultValue="defaultValue"
|
||||
:custom-style="{ padding: '0 30rpx' }" @click="selectMenu">
|
||||
<uv-drop-down-item name="billType" type="2" :label="dropItem('billType').label" :value="dropItem('billType').value">
|
||||
</uv-drop-down-item>
|
||||
</uv-drop-down>
|
||||
<uv-drop-down-popup sign="dropDown_1" :click-overlay-on-close="true" :currentDropItem="currentDropItem"
|
||||
@clickItem="clickItem" @popupChange="change"></uv-drop-down-popup>
|
||||
</template>
|
||||
|
||||
|
||||
<view class="box">
|
||||
<view v-for="item in listData" class="item" @tap="goDetail(item)">
|
||||
<!-- <uv-icon name="file-text" size="36rpx" style="margin-top: 4rpx;" @tap="itemCopy(item)"></uv-icon> -->
|
||||
<view class="title">单据号:{{ item.billNo }}</view>
|
||||
<view v-show="item.billType == 0"><text>入库类型</text>:{{ item.rkTypeName }}</view>
|
||||
<view v-show="item.billType == 1"><text>出库类型</text>:{{ item.ckTypeName }}</view>
|
||||
<view><text>所属仓库:</text>{{ item.cangkuName }}</view>
|
||||
<view><text>物资类型:</text>{{ item.wlTypeName }}</view>
|
||||
<view><text>理货员:</text>{{ item.lihuoYName }}</view>
|
||||
<view><text>提交时间:</text>{{ parseTime(item.createTime) }}</view>
|
||||
<view class="statusBtn">{{ typeItem('billType', parseInt(item.billType)) }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
</z-paging>
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed } from "vue";
|
||||
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app";
|
||||
import { auditList } from "@/api/mine"
|
||||
|
||||
// *****下拉筛选
|
||||
// 默认值
|
||||
const defaultValue = ref([]);
|
||||
// 选择结果
|
||||
const result = ref([{ name: 'billType', label: '全部', value: '' }]);
|
||||
const activeName = ref('');
|
||||
// 筛选条件配置
|
||||
const billType = ref({
|
||||
label: '文档格式',
|
||||
value: '',
|
||||
activeIndex: 0,
|
||||
color: '#333',
|
||||
activeColor: '#2878ff',
|
||||
child: [{
|
||||
label: '全部',
|
||||
value: ''
|
||||
}, {
|
||||
label: '入库',
|
||||
value: 0
|
||||
}, {
|
||||
label: '出库',
|
||||
value: 1
|
||||
}]
|
||||
});
|
||||
// 计算属性
|
||||
const dropItem = computed(() => {
|
||||
return (name) => {
|
||||
const resultObj = {};
|
||||
const find = result.value.find(item => item.name === name);
|
||||
if (find) {
|
||||
resultObj.label = find.label;
|
||||
resultObj.value = find.value;
|
||||
} else {
|
||||
resultObj.label = getPropertyByName(name).label;
|
||||
resultObj.value = getPropertyByName(name).value;
|
||||
}
|
||||
return resultObj;
|
||||
}
|
||||
});
|
||||
|
||||
const currentDropItem = computed(() => {
|
||||
return getPropertyByName(activeName.value);
|
||||
});
|
||||
|
||||
// 工具函数:根据名称获取对应的响应式对象
|
||||
function getPropertyByName(name) {
|
||||
switch (name) {
|
||||
case 'billType': return billType.value;
|
||||
default: return {};
|
||||
}
|
||||
}
|
||||
|
||||
// 生命周期钩子
|
||||
onPageScroll(() => {
|
||||
// 滚动后及时更新位置
|
||||
dropDown.value?.init();
|
||||
});
|
||||
|
||||
const selectMenu = (e) => {
|
||||
const { name, active, type } = e;
|
||||
activeName.value = name;
|
||||
|
||||
// type 等于1 的需要特殊处理:type不等于1可以忽略
|
||||
if (type == 1) {
|
||||
clickItem({
|
||||
name: 'vip_type',
|
||||
label: 'VIP文档',
|
||||
value: e.active ? 1 : 0
|
||||
});
|
||||
} else {
|
||||
const find = result.value.find(item => item.name == activeName.value);
|
||||
if (find) {
|
||||
const findIndex = getPropertyByName(activeName.value).child.findIndex(item =>
|
||||
item.label == find.label && item.value == find.value
|
||||
);
|
||||
getPropertyByName(activeName.value).activeIndex = findIndex;
|
||||
} else {
|
||||
getPropertyByName(activeName.value).activeIndex = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const clickItem = (e) => {
|
||||
// 下面有重新赋值,所以用let
|
||||
let { label, value } = e;
|
||||
const findIndex = result.value.findIndex(item => item.name == activeName.value);
|
||||
|
||||
if (defaultValue.value.indexOf(value) > -1 && getPropertyByName(activeName.value).label) {
|
||||
label = getPropertyByName(activeName.value).label;
|
||||
}
|
||||
|
||||
// 已经存在筛选项
|
||||
if (findIndex > -1) {
|
||||
result.value[findIndex] = {
|
||||
name: activeName.value,
|
||||
label,
|
||||
value
|
||||
}
|
||||
} else {
|
||||
result.value.push({
|
||||
name: activeName.value,
|
||||
label,
|
||||
value
|
||||
});
|
||||
}
|
||||
|
||||
result.value = result.value.filter(item => defaultValue.value.indexOf(item.value) == -1);
|
||||
|
||||
result.value.forEach(item=> {
|
||||
queryParams.value[item.name] = item.value
|
||||
})
|
||||
pagingRef.value.reload()
|
||||
console.log("筛选的值:", queryParams.value)
|
||||
};
|
||||
|
||||
const change = (e) => {
|
||||
console.log('弹窗打开状态:', e);
|
||||
}
|
||||
|
||||
// 获取到对应的入/出库
|
||||
const typeItem = (name, value) => {
|
||||
const scanTypeObj = getPropertyByName(name);
|
||||
if (scanTypeObj && scanTypeObj.child) {
|
||||
const item = scanTypeObj.child.find(item => item.value === value);
|
||||
return item ? item.label : null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
const queryParams = ref({
|
||||
keyword: "",
|
||||
approverId: uni.getStorageSync('user').userId,
|
||||
auditResult: 2,
|
||||
billType: "",
|
||||
pageNum: 1,
|
||||
pageSize: 10
|
||||
})
|
||||
const pagingRef = ref(null)
|
||||
const listData = ref([])
|
||||
// 获取列表
|
||||
const queryList = (pageNo, pageSize) => {
|
||||
queryParams.value.pageNum = pageNo
|
||||
console.log(pageNo, pageSize, queryParams.value)
|
||||
auditList(queryParams.value).then(res => {
|
||||
console.log(res.rows)
|
||||
pagingRef.value.complete(res.rows)
|
||||
}).catch(res => {
|
||||
pagingRef.value.complete(false)
|
||||
})
|
||||
}
|
||||
const searchList = () => {
|
||||
pagingRef.value.reload()
|
||||
}
|
||||
|
||||
onLoad(() => {
|
||||
})
|
||||
|
||||
onShow(() => {
|
||||
pagingRef.value?.reload()
|
||||
})
|
||||
|
||||
const goDetail = (item) => {
|
||||
uni.navigateTo({
|
||||
url: "/pagesMine/auditDetail",
|
||||
success: res => {
|
||||
res.eventChannel.emit('auditInfo',{info:item})
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
position: relative;
|
||||
.containerBox{
|
||||
padding: 32rpx;
|
||||
.dropDown{
|
||||
padding: 0 30rpx;
|
||||
border-bottom: 1px solid #dadbde;
|
||||
.item_dropDown{
|
||||
padding: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
::v-deep .uv-text{
|
||||
width: unset !important;
|
||||
flex: unset !important;
|
||||
}
|
||||
::v-deep .item_text{
|
||||
max-width: 200rpx;
|
||||
margin-right: 10rpx !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
::v-deep .uv-search {
|
||||
flex: unset;
|
||||
}
|
||||
.box{
|
||||
// background-color: #ebebeb;
|
||||
// background-color: #f5f5f5;
|
||||
// padding-top: 20rpx;
|
||||
.item {
|
||||
background: #efefef;
|
||||
padding: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
line-height: 50rpx;
|
||||
font-size: 28rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #333;
|
||||
position: relative;
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
text{
|
||||
color: #666;
|
||||
}
|
||||
.statusBtn {
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
right: 10rpx;
|
||||
background-color: #199793;
|
||||
color: white;
|
||||
padding: 0 10rpx;
|
||||
border-radius: 4rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
::v-deep .uv-input__content{
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
208
pagesMine/auditDetail.vue
Normal file
208
pagesMine/auditDetail.vue
Normal file
@@ -0,0 +1,208 @@
|
||||
<template>
|
||||
<view class="container">
|
||||
|
||||
<view v-show="detailData.billType == 0"><text>入库类型</text>:{{ detailData.rkTypeName }}</view>
|
||||
<view v-show="detailData.billType == 1"><text>出库类型</text>:{{ detailData.ckTypeName }}</view>
|
||||
<view><text>所属仓库:</text>{{ detailData.cangkuName }}</view>
|
||||
<view><text>物资类型:</text>{{ detailData.wlTypeName }}</view>
|
||||
<view><text>理货员:</text>{{ detailData.lihuoYName }}</view>
|
||||
<view><text>入库时间:</text>{{ parseTime(detailData.createTime) }}</view>
|
||||
<view class="box">
|
||||
<view v-for="item in detailData.scenePhotos" class="item">
|
||||
<view><text>项目描述:</text>{{ item.xmMs }}</view>
|
||||
<view><text>供应商:</text>{{ item.gysMc }}</view>
|
||||
<view><text>物料号:</text>{{ item.wlNo }}</view>
|
||||
<view><text>物料描述:</text>{{ item.wlMs }}</view>
|
||||
<view><text>数量:</text>{{ item.realQty }}{{ item.dw }}</view>
|
||||
<view><text>项目定义号:</text>{{ item.xmNo }}</view>
|
||||
<view><text>存放位置:</text>{{ item.pcode || "-" }}</view>
|
||||
<!-- <view><text>身份码:</text>{{ item.entityId || "-" }}</view> -->
|
||||
<view><text>备注:</text>{{ item.rkRemark || "-" }}</view>
|
||||
<view><text>现场照片:</text><uv-image height="80" mode="heightFix" @tap="previewImage(item.signUrl)" :src="item.signUrl"></uv-image></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="btn">
|
||||
<uv-button type="error" text="确定" size="large" style="width: 48%;" @tap="openModal(0)">驳 回</uv-button>
|
||||
<uv-button type="primary" text="确定" size="large" class="mainBtn" style="width: 48%;" @tap="openModal(1)">同 意</uv-button>
|
||||
</view>
|
||||
|
||||
|
||||
|
||||
<uv-modal ref="auditModalRef" title="审批信息" @confirm="auditConfirm" :showCancelButton="true" :closeOnClickOverlay="false" asyncClose>
|
||||
<view class="slot-content" style="width: 100%;">
|
||||
<uv-form labelPosition="top" :model="auditForm" labelWidth="80" :rules="auditRules" ref="auditFormRef">
|
||||
<uv-form-item label="签字" prop="approverSignUrl" borderBottom v-if="auditStatus == 1">
|
||||
<uv-button text="去签名" v-if="!auditForm.approverSignUrl" @tap="goSign"></uv-button>
|
||||
<uv-image height="80" mode="heightFix" v-if="auditForm.approverSignUrl" @tap="previewImage(auditForm.approverSignUrl)" :src="auditForm.approverSignUrl"></uv-image>
|
||||
</uv-form-item>
|
||||
<uv-form-item label="备注" prop="remark" borderBottom>
|
||||
<uv-textarea v-model="auditForm.remark" placeholder="备注" />
|
||||
</uv-form-item>
|
||||
</uv-form>
|
||||
</view>
|
||||
</uv-modal>
|
||||
|
||||
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, getCurrentInstance, onUnmounted } from "vue";
|
||||
import { onLoad, onShow, onPageScroll } from "@dcloudio/uni-app";
|
||||
import { passedAudit } from "@/api/mine"
|
||||
|
||||
const instance = getCurrentInstance().proxy
|
||||
|
||||
const detailData = ref({})
|
||||
onLoad(() => {
|
||||
const eventChannel = instance.getOpenerEventChannel();
|
||||
// 监听redactInfo事件,获取上一页面通过eventChannel传送到当前页面的数据
|
||||
eventChannel.on('auditInfo', function(data) {
|
||||
detailData.value = data.info
|
||||
console.log("获取到信息", data.info)
|
||||
});
|
||||
})
|
||||
|
||||
// 预览
|
||||
const previewImage = (img) => {
|
||||
let arr = []
|
||||
arr.push(img)
|
||||
uni.previewImage({
|
||||
urls: arr,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const auditModalRef = ref(null)
|
||||
const auditFormRef = ref(null)
|
||||
const auditStatus = ref(0)
|
||||
const openModal = (status) => {
|
||||
auditForm.value.approverSignUrl = ""
|
||||
auditForm.value.remark = ""
|
||||
auditStatus.value = status
|
||||
auditModalRef.value.open();
|
||||
}
|
||||
const auditForm = ref({
|
||||
approverSignUrl: "",
|
||||
remark: '',
|
||||
})
|
||||
const auditRules = computed(() => ({
|
||||
'approverSignUrl': {
|
||||
type: 'string',
|
||||
required: auditStatus.value == 1,
|
||||
message: '请手写签字',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
'remark': {
|
||||
type: 'string',
|
||||
required: auditStatus.value == 0,
|
||||
message: '请填写备注',
|
||||
trigger: ['blur', 'change']
|
||||
},
|
||||
}));
|
||||
|
||||
// 去签名页面
|
||||
const goSign = () => {
|
||||
// 移除之前的事件监听器避免重复
|
||||
uni.$off('getSignImg')
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pagesMine/signature',
|
||||
success: () => {
|
||||
// 监听签名返回事件
|
||||
const eventHandler = (e) => {
|
||||
console.log('getSignImg', e)
|
||||
// signBase64.value = e.base64
|
||||
// signTempimg.value = e.path
|
||||
auditForm.value.approverSignUrl = e.url
|
||||
}
|
||||
|
||||
// 监听一次自定义事件
|
||||
uni.$once('getSignImg', eventHandler)
|
||||
|
||||
// 页面卸载时移除监听(避免内存泄漏)
|
||||
// uni.$off('getSignImg', eventHandler)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const auditConfirm = () => {
|
||||
auditFormRef.value.validate().then(res => {
|
||||
let obj = {
|
||||
billNo: detailData.value.billNo,
|
||||
id: detailData.value.id,
|
||||
rkId: detailData.value.rkId,
|
||||
remark: auditForm.value.remark,
|
||||
auditResult: auditStatus.value,
|
||||
}
|
||||
if (auditStatus.value == 1) {
|
||||
obj.approverSignUrl = auditForm.value.approverSignUrl
|
||||
}
|
||||
passedAudit(obj).then(res => {
|
||||
auditModalRef.value.close()
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
icon: 'none',
|
||||
mask: true,
|
||||
dution: 2000
|
||||
})
|
||||
setTimeout(() => {
|
||||
uni.navigateBack({})
|
||||
}, 2000)
|
||||
})
|
||||
}).catch(errors => {
|
||||
auditModalRef.value.closeLoading()
|
||||
})
|
||||
}
|
||||
|
||||
// 组件卸载时移除事件监听器
|
||||
onUnmounted(() => {
|
||||
console.log("协助")
|
||||
uni.$off('getSignImg')
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.container {
|
||||
position: relative;
|
||||
padding: 32rpx;
|
||||
padding-bottom: 120rpx;
|
||||
line-height: 50rpx;
|
||||
font-size: 28rpx;
|
||||
border-radius: 8rpx;
|
||||
color: #333;
|
||||
|
||||
text{
|
||||
color: #666;
|
||||
}
|
||||
.box{
|
||||
.item {
|
||||
background: #efefef;
|
||||
padding: 20rpx;
|
||||
margin-top: 20rpx;
|
||||
.title {
|
||||
font-size: 32rpx;
|
||||
font-weight: bold;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
.btn{
|
||||
position: fixed;
|
||||
width: calc(100vw - 64rpx);
|
||||
bottom: 0;
|
||||
left: 32rpx;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
::v-deep .uv-input__content{
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
196
pagesMine/index.js
Normal file
196
pagesMine/index.js
Normal file
@@ -0,0 +1,196 @@
|
||||
function getLocalFilePath(path) {
|
||||
if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('file://') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('/storage/emulated/0/') === 0) {
|
||||
return path
|
||||
}
|
||||
if (path.indexOf('/') === 0) {
|
||||
var localFilePath = plus.io.convertAbsoluteFileSystem(path)
|
||||
if (localFilePath !== path) {
|
||||
return localFilePath
|
||||
} else {
|
||||
path = path.substr(1)
|
||||
}
|
||||
}
|
||||
return '_www/' + path
|
||||
}
|
||||
|
||||
function dataUrlToBase64(str) {
|
||||
var array = str.split(',')
|
||||
return array[array.length - 1]
|
||||
}
|
||||
|
||||
var index = 0
|
||||
function getNewFileId() {
|
||||
return Date.now() + String(index++)
|
||||
}
|
||||
|
||||
function biggerThan(v1, v2) {
|
||||
var v1Array = v1.split('.')
|
||||
var v2Array = v2.split('.')
|
||||
var update = false
|
||||
for (var index = 0; index < v2Array.length; index++) {
|
||||
var diff = v1Array[index] - v2Array[index]
|
||||
if (diff !== 0) {
|
||||
update = diff > 0
|
||||
break
|
||||
}
|
||||
}
|
||||
return update
|
||||
}
|
||||
|
||||
export function pathToBase64(path) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof window === 'object' && 'document' in window) {
|
||||
if (typeof FileReader === 'function') {
|
||||
var xhr = new XMLHttpRequest()
|
||||
xhr.open('GET', path, true)
|
||||
xhr.responseType = 'blob'
|
||||
xhr.onload = function() {
|
||||
if (this.status === 200) {
|
||||
let fileReader = new FileReader()
|
||||
fileReader.onload = function(e) {
|
||||
resolve(e.target.result)
|
||||
}
|
||||
fileReader.onerror = reject
|
||||
fileReader.readAsDataURL(this.response)
|
||||
}
|
||||
}
|
||||
xhr.onerror = reject
|
||||
xhr.send()
|
||||
return
|
||||
}
|
||||
var canvas = document.createElement('canvas')
|
||||
var c2x = canvas.getContext('2d')
|
||||
var img = new Image
|
||||
img.onload = function() {
|
||||
canvas.width = img.width
|
||||
canvas.height = img.height
|
||||
c2x.drawImage(img, 0, 0)
|
||||
resolve(canvas.toDataURL())
|
||||
canvas.height = canvas.width = 0
|
||||
}
|
||||
img.onerror = reject
|
||||
img.src = path
|
||||
return
|
||||
}
|
||||
if (typeof plus === 'object') {
|
||||
plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
|
||||
entry.file(function(file) {
|
||||
var fileReader = new plus.io.FileReader()
|
||||
fileReader.onload = function(data) {
|
||||
resolve(data.target.result)
|
||||
}
|
||||
fileReader.onerror = function(error) {
|
||||
reject(error)
|
||||
}
|
||||
fileReader.readAsDataURL(file)
|
||||
}, function(error) {
|
||||
reject(error)
|
||||
})
|
||||
}, function(error) {
|
||||
reject(error)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
|
||||
wx.getFileSystemManager().readFile({
|
||||
filePath: path,
|
||||
encoding: 'base64',
|
||||
success: function(res) {
|
||||
resolve('data:image/png;base64,' + res.data)
|
||||
},
|
||||
fail: function(error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
reject(new Error('not support'))
|
||||
})
|
||||
}
|
||||
|
||||
export function base64ToPath(base64) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
if (typeof window === 'object' && 'document' in window) {
|
||||
base64 = base64.split(',')
|
||||
var type = base64[0].match(/:(.*?);/)[1]
|
||||
var str = atob(base64[1])
|
||||
var n = str.length
|
||||
var array = new Uint8Array(n)
|
||||
while (n--) {
|
||||
array[n] = str.charCodeAt(n)
|
||||
}
|
||||
return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
|
||||
}
|
||||
var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
|
||||
if (extName) {
|
||||
extName = extName[1]
|
||||
} else {
|
||||
reject(new Error('base64 error'))
|
||||
}
|
||||
var fileName = getNewFileId() + '.' + extName
|
||||
if (typeof plus === 'object') {
|
||||
var basePath = '_doc'
|
||||
var dirPath = 'uniapp_temp'
|
||||
var filePath = basePath + '/' + dirPath + '/' + fileName
|
||||
if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
|
||||
plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
|
||||
entry.getDirectory(dirPath, {
|
||||
create: true,
|
||||
exclusive: false,
|
||||
}, function(entry) {
|
||||
entry.getFile(fileName, {
|
||||
create: true,
|
||||
exclusive: false,
|
||||
}, function(entry) {
|
||||
entry.createWriter(function(writer) {
|
||||
writer.onwrite = function() {
|
||||
resolve(filePath)
|
||||
}
|
||||
writer.onerror = reject
|
||||
writer.seek(0)
|
||||
writer.writeAsBinary(dataUrlToBase64(base64))
|
||||
}, reject)
|
||||
}, reject)
|
||||
}, reject)
|
||||
}, reject)
|
||||
return
|
||||
}
|
||||
var bitmap = new plus.nativeObj.Bitmap(fileName)
|
||||
bitmap.loadBase64Data(base64, function() {
|
||||
bitmap.save(filePath, {}, function() {
|
||||
bitmap.clear()
|
||||
resolve(filePath)
|
||||
}, function(error) {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
}, function(error) {
|
||||
bitmap.clear()
|
||||
reject(error)
|
||||
})
|
||||
return
|
||||
}
|
||||
if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
|
||||
var filePath = wx.env.USER_DATA_PATH + '/' + fileName
|
||||
wx.getFileSystemManager().writeFile({
|
||||
filePath: filePath,
|
||||
data: dataUrlToBase64(base64),
|
||||
encoding: 'base64',
|
||||
success: function() {
|
||||
resolve(filePath)
|
||||
},
|
||||
fail: function(error) {
|
||||
reject(error)
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
reject(new Error('not support'))
|
||||
})
|
||||
}
|
||||
633
pagesMine/print.vue
Normal file
633
pagesMine/print.vue
Normal file
@@ -0,0 +1,633 @@
|
||||
<template>
|
||||
<div>
|
||||
<div style="display: flex;flex-wrap: wrap;justify-content: space-evenly;">
|
||||
<button type="primary" @click="openDev" style="width:100px;height:50px;" :disabled="isOpen == true">连接打印机</button>
|
||||
<button type="primary" @click="closeConnect" style="width:100px;height:50px;" :disabled="isOpen == false">关闭连接</button>
|
||||
<button type="primary" @click="getPrinterStatus" style="width:100px;height:50px;" :disabled="isOpen == false">获取状态</button>
|
||||
<button type="primary" @click="printText" style="width:100px;height:50px;" :disabled="isOpen == false">文字打印</button>
|
||||
<button type="primary" @click="printBarCode" style="width:100px;height:50px;" :disabled="isOpen == false">打印条码</button>
|
||||
<button type="primary" @click="searchGap" style="width:100px;height:50px;" :disabled="isOpen == false">标签对齐</button>
|
||||
<button type="primary" @click="printTable" style="width:100px;height:50px;" :disabled="isOpen == false">打印表格</button>
|
||||
<button type="primary" @click="setSensitivity" style="width:100px;height:50px;" :disabled="isOpen == false">灵敏度</button>
|
||||
<button type="primary" @click="printSelfCheck" style="width:100px;height:50px;" :disabled="isOpen == false">打印自检页</button>
|
||||
<button type="primary" @click="setPaperFeed" style="width:100px;height:50px;" :disabled="isOpen == false">走纸</button>
|
||||
<button type="primary" @click="setPaperBack" style="width:100px;height:50px;" :disabled="isOpen == false">退纸</button>
|
||||
<button type="primary" @click="setDensity" style="width:100px;height:50px;" :disabled="isOpen == false">浓度设置</button>
|
||||
<button type="primary" @click="setPaperType(0)" style="width:100px;height:50px;" :disabled="isOpen == false">设置热敏纸</button>
|
||||
<button type="primary" @click="setPaperType(1)" style="width:100px;height:50px;" :disabled="isOpen == false">设置标签纸</button>
|
||||
<button type="primary" @click="sendBytesData" style="width:100px;height:50px;" :disabled="isOpen == false">发送测试</button>
|
||||
<button type="primary" @click="read" style="width:100px;height:50px;" :disabled="isOpen == false">读取测试</button>
|
||||
<button type="primary" @click="setFlowMode" style="width:100px;height:50px;" :disabled="isOpen == false">打开流控开关</button>
|
||||
<button type="primary" style="width:100px;height:50px;opacity: 0;">占位</button>
|
||||
</div>
|
||||
|
||||
<canvas canvas-id="myCanvas" style="width: 340px;height: 240px;"></canvas>
|
||||
|
||||
<div style="height:50px;width:100px;">
|
||||
<button type="primary" @click="printImg" style="width:300px;height:50px;" :disabled="isOpen == false">打印图片</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { onLoad, onReady } from '@dcloudio/uni-app';
|
||||
var printSDK = uni.requireNativePlugin("PrintSDK");
|
||||
import QRCode from '@/static/uqrcode.es.js'; // 确保引入qrcode.js
|
||||
|
||||
// 响应式数据
|
||||
const isOpen = ref(false);
|
||||
|
||||
// 画布相关
|
||||
let canvasContext = null;
|
||||
|
||||
// 生命周期钩子 - 组件加载时
|
||||
onLoad(() => {
|
||||
// 调用同步方法初始化程序和uhf
|
||||
/* console.log("开始初始化")
|
||||
uni.showToast({
|
||||
title: "开始初始化",
|
||||
icon: "none",
|
||||
});
|
||||
var ret = printSDK.initUHF()
|
||||
var initResult = ret.code == "0"? '初始化成功':'初始化失败';
|
||||
uni.showToast({
|
||||
title: initResult,
|
||||
icon: "none",
|
||||
}); */
|
||||
});
|
||||
|
||||
// 生命周期钩子 - 组件DOM已更新
|
||||
onReady(() => {
|
||||
drawCanvas();
|
||||
});
|
||||
|
||||
// 生命周期钩子 - 组件挂载后
|
||||
onMounted(() => {
|
||||
// 注册全局事件监听
|
||||
plus.globalEvent.addEventListener('sendMessage', function(e) {
|
||||
if (e.tag == "getPrinterStatus") {
|
||||
// 打印机状态返回值
|
||||
uni.showToast({
|
||||
title: "sendMessage收到:" + JSON.stringify(e.msg),
|
||||
icon: "none",
|
||||
});
|
||||
} else if (e.tag == "initPrint") {
|
||||
// 连接和关闭打印机时返回的信息
|
||||
uni.showToast({
|
||||
title: "sendMessage收到:" + JSON.stringify(e.msg),
|
||||
icon: "none",
|
||||
});
|
||||
} else if (e.tag = "read") {
|
||||
// read函数返回的读取到的打印机信息的函数
|
||||
uni.showToast({
|
||||
title: "sendMessage收到:" + JSON.stringify(e.msg),
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// 绘制画布表格+二维码
|
||||
const drawCanvas = () => {
|
||||
canvasContext = uni.createCanvasContext('myCanvas');
|
||||
console.log(canvasContext)
|
||||
canvasContext.fillStyle = 'white'; // 设置填充颜色为红色
|
||||
canvasContext.fillRect(0, 0, 340, 240); // 填充整个画板
|
||||
drawTable(canvasContext);
|
||||
drawText(canvasContext);
|
||||
drawQRCode(canvasContext);
|
||||
canvasContext.draw(true); // 异步绘制,false表示绘制完成后不返回绘图结果
|
||||
};
|
||||
|
||||
// 绘制文本
|
||||
const drawText = (ctx) => {
|
||||
ctx.setFontSize(25);
|
||||
ctx.fillText('绘制测试页XX公司', 70, 40);
|
||||
};
|
||||
|
||||
// 绘制二维码
|
||||
const drawQRCode = (ctx) => {
|
||||
// 使用uQRCode.js生成二维码
|
||||
var qr = new QRCode('myCanvas', {
|
||||
width: 70,
|
||||
height: 70,
|
||||
colorDark: "#000000",
|
||||
colorLight: "#ffffff"
|
||||
});
|
||||
qr.data = "123";
|
||||
qr.size = 70;
|
||||
qr.make();
|
||||
qr.canvasContext = ctx;
|
||||
|
||||
ctx.save();
|
||||
// 平移画布到 (245, 115) 位置
|
||||
ctx.translate(245, 115);
|
||||
// 在平移后的位置绘制二维码
|
||||
qr.drawCanvas();
|
||||
// 恢复之前保存的画布上下文
|
||||
ctx.restore();
|
||||
};
|
||||
|
||||
// 绘制表格
|
||||
const drawTable = (ctx) => {
|
||||
// 绘制表格数据
|
||||
ctx.moveTo(10, 1);
|
||||
ctx.lineTo(320, 1);
|
||||
ctx.moveTo(10, 70);
|
||||
ctx.lineTo(320, 70);
|
||||
ctx.setFontSize(20);
|
||||
ctx.setFillStyle('#000000');
|
||||
ctx.fillText('物料编号: 134588788-1', 20, 100);
|
||||
ctx.moveTo(10, 110)
|
||||
ctx.lineTo(320, 110);
|
||||
ctx.fillText('物料名称: 连接杆', 20, 140);
|
||||
ctx.moveTo(10, 150)
|
||||
ctx.lineTo(240, 150);
|
||||
|
||||
ctx.moveTo(240, 110);
|
||||
ctx.lineTo(240, 190);
|
||||
|
||||
ctx.fillText('批次: H28228618', 20, 180);
|
||||
ctx.moveTo(10, 190)
|
||||
ctx.lineTo(320, 190);
|
||||
ctx.fillText('数量(QTY): 1', 20, 220);
|
||||
ctx.moveTo(10, 230)
|
||||
ctx.lineTo(320, 230);
|
||||
ctx.setFontSize(25);
|
||||
// ctx.fillText('标记问题件', 100, 275);
|
||||
// ctx.moveTo(10, 285)
|
||||
// ctx.lineTo(320, 285);
|
||||
|
||||
// 左边外边框
|
||||
ctx.moveTo(10, 0)
|
||||
ctx.lineTo(10, 230);
|
||||
// 右边外边框
|
||||
ctx.moveTo(320, 0)
|
||||
ctx.lineTo(320, 230);
|
||||
ctx.setStrokeStyle('red')
|
||||
ctx.stroke()
|
||||
};
|
||||
|
||||
// 流控开关
|
||||
const setFlowMode = () => {
|
||||
let a = printSDK.sendBytesData("1F111F2C371F1F")
|
||||
console.log(a)
|
||||
uni.showToast({
|
||||
title: "流控开关已打开",
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
|
||||
// 连接打印机
|
||||
const openDev = () => {
|
||||
console.log("ret", printSDK);
|
||||
var ret = printSDK.connectPrinter()
|
||||
var openResult = ret.code == "0" ? '连接成功' : '连接失败';
|
||||
if (ret.code == "0") {
|
||||
isOpen.value = true
|
||||
}
|
||||
uni.showToast({
|
||||
title: openResult,
|
||||
icon: "none",
|
||||
});
|
||||
var ret = printSDK.initPrint();
|
||||
if (ret.code != '0') {
|
||||
uni.showToast({
|
||||
title: "打印机初始化失败",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 下电
|
||||
const closeConnect = () => {
|
||||
var ret = printSDK.closeConnect()
|
||||
var closeResult = ret.code == "0" ? '成功' : '失败';
|
||||
if (ret.code == "0") {
|
||||
isOpen.value = false
|
||||
}
|
||||
uni.showToast({
|
||||
title: closeResult,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
|
||||
// 打印文字测试
|
||||
const printText = () => {
|
||||
var ret = printSDK.initPrint();
|
||||
if (ret.code != '0') {
|
||||
uni.showToast({
|
||||
title: "打印机初始化失败",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
printSDK.setFont(0, 1, 1, 0, 0);
|
||||
printSDK.setPrinter(2, 1);
|
||||
var ret = printSDK.printText("打印文字测试\r\n");
|
||||
if (ret.code != '0') {
|
||||
uni.showToast({
|
||||
title: "函数执行失败",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
printSDK.setFont(0, 0, 0, 0, 0);
|
||||
printSDK.setPrinter(2, 0);
|
||||
var ret = printSDK.printText("打印文字测试\r\n");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const printBarCode = () => {
|
||||
var ret = printSDK.initPrint();
|
||||
if (ret.code != '0') {
|
||||
uni.showToast({
|
||||
title: "打印机初始化失败",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
var type = [73, 4, 6, 5, 72, 3, 102]
|
||||
for (var i = 0; i < type.length; i++) {
|
||||
printSDK.setPrinter(1, 2);
|
||||
if (type[i] == 102) {
|
||||
var ret = printSDK.printBarCode(type[i], 2, 3, 6, "123456");
|
||||
} else {
|
||||
var ret = printSDK.printBarCode(type[i], 2, 162, 2, "0123456789");
|
||||
}
|
||||
printSDK.setPrinter(1, 3);
|
||||
printSDK.setPrinter(2, 0);
|
||||
if (ret.code == '0') {
|
||||
uni.showToast({
|
||||
title: "函数执行失败",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// 保存图片并打印
|
||||
const saveImage = (picData) => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: picData,
|
||||
success(result) {
|
||||
uni.showToast({
|
||||
title: "开始打印图片",
|
||||
icon: "none",
|
||||
});
|
||||
var destPic = result.file;
|
||||
|
||||
var ret = printSDK.initPrint();
|
||||
if (ret.code != '0') {
|
||||
uni.showToast({
|
||||
title: "打印机初始化失败",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
printSDK.printText("\n");
|
||||
printSDK.setPrinter(1, 1);
|
||||
var path = result.path;
|
||||
getImageSize(path);
|
||||
uni.showToast({
|
||||
title: "打印路径:" + path,
|
||||
icon: "none",
|
||||
});
|
||||
console.log(path);
|
||||
ret = printSDK.printImage(result.file, 3, 0, false);
|
||||
// printSDK.setPaperFeed(50)
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
printSDK.searchGap()
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "函数执行失败",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
fail() {
|
||||
uni.hideLoading()
|
||||
uni.showModal({
|
||||
content: '检测到您没打开获取信息功能权限,是否去设置打开?',
|
||||
confirmText: "确认",
|
||||
cancelText: '取消',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
uni.openSetting({
|
||||
success: (res) => {
|
||||
console.log(res);
|
||||
uni.showToast({
|
||||
title: "请重新打印图片",
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
})
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: "保存失败,请打开权限功能重试",
|
||||
icon: "none"
|
||||
});
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// 获取图片尺寸
|
||||
const getImageSize = (filePath) => {
|
||||
// 使用 uni.getImageInfo 获取图片的元数据,包括尺寸信息
|
||||
uni.getImageInfo({
|
||||
src: filePath,
|
||||
success: (imageInfo) => {
|
||||
console.log('图片宽度:', imageInfo.width);
|
||||
console.log('图片高度:', imageInfo.height);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('获取图片信息失败', err);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// 打印图片
|
||||
const printImg = () => {
|
||||
for (let index = 0; index < 5; index++) {
|
||||
printSDK.setPaperBack(2)
|
||||
}
|
||||
// uni.showToast({
|
||||
// title: "函数执行成功",
|
||||
// icon: "none",
|
||||
// });
|
||||
// canvas保存成临时图片
|
||||
uni.canvasToTempFilePath({
|
||||
width: 350,
|
||||
height: 600,
|
||||
canvasId: 'myCanvas',
|
||||
success: function(res) {
|
||||
console.log(res.tempFilePath)
|
||||
var picData = res.tempFilePath
|
||||
// 后台直接打印图片
|
||||
saveImage(picData);
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// 打印表格
|
||||
const printTable = () => {
|
||||
var column = "品名;数量;单价;金额";
|
||||
var regularExpression = ";";
|
||||
var columnWidth = "14,6,6,6"; //逗号分隔字符串,不要调整格式,逗号和数字之间不要加空格!!!!!!!!!!!!!!
|
||||
var rows = ["保鲜袋;10.00;1;10.00", "铁丝挂钩;5.00;2;10.00", "雨伞;5.00;3;15.00"];
|
||||
var ret = printSDK.printTable(column, regularExpression, columnWidth, rows);
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功!",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 打印自检页
|
||||
const printSelfCheck = () => {
|
||||
var ret = printSDK.printSelfCheck();
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 走纸
|
||||
const setPaperFeed = () => {
|
||||
var ret = printSDK.setPaperFeed(2);
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 退纸
|
||||
const setPaperBack = () => {
|
||||
var ret = printSDK.setPaperBack(2);
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 获取打印机状态
|
||||
const getPrinterStatus = () => {
|
||||
var ret = printSDK.getPrinterStatus();
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "正常",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: ret.code,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 标签对齐
|
||||
const searchGap = () => {
|
||||
var ret = printSDK.searchGap();
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 设置灵敏度
|
||||
const setSensitivity = () => {
|
||||
var ret = printSDK.setSensitivity(10);
|
||||
if (ret.code == "0") {
|
||||
uni.showToast({
|
||||
title: "函数执行成功",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 设置浓度
|
||||
const setDensity = () => {
|
||||
var ret = printSDK.setDensity(0);
|
||||
if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: ret.code,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 设置纸张类型
|
||||
const setPaperType = (type) => {
|
||||
var ret = printSDK.setPaperType(type)
|
||||
if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: ret.code,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 发送测试
|
||||
const sendBytesData = () => {
|
||||
var ret = printSDK.sendBytesData("1b3300")
|
||||
if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: ret.code,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 读取测试
|
||||
const read = () => {
|
||||
var ret = printSDK.read()
|
||||
if (ret.code == "-999") {
|
||||
uni.showToast({
|
||||
title: "打印机未连接",
|
||||
icon: "none",
|
||||
});
|
||||
} else if (ret.code == "999") {
|
||||
uni.showToast({
|
||||
title: "打印机未初始化",
|
||||
icon: "none",
|
||||
});
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: ret.code,
|
||||
icon: "none",
|
||||
});
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
uni-button{
|
||||
margin: 0;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
canvas {
|
||||
/* border: 1px solid #000; */
|
||||
}
|
||||
</style>
|
||||
88
pagesMine/signPreview.vue
Normal file
88
pagesMine/signPreview.vue
Normal file
@@ -0,0 +1,88 @@
|
||||
<template>
|
||||
<view class="exmaple1">
|
||||
<button @click="onSign">去签名</button>
|
||||
<view class="sign-preview">
|
||||
<image
|
||||
class="sign-image"
|
||||
v-if="signBase64"
|
||||
:src="signBase64"
|
||||
mode="widthFix"
|
||||
@click="onPreview"
|
||||
></image>
|
||||
<view v-else>签名预览</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onShow } from '@dcloudio/uni-app'
|
||||
import { ref, onUnmounted } from 'vue'
|
||||
|
||||
|
||||
const signBase64 = ref('')
|
||||
const signTempimg = ref('')
|
||||
// 去签名页面
|
||||
const onSign = () => {
|
||||
// 移除之前的事件监听器避免重复
|
||||
uni.$off('getSignImg')
|
||||
|
||||
uni.navigateTo({
|
||||
url: '/pagesMine/signature',
|
||||
success: () => {
|
||||
// 监听签名返回事件
|
||||
const eventHandler = (e) => {
|
||||
console.log('getSignImg', e)
|
||||
signBase64.value = e.base64
|
||||
signTempimg.value = e.path
|
||||
}
|
||||
|
||||
// 监听一次自定义事件
|
||||
uni.$once('getSignImg', eventHandler)
|
||||
|
||||
// 页面卸载时移除监听(避免内存泄漏)
|
||||
// uni.$off('getSignImg', eventHandler)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 预览签名图片
|
||||
const onPreview = () => {
|
||||
if (signTempimg.value) {
|
||||
uni.previewImage({
|
||||
urls: [signTempimg.value]
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
onShow(()=>{
|
||||
// plus.screen.lockOrientation('portrait-primary');
|
||||
console.log("竖屏")
|
||||
})
|
||||
|
||||
// 组件卸载时移除事件监听器
|
||||
// onUnmounted(() => {
|
||||
// uni.$off('getSignImg')
|
||||
// })
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.exmaple1 {
|
||||
padding: 24rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.sign-preview {
|
||||
min-height: 1000rpx;
|
||||
margin-top: 24rpx;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border: 1px solid #66ccff;
|
||||
background-color: #f0f0f0;
|
||||
color: #bbbbbb;
|
||||
}
|
||||
|
||||
.sign-image {
|
||||
width: 640rpx;
|
||||
}
|
||||
</style>
|
||||
278
pagesMine/signature.vue
Normal file
278
pagesMine/signature.vue
Normal file
@@ -0,0 +1,278 @@
|
||||
<template>
|
||||
<view class="box">
|
||||
<canvas v-if="showCanvas" id="canvas" canvas-id="canvas" style="width: 100vw;background-color: green;" :style="`height:${canvasHeight}px`" @touchstart="startDraw" @touchmove="drawing" @@touchend="endDraw"></canvas>
|
||||
|
||||
<cover-view class="tipTxt">请在空白处横屏签名</cover-view>
|
||||
|
||||
<view class="btn">
|
||||
<uv-button size="large" style="width: 50%;" @tap="clearSign">重 签</uv-button>
|
||||
<uv-button type="primary" size="large" class="mainBtn" style="width: 50%;" @tap="confirm">完 成</uv-button>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { onReady, onUnload } from '@dcloudio/uni-app';
|
||||
import { ref, nextTick } from 'vue';
|
||||
import { pathToBase64, base64ToPath } from './index.js'
|
||||
import { uploadImg } from "@/api/upload"
|
||||
|
||||
const btnHeight = ref(null)
|
||||
const BoxHeight = ref(null)
|
||||
const canvasWidth = ref(null)
|
||||
const canvasHeight = ref(null)
|
||||
const showCanvas = ref(false)
|
||||
|
||||
const signFlag = ref(false)
|
||||
|
||||
const getBtnHeight = () => {
|
||||
const query = uni.createSelectorQuery().in(this);
|
||||
// 选择要查询的元素,使用元素ID或类名
|
||||
query.select('.btn').boundingClientRect(data => {
|
||||
btnHeight.value = data.height
|
||||
}).select('.box').boundingClientRect(res => {
|
||||
// console.log('元素高度:', res);
|
||||
// BoxHeight.value = res.height
|
||||
// canvasWidth.value = res.width
|
||||
}).exec(() => {
|
||||
// 确保两个查询都完成后再初始化画布
|
||||
if (btnHeight.value && BoxHeight.value && canvasWidth.value) {
|
||||
console.log("获取",BoxHeight.value,btnHeight.value);
|
||||
|
||||
canvasHeight.value = BoxHeight.value - btnHeight.value
|
||||
showCanvas.value = true
|
||||
// 等待DOM更新完成后再初始化Canvas
|
||||
nextTick(() => {
|
||||
initCanvas();
|
||||
});
|
||||
} else {
|
||||
console.error('获取元素尺寸失败,无法初始化画布');
|
||||
}
|
||||
}); // 执行查询
|
||||
}
|
||||
|
||||
let canvasContext = null
|
||||
const initCanvas = () => {
|
||||
console.log(canvasWidth.value, canvasHeight.value)
|
||||
canvasContext = uni.createCanvasContext('canvas');
|
||||
canvasContext.setFillStyle('#F5F5F5'); // 设置填充颜色为红色
|
||||
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value); // 填充整个画板
|
||||
canvasContext.draw(true)
|
||||
}
|
||||
|
||||
const startX = ref(null)
|
||||
const startY = ref(null)
|
||||
const startDraw = (e) => {
|
||||
startX.value = e.touches[0].x
|
||||
startY.value = e.touches[0].y
|
||||
canvasContext.beginPath(); // 开始创建一个路径
|
||||
signFlag.value = true
|
||||
}
|
||||
const endDraw = (e) => {
|
||||
startX.value = 0
|
||||
startY.value = 0
|
||||
}
|
||||
|
||||
const drawing = (e) => {
|
||||
let temX = e.touches[0].x;
|
||||
let temY = e.touches[0].y;
|
||||
canvasContext.moveTo(startX.value, startY.value)
|
||||
canvasContext.lineTo(temX, temY)
|
||||
canvasContext.setStrokeStyle('#000') // 文字颜色
|
||||
canvasContext.setLineWidth(4) // 文字宽度
|
||||
canvasContext.setLineCap('round') // 文字圆角
|
||||
canvasContext.stroke() // 文字绘制
|
||||
startX.value = temX
|
||||
startY.value = temY
|
||||
canvasContext.draw(true) // 文字绘制到画布中
|
||||
}
|
||||
|
||||
const clearSign = () => {
|
||||
canvasContext.setFillStyle('#F5F5F5'); // 设置填充颜色为红色
|
||||
canvasContext.fillRect(0, 0, canvasWidth.value, canvasHeight.value); // 填充整个画板
|
||||
canvasContext.draw(true) // 文字绘制到画布中
|
||||
signFlag.value = false
|
||||
}
|
||||
|
||||
const confirm = () => {
|
||||
// 确认按钮事件
|
||||
if (!signFlag.value) {
|
||||
uni.showToast({
|
||||
title: '请签名后再点击确定',
|
||||
icon: 'none',
|
||||
duration: 2000
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
uni.showModal({
|
||||
title: '确认',
|
||||
content: '确认签名无误吗',
|
||||
showCancel: true,
|
||||
success: async ({ confirm }) => {
|
||||
if (confirm) {
|
||||
let tempFile
|
||||
// if (this.horizontal) {
|
||||
tempFile = await saveHorizontalCanvas()
|
||||
// } else {
|
||||
// tempFile = await this.saveCanvas()
|
||||
// }
|
||||
console.log(tempFile, "tempFile")
|
||||
const base64 = await pathToBase64(tempFile)
|
||||
const path = await base64ToPath(base64)
|
||||
console.log(path, "path")
|
||||
const res = await uploadImg(path, {});
|
||||
uni.navigateBack();
|
||||
uni.$emit('getSignImg', { base64, path, url: res.url });
|
||||
// uploadImg(path, {}).then(res=>{
|
||||
// console.log(base64, path, res.url, "打印")
|
||||
// let url = res.url
|
||||
// uni.$emit('getSignImg', { base64, path, url })
|
||||
// uni.navigateBack()
|
||||
// })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
const saveHorizontalCanvas = async () => {
|
||||
return await new Promise((resolve, reject) => {
|
||||
uni.canvasToTempFilePath(
|
||||
{
|
||||
canvasId: 'canvas',
|
||||
fileType: "png", // 只支持png和jpg
|
||||
success: (res) => {
|
||||
if (!res.tempFilePath) {
|
||||
uni.showModal({
|
||||
title: '提示',
|
||||
content: '保存签名失败',
|
||||
showCancel: false
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// #ifdef APP
|
||||
uni.compressImage({
|
||||
src: res.tempFilePath,
|
||||
quality: 100, // 范围 0 - 100
|
||||
rotate: 270,
|
||||
success: (r) => {
|
||||
console.log('==== compressImage :', r)
|
||||
resolve(r.tempFilePath)
|
||||
}
|
||||
})
|
||||
// #endif
|
||||
|
||||
// #ifndef APP
|
||||
// uni.getImageInfo({
|
||||
// src: res.tempFilePath,
|
||||
// success: (r) => {
|
||||
// // console.log('==== getImageInfo :', r)
|
||||
// // 将signCanvas的内容复制到hsignCanvas中
|
||||
// const hcanvasCtx = uni.createCanvasContext('hsignCanvas', this)
|
||||
// // 横屏宽高互换
|
||||
// hcanvasCtx.translate(this.canvasHeight / 2, this.canvasWidth / 2)
|
||||
// hcanvasCtx.rotate(Math.PI * (-90 / 180))
|
||||
// hcanvasCtx.drawImage(
|
||||
// r.path,
|
||||
// -this.canvasWidth / 2,
|
||||
// -this.canvasHeight / 2,
|
||||
// this.canvasWidth,
|
||||
// this.canvasHeight
|
||||
// )
|
||||
// hcanvasCtx.draw(false, async () => {
|
||||
// const hpathRes = await uni.canvasToTempFilePath(
|
||||
// {
|
||||
// canvasId: 'hsignCanvas',
|
||||
// fileType: this.expFile.fileType, // 只支持png和jpg
|
||||
// quality: this.expFile.quality // 范围 0 - 1
|
||||
// },
|
||||
// this
|
||||
// )
|
||||
// let tempFile = ''
|
||||
// if (Array.isArray(hpathRes)) {
|
||||
// hpathRes.some((item) => {
|
||||
// if (item) {
|
||||
// tempFile = item.tempFilePath
|
||||
// return
|
||||
// }
|
||||
// })
|
||||
// } else {
|
||||
// tempFile = hpathRes.tempFilePath
|
||||
// }
|
||||
// resolve(tempFile)
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
// #endif
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('图片生成失败:' + err)
|
||||
resolve(false)
|
||||
}
|
||||
},
|
||||
this
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
onReady(() => {
|
||||
// uni.showLoading({
|
||||
// title: '正在加载,请稍后...',
|
||||
// mask: true
|
||||
// })
|
||||
// 页面加载完成后设置横屏
|
||||
// plus.screen.lockOrientation('landscape-primary')
|
||||
// nextTick(() => {
|
||||
// getBtnHeight();
|
||||
// });
|
||||
// setTimeout(() => {
|
||||
// uni.hideLoading();
|
||||
uni.getSystemInfo({
|
||||
success: function (res) {
|
||||
console.log(res)
|
||||
BoxHeight.value = res.windowHeight
|
||||
canvasWidth.value = res.windowWidth
|
||||
}
|
||||
});
|
||||
getBtnHeight();
|
||||
// }, 1500);
|
||||
// nextTick(() => {
|
||||
// getBtnHeight();
|
||||
// });
|
||||
})
|
||||
|
||||
|
||||
onUnload(() => {
|
||||
// 页面卸载时恢复竖屏
|
||||
// plus.screen.lockOrientation('portrait-primary');
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.box {
|
||||
position: relative;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
|
||||
.tipTxt{
|
||||
position: absolute;
|
||||
top: 10rpx;
|
||||
left: 10rpx;
|
||||
color: #999;
|
||||
font-size: 44rpx;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: fixed;
|
||||
width: 100vw;
|
||||
bottom: 0;
|
||||
z-index: 99;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user