qa-prevention-gwj-first-app/pages/application/gas-detection/gas-detection-record.vue

1431 lines
39 KiB
Vue
Raw Permalink Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<view :class="isUps == true ? 'prevent' : ''">
<cu-custom bgColor="bg-gradual-blueness" :isBack="true">
<block slot="backText">返回</block>
<block slot="content">气体检测记录</block>
</cu-custom>
<scroll-view scroll-y="false" >
<view class="form">
<!-- <view class="cu-form-textarea">
<view class="cu-form-title text-hui">检查内容</view>
<view class="f24 text-black">
{{pd.CHECK_CONTENT}}
</view>
</view> -->
<view class="ace-list mt30">
<view class="ace-title">
<text class="text-semi">初次气体检测</text>
<button v-if="pd.STATUS=='4'" class="cu-btn round bg-blue" @click="$noMultipleClicks(addGas,'1')">添加</button>
</view>
<view class="acb-content">
<view class="add_pard_item" v-bind:key="index" v-for="(item,index) of gasDetectionList" v-if="item.TYPE=='1'">
<view class="add_pard_del" v-if="pd.STATUS=='4'" @click="removeOther(item.GASDETECTION_ID)">
<text class="cuIcon-roundclosefill text-red f40"></text>
</view>
<view @click="$noMultipleClicks(goToEdit,item.GASDETECTION_ID)" class="cu-form-group">
<view class="title">检查位置:{{item.LOCATION}}</view>
<view v-if="item.DECIDE=='1'">合格</view>
<view v-else-if="item.DECIDE=='0'">不合格</view>
</view>
</view>
</view>
</view>
<view class="ace-list mt30">
<view class="ace-title">
<text class="text-semi">再次检测</text>
<button v-if="pd.STATUS=='4'" class="cu-btn round bg-blue" @click="$noMultipleClicks(addGas,'2')">添加</button>
</view>
<view class="acb-content">
<view class="add_pard_item" v-bind:key="index" v-for="(item,index) of gasDetectionList" v-if="item.TYPE=='2'">
<view class="add_pard_del" v-if="pd.STATUS=='4'" @click="removeOther(item.GASDETECTION_ID)">
<text class="cuIcon-roundclosefill text-red f40"></text>
</view>
<view @click="$noMultipleClicks(goToEdit,item.GASDETECTION_ID)" class="cu-form-group">
<view class="title">检查位置:{{item.LOCATION}}</view>
<view v-if="item.DECIDE=='1'">合格</view>
<view v-else-if="item.DECIDE=='0'">不合格</view>
</view>
</view>
</view>
</view>
<view class="ace-list mt30">
<view class="ace-title">
<text class="text-semi">作业中实时检测</text>
<button v-if="pd.STATUS=='4'" class="cu-btn round bg-blue" @click="$noMultipleClicks(addGas,'3')">添加</button>
</view>
<view class="acb-content">
<view class="add_pard_item" v-bind:key="index" v-for="(item,index) of gasDetectionList" v-if="item.TYPE=='3'" >
<view class="add_pard_del" v-if="pd.STATUS=='4'" @click="removeOther(item.GASDETECTION_ID)">
<text class="cuIcon-roundclosefill text-red f40"></text>
</view>
<view @click="$noMultipleClicks(goToEdit,item.GASDETECTION_ID)" class="cu-form-group">
<view class="title">检查位置:{{item.LOCATION}}</view>
<view v-if="item.DECIDE=='1'">合格</view>
<view v-else-if="item.DECIDE=='0'">不合格</view>
</view>
</view>
</view>
</view>
<view class="de-card-list de-list">
<view class="cu-form-group bb">
<view class="title">检测时间</view>
<ruiDatePicker v-if="pd.STATUS=='4'"
:start="todayDate"
fields="minute"
:value="pd.INSPECTORTIME?pd.INSPECTORTIME:'请选择'"
@change="changeInspectorTime"
></ruiDatePicker>
<view v-else>{{pd.INSPECTORTIME}}</view>
</view>
<view class="cu-form-group ">
<view class="title">检测人签字</view>
<button class="cu-btn bg-green shadow" :disabled="pd.STATUS=='5'" @tap="showModal" data-target="Modal">手写签字</button>
</view>
<view class="cu-bar bg-white" v-show="imgList && imgList.length > 0">
<view class="action">
签字照片
</view>
<!-- <view class="action">
{{imgList.length}}/4
</view> -->
</view>
<view class="cu-form-group" v-show="imgList && imgList.length > 0">
<view class="grid col-4 grid-square flex-sub">
<view style="width: 60%;" class="bg-img" v-for="(item,index) in imgList" :key="index" @tap="ViewImage" data-type="0" :data-url="imgList[index].filePath">
<image :src="imgList[index].filePath" mode="aspectFill"></image>
<view class="cu-tag bg-red" v-show="pd.STATUS=='4'" @tap.stop="DelImg" data-type="0" :data-index="index">
<text class='cuIcon-close'></text>
</view>
</view>
</view>
</view>
<view class="cu-modal" :class="modalName=='Modal'?'show':''">
<view class="cu-dialog">
<view class="cu-bar bg-white justify-end">
<view class="content">签名</view>
<view class="action" @tap="hideModal">
<text class="cuIcon-close text-red"></text>
</view>
</view>
<view>
<view class="wrapper">
<view class="handCenter">
<canvas
class="handWriting"
:disable-scroll="true"
@touchstart="uploadScaleStart"
@touchmove="uploadScaleMove"
@touchend="uploadScaleEnd"
canvas-id="handWriting"
></canvas>
</view>
<!-- <view class="handBtn">
<image
@click="selectColorEvent('black','#1A1A1A')"
:src="selectColor === 'black' ? '/static/color_black_selected.png' : '/static/color_black.png'"
:class="[selectColor === 'black' ? 'color_select' : '', 'black-select']"
></image>
<image
@click="selectColorEvent('red','#ca262a')"
:src="selectColor === 'red' ? '/static/color_red_selected.png' : '/static/color_red.png'"
:class="[selectColor === 'red' ? 'color_select' : '', 'black-select']"
></image>
<button @click="retDraw" class="delBtn">重写</button>
<!-- <button @click="saveCanvasAsImg" class="saveBtn">保存</button>
<button @click="previewCanvasImg" class="previewBtn">预览</button>
<button @click="uploadCanvasImg" class="uploadBtn">上传</button>
<button @click="subCanvas" class="subBtn">完成</button>
</view> -->
</view>
</view>
<view class="cu-bar bg-white justify-end">
<view class="action">
<button class="cu-btn line-green text-green" @click="retDraw">重写</button>
<button class="cu-btn bg-green margin-left" @click="subCanvas">完成</button>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="padding flex flex-direction">
<button class="cu-btn bg-blue margin-tb-sm lg" v-if="pd.STATUS=='4'" @click="$noMultipleClicks(goSubmit)"></button>
</view>
</scroll-view>
</view>
</template>
<script>
import {
basePath,corpinfoId,deptId,loginUser,formatDate,loginSession,baseImgPath
} from '@/common/tool.js';
import tkiTree from "@/components/select-tree/select-tree.vue"
import gcoord from '@/common/gcoord.js'
import ruiDatePicker from '@/components/rattenking-dtpicker/rattenking-dtpicker.vue';
export default {
components: {
tkiTree,ruiDatePicker
},
data() {
return {
isUps:false,
msg:'add',
riskId:'',
itemId:'',
index:'',
noClick:true,
pd:[],// 数据
todayDate:'',
forbidEdit:true,// 禁止修改
gasDetectionList:[],// 气体检测清单
modalName:null,
imgList:[],
//手写板
canvasName: 'handWriting',
ctx: '',
canvasWidth: 0,
canvasHeight: 0,
transparent: 1, // 透明度
selectColor: 'black',
lineColor: '#1A1A1A', // 颜色
lineSize: 1.5, // 笔记倍数
lineMin: 0.5, // 最小笔画半径
lineMax: 4, // 最大笔画半径
pressure: 1, // 默认压力
smoothness: 60, //顺滑度用60的距离来计算速度
currentPoint: {},
currentLine: [], // 当前线条
firstTouch: true, // 第一次触发
radius: 1, //画圆的半径
cutArea: { top: 0, right: 0, bottom: 0, left: 0 }, //裁剪区域
bethelPoint: [], //保存所有线条 生成的贝塞尔点;
lastPoint: 0,
chirography: [], //笔迹
currentChirography: {}, //当前笔迹
linePrack: [], //划线轨迹 , 生成线条的实际点
}
},
onLoad(event){
var _this = this;
this.pd.LIMITSPACEAPPROVE_ID = event.LIMITSPACEAPPROVE_ID;
//手写板
let canvasName = this.canvasName;
let ctx = uni.createCanvasContext(canvasName);
this.ctx = ctx;
var query = uni.createSelectorQuery();
query
.select('.handCenter')
.boundingClientRect(rect => {
this.canvasWidth = rect.width;
this.canvasHeight = rect.height;
/* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
this.setCanvasBg('#fff');
})
.exec();
},
onReady() {
},
onShow() {
var _this = this;
this.todayDate = formatDate(new Date(), 'yyyy-MM-dd hh:mm');
if(this.pd.LIMITSPACEAPPROVE_ID){
this.msg="edit";
this.getData();
}
loginSession();
},
methods: {
showModal(e) {
this.modalName = e.currentTarget.dataset.target
},
getData() {
var _this = this;
uni.showLoading({
title: '请稍候'
})
uni.request({
url: basePath + '/app/limitspaceapprove/goEdit',
method: 'POST',
dataType: 'json',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
data: {
LIMITSPACEAPPROVE_ID: _this.pd.LIMITSPACEAPPROVE_ID,
},
success: (res) => {
if ("success" == res.data.result) {
uni.hideLoading();
_this.pd = res.data.pd; //参数map
let files=res.data.jcImgs;
console.info("第2处")
//_this.imgList.splice(0,_this.imgList.length);
for(var i=0;i<files.length;i++){
let img={};
img.filePath=baseImgPath+files[i].FILEPATH;
img.id=files[i].IMGFILES_ID;
_this.imgList.push(img);
}
_this.getGasList();
} else if ("exception" == data.result) {
uni.showToast({
title: '',
duration: 2000
});
}
}
});
},
//
getGasList() {
var _this = this;
var ISFINISH = '0';
if(this.pd.STATUS == '5'){
ISFINISH = '1'
}
uni.showLoading({
title: ''
})
uni.request({
url: basePath + '/app/gasdetection/listAllBycondition',
method: 'POST',
dataType: 'json',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
data: {
LIMITSPACEAPPROVE_ID: _this.pd.LIMITSPACEAPPROVE_ID,
CORPINFO_ID: corpinfoId,
ISFINISH: ISFINISH
},
success: (res) => {
if ("success" == res.data.result) {
uni.hideLoading();
_this.gasDetectionList = res.data.varList;
} else if ("exception" == data.result) {
uni.showToast({
title: '错误',
duration: 2000
});
}
}
});
},
//获取数据字典数据
getDict: function () {
var _this = this;
uni.request({
method: 'POST',
dataType: 'json',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
url: basePath + '/dictionaries/getLevels?tm=' + new Date().getTime(),
data: {DICTIONARIES_ID: 'dad23a464729485ba364994942db83cc'},
dataType: 'json',
success: function (res) {
_this.finiteSpaceList = res.data.list;
}
});
uni.request({
method: 'POST',
dataType: 'json',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
url: basePath + '/dictionaries/getLevels?tm=' + new Date().getTime(),
data: {DICTIONARIES_ID: 'a178357ce6ce4d6a9ac95def6aca3a14'},
dataType: 'json',
success: function (res) {
_this.riskGradeList = res.data.list;
}
});
},
// 获取用户列表
getUserList(){
var _this = this;
uni.request({
method: 'POST',
dataType: 'json',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
url: basePath + '/app/user/listUserByCorp?tm=' + new Date().getTime(),
data: {CORPINFO_ID: corpinfoId},
dataType: 'json',
success: function (res) {
_this.userList = res.data.userList;
}
});
},
// 获取有限空间列表
getLimitSpace(){
var _this = this;
uni.request({
method: 'POST',
dataType: 'json',
header: {
'Content-type': 'application/x-www-form-urlencoded'
},
url: basePath + '/app/limitspace/listAllSpace?tm=' + new Date().getTime(),
data: {CORPINFO_ID: corpinfoId},
dataType: 'json',
success: function (res) {
_this.limitSpaceList = res.data.varList;
}
});
},
guardianChange(e){
this.gindex = e.detail.value;
this.pd.GUARDIAN=this.userList[this.gindex].USER_ID;
this.pd.GUARDIANNAME=this.userList[this.gindex].USERNAME; // 操作并重置监测人员
this.jcuserList.splice(0,this.jcuserList.length);
if(this.pd.SITESUPERVISOR != this.pd.GUARDIAN){
this.jcuserList.push({"USER_ID":this.pd.SITESUPERVISOR,"USERNAME":this.pd.SITESUPERVISORNAME});
this.jcuserList.push({"USER_ID":this.pd.GUARDIAN,"USERNAME":this.pd.GUARDIANNAME});
} else {
this.jcuserList.push({"USER_ID":this.pd.GUARDIAN,"USERNAME":this.pd.GUARDIANNAME});
}
this.pd.INSPECTOR = '';
this.pd.INSPECTORNAME = '';
this.iindex = -1;
this.$forceUpdate();//强制刷新
},
sitesupervisorChange(e){
this.sindex = e.detail.value;
this.pd.SITESUPERVISOR=this.userList[this.sindex].USER_ID;
this.pd.SITESUPERVISORNAME=this.userList[this.sindex].USERNAME;
this.jcuserList.splice(0,this.jcuserList.length);
if(this.pd.SITESUPERVISOR != this.pd.GUARDIAN){
this.jcuserList.push({"USER_ID":this.pd.SITESUPERVISOR,"USERNAME":this.pd.SITESUPERVISORNAME});
this.jcuserList.push({"USER_ID":this.pd.GUARDIAN,"USERNAME":this.pd.GUARDIANNAME});
} else {
this.jcuserList.push({"USER_ID":this.pd.GUARDIAN,"USERNAME":this.pd.GUARDIANNAME});
}
// 操作并重置监测人员
this.pd.INSPECTOR = '';
this.pd.INSPECTORNAME = '';
this.iindex = -1;
this.$forceUpdate();//强制刷新
},
approverChange(e){
this.aindex = e.detail.value;
this.pd.APPROVER=this.userList[this.aindex].USER_ID;
this.pd.APPROVERNAME=this.userList[this.aindex].USERNAME;
this.$forceUpdate();//强制刷新
},
limitspaceChange(e){
this.lindex = e.detail.value;
this.pd.LIMITSPACE_ID=this.limitSpaceList[this.lindex].LIMITSPACE_ID;
this.pd.LIMITSPACENAME=this.limitSpaceList[this.lindex].NAME;
this.$forceUpdate();//强制刷新
},
inspectorChange(e){
this.iindex = e.detail.value;
this.pd.INSPECTOR=this.jcuserList[this.iindex].USER_ID;
this.pd.INSPECTORNAME=this.jcuserList[this.iindex].USERNAME;
this.$forceUpdate();//强制刷新
},
removeOther: function(id){
var _this = this;
uni.showModal({
title: '提示',
cancelText: '确认',
confirmText: '取消',
content: '确定删除气体检测单吗?',
success: function (res) {
if (res.cancel) {
uni.request({
url: basePath + "/app/gasdetection/delete", //提交接口
method: 'POST',
dataType: 'json',
header:{
'Content-type':'application/x-www-form-urlencoded'
},
data: {
GASDETECTION_ID: id
},
success: (res) => {
uni.hideLoading();
if ("success" == res.data.result) {
_this.getGasList();
uni.showToast({
icon: 'none',
title: '删除成功',
duration: 1500
});
}else{
uni.showToast({
icon:'none',
title: '系统错误',
duration: 2000
});
}
}
});
}
}
});
},
isflowClick(e){
if(e==1){
this.pd.ISFLOW = 0;
} else if(e==0){
this.pd.ISFLOW = 1;
}
},
istrainClick(e){
if(e==1){
this.pd.ISTRAIN = 0;
} else if(e==0){
this.pd.ISTRAIN = 1;
}
},
isequipmentClick(e){
if(e==1){
this.pd.ISEQUIPMENT = 0;
} else if(e==0){
this.pd.ISEQUIPMENT = 1;
}
},
isrescueClick(e){
if(e==1){
this.pd.ISRESCUE = 0;
} else if(e==0){
this.pd.ISRESCUE = 1;
}
},
isPosInt(){
if(!/^[1-9]\d*$/.test(this.pd.MAXPERSON)){
uni.showToast({
icon: 'none',
title: '请输入正整数',
duration: 1500
});
}
},
changeStartDate(e) {
this.pd.STARTTIME = e.detail.value
this.$forceUpdate();//强制刷新
},
changeInspectorTime(e) {
this.pd.INSPECTORTIME = e
this.$forceUpdate();//强制刷新
},
addGas(type){
uni.navigateTo({
url: '/pages/application/gas-detection/gas-detection-detail?type='+ type +'&LIMITSPACEAPPROVE_ID=' + this.pd.LIMITSPACEAPPROVE_ID
});
},
goSubmit() {
var _this = this;
if (!_this.pd.INSPECTORTIME || _this.pd.INSPECTORTIME == '请选择') {
uni.showToast({
icon: 'none',
title: '请填检测时间',
duration: 1500
});
return;
}
if (_this.imgList.length <= 0) {
uni.showToast({
icon: 'none',
title: '请上传手写签名',
duration: 1500
});
return;
}
uni.showModal({
title: '提示',
content: '请确定是否正确填写气体检测单,点击确认后将归档?',
cancelColor:"#000000",
cancelText: '取消',
confirmText: '确定',
success: res => {
if (res.confirm) {
uni.showLoading({
title: '请稍候'
})
var fileList = [];
for (var i = 0; i < _this.imgList.length; i++) {
if(!_this.imgList[i].id){
var file = {};
file.type = 11;
file.filePath = _this.imgList[i].filePath;
fileList.push(file);
}
}
new Promise((resolve, reject) => {
_this.submit().then(() => {resolve();})
}).then(() => {
var i=0;
_this.uploadImg(fileList,i).then(() => {resolve();})
}).then(() => {
uni.showToast({
icon:'none',
title: '保存成功',
duration: 2000
});
var pages = getCurrentPages(); // 获取当前页面栈
var prePage = pages[pages.length - 2]; // 上一个页面
// var task = prePage.$vm.list[_this.index];
if(_this.index) {
prePage.$vm.initflag = true; // A 页面 init方法 为true
// prePage.$vm.list[_this.index].ISNORMAL = 1;
// prePage.$vm.list[_this.index].HIDDEN_ID = _this.pd.HIDDEN_ID;
}
uni.navigateBack({});
uni.hideLoading();
})
}
}
})
},
submit(){
return new Promise((resolve, reject) => {
var status = 5;
uni.request({
url: basePath+'/app/limitspaceapprove/pigeonhole',
method: 'POST',
dataType: 'json',
header: {
'Content-type':'application/x-www-form-urlencoded'
},
data: {
LIMITSPACEAPPROVE_ID:this.pd.LIMITSPACEAPPROVE_ID,
STATUS:status,
CORPINFO_ID:corpinfoId,
INSPECTORTIME:this.pd.INSPECTORTIME,
USER:loginUser.USER_ID,
},
success: (res) => {
uni.hideLoading();
if ("success" == res.data.result) {
resolve();
}else{
uni.showToast({
icon:'none',
title: '系统错误',
duration: 2000
});
}
}
});
});
},
uploadImg(tempFilePaths,i){
return new Promise((resolve, reject) => {
var _this = this;
if(tempFilePaths.length==0){
resolve();
}
uni.showLoading({
title: '上传中'
})
uni.uploadFile({
url: basePath+'/app/imgfiles/add',
filePath: tempFilePaths[i].filePath,
name: 'FFILE',
formData: {
'TYPE': tempFilePaths[i].type,
'FOREIGN_KEY': _this.pd.LIMITSPACEAPPROVE_ID
},
success: (res) => {
i++;
if (tempFilePaths.length > i) {
_this.uploadImg(tempFilePaths, i);
} else {
uni.hideLoading();
resolve();
}
},
fail: (err) => {
uni.hideLoading();
uni.showModal({
content: err.errMsg,
showCancel: false
});
}
})
})
},
goToEdit(id){
uni.navigateTo({
url: '/pages/application/gas-detection/gas-detection-detail?GASDETECTION_ID='+ id
});
},
// 笔迹开始
uploadScaleStart(e) {
if (e.type != 'touchstart') return false;
let ctx = this.ctx;
ctx.setFillStyle(this.lineColor); // 初始线条设置颜色
ctx.setGlobalAlpha(this.transparent); // 设置半透明
let currentPoint = {
x: e.touches[0].x,
y: e.touches[0].y
};
let currentLine = this.currentLine;
currentLine.unshift({
time: new Date().getTime(),
dis: 0,
x: currentPoint.x,
y: currentPoint.y
});
this.currentPoint = currentPoint;
// currentLine
if (this.firstTouch) {
this.cutArea = { top: currentPoint.y, right: currentPoint.x, bottom: currentPoint.y, left: currentPoint.x };
this.firstTouch = false;
}
this.pointToLine(currentLine);
},
//图片上传
ChooseImage(e) {
var _this = this;
var ss=4-this.imgList.length;
uni.chooseImage({
count: ss, //默认9
sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
sourceType: ['camera','album'], //从相册选择
success: (res) => {
if(e==0) {
let img={};
img.id='';
img.filePath=res.tempFilePaths[0];
this.imgList.push(img)
}else{
let img={};
img.id='';
img.filePath=res.tempFilePaths[0];
this.imgList1.push(img)
}
}
});
},
ViewImage(e) {
console.info(e.currentTarget.dataset.type)
if(e.currentTarget.dataset.type==0) {
let files =[];
for(var i=0;i<this.imgList.length;i++){
files.push(this.imgList[i].filePath)
}
uni.previewImage({
urls: files,
current: e.currentTarget.dataset.url
});
}else{
let files =[];
for(var i=0;i<this.imgList1.length;i++){
files.push(this.imgList1[i].filePath)
}
uni.previewImage({
urls: files,
current: e.currentTarget.dataset.url
});
}
},
DelImg(e) {
var _this = this;
let i=e.currentTarget.dataset.index
uni.showModal({
title: '',
content: '',
cancelColor:"#000000",
cancelText: '',
confirmText: '',
success: res => {
if (res.confirm) {
if(e.currentTarget.dataset.type==0) {
if(_this.imgList[i].id) {
uni.showLoading({
title: '处理中'
})
uni.request({
url: basePath+'/app/imgfiles/delete',
method: 'POST',
dataType: 'json',
header: {
'Content-type':'application/x-www-form-urlencoded'
},
data: {
IMGFILES_ID: _this.imgList[i].id,
},
success: (res) => {
uni.hideLoading();
uni.showToast({
icon: 'none',
title: '删除成功',
duration: 1500
});
console.info("第3处")
_this.imgList.splice(i, 1)
},
fail: (err) => {
uni.hideLoading();
uni.showModal({
content: err.errMsg,
showCancel: false
});
}
})
}else {
console.info("第4处")
this.imgList.splice(e.currentTarget.dataset.index, 1)
}
}else{
if(_this.imgList1[i].id) {
uni.showLoading({
title: '处理中'
})
uni.request({
url: basePath+'/app/imgfiles/delete',
method: 'POST',
dataType: 'json',
header: {
'Content-type':'application/x-www-form-urlencoded'
},
data: {
IMGFILES_ID: _this.imgList1[i].id,
},
success: (res) => {
uni.hideLoading();
uni.showToast({
icon: 'none',
title: '删除成功',
duration: 1500
});
_this.imgList1.splice(i, 1)
},
fail: (err) => {
uni.hideLoading();
uni.showModal({
content: err.errMsg,
showCancel: false
});
}
})
}else {
this.imgList1.splice(e.currentTarget.dataset.index, 1)
}
}
}
}
})
},
hideModal(e) {
this.modalName = null
},
// 笔迹移动
uploadScaleMove(e) {
if (e.type != 'touchmove') return false;
if (e.cancelable) {
// 判断默认行为是否已经被禁用
if (!e.defaultPrevented) {
e.preventDefault();
}
}
let point = {
x: e.touches[0].x,
y: e.touches[0].y
};
//测试裁剪
if (point.y < this.cutArea.top) {
this.cutArea.top = point.y;
}
if (point.y < 0) this.cutArea.top = 0;
if (point.x > this.cutArea.right) {
this.cutArea.right = point.x;
}
if (this.canvasWidth - point.x <= 0) {
this.cutArea.right = this.canvasWidth;
}
if (point.y > this.cutArea.bottom) {
this.cutArea.bottom = point.y;
}
if (this.canvasHeight - point.y <= 0) {
this.cutArea.bottom = this.canvasHeight;
}
if (point.x < this.cutArea.left) {
this.cutArea.left = point.x;
}
if (point.x < 0) this.cutArea.left = 0;
this.lastPoint = this.currentPoint;
this.currentPoint = point;
let currentLine = this.currentLine;
currentLine.unshift({
time: new Date().getTime(),
dis: this.distance(this.currentPoint, this.lastPoint),
x: point.x,
y: point.y
});
this.pointToLine(currentLine);
},
// 笔迹结束
uploadScaleEnd(e) {
if (e.type != 'touchend') return 0;
let point = {
x: e.changedTouches[0].x,
y: e.changedTouches[0].y
};
this.lastPoint = this.currentPoint;
this.currentPoint = point;
let currentLine = this.currentLine;
currentLine.unshift({
time: new Date().getTime(),
dis: this.distance(this.currentPoint, this.lastPoint),
x: point.x,
y: point.y
});
if (currentLine.length > 2) {
var info = (currentLine[0].time - currentLine[currentLine.length - 1].time) / currentLine.length;
//$("#info").text(info.toFixed(2));
}
//一笔结束,保存笔迹的坐标点,清空,当前笔迹
//增加判断是否在手写区域;
this.pointToLine(currentLine);
var currentChirography = {
lineSize: this.lineSize,
lineColor: this.lineColor
};
var chirography = this.chirography;
chirography.unshift(currentChirography);
this.chirography = chirography;
var linePrack = this.linePrack;
linePrack.unshift(this.currentLine);
this.linePrack = linePrack;
this.currentLine = [];
},
retDraw() {
this.ctx.clearRect(0, 0, 700, 730);
this.ctx.draw();
//设置canvas背景
this.setCanvasBg('#fff');
},
//画两点之间的线条;参数为:line会绘制最近的开始的两个点
pointToLine(line) {
this.calcBethelLine(line);
return;
},
//计算插值的方式;
calcBethelLine(line) {
if (line.length <= 1) {
line[0].r = this.radius;
return;
}
let x0,
x1,
x2,
y0,
y1,
y2,
r0,
r1,
r2,
len,
lastRadius,
dis = 0,
time = 0,
curveValue = 0.5;
if (line.length <= 2) {
x0 = line[1].x;
y0 = line[1].y;
x2 = line[1].x + (line[0].x - line[1].x) * curveValue;
y2 = line[1].y + (line[0].y - line[1].y) * curveValue;
//x2 = line[1].x;
//y2 = line[1].y;
x1 = x0 + (x2 - x0) * curveValue;
y1 = y0 + (y2 - y0) * curveValue;
} else {
x0 = line[2].x + (line[1].x - line[2].x) * curveValue;
y0 = line[2].y + (line[1].y - line[2].y) * curveValue;
x1 = line[1].x;
y1 = line[1].y;
x2 = x1 + (line[0].x - x1) * curveValue;
y2 = y1 + (line[0].y - y1) * curveValue;
}
//从计算公式看,三个点分别是(x0,y0),(x1,y1),(x2,y2) (x1,y1)这个是控制点,控制点不会落在曲线上;实际上,这个点还会手写获取的实际点,却落在曲线上
len = this.distance({ x: x2, y: y2 }, { x: x0, y: y0 });
lastRadius = this.radius;
for (let n = 0; n < line.length - 1; n++) {
dis += line[n].dis;
time += line[n].time - line[n + 1].time;
if (dis > this.smoothness) break;
}
this.radius = Math.min((time / len) * this.pressure + this.lineMin, this.lineMax) * this.lineSize;
line[0].r = this.radius;
//计算笔迹半径;
if (line.length <= 2) {
r0 = (lastRadius + this.radius) / 2;
r1 = r0;
r2 = r1;
//return;
} else {
r0 = (line[2].r + line[1].r) / 2;
r1 = line[1].r;
r2 = (line[1].r + line[0].r) / 2;
}
let n = 5;
let point = [];
for (let i = 0; i < n; i++) {
let t = i / (n - 1);
let x = (1 - t) * (1 - t) * x0 + 2 * t * (1 - t) * x1 + t * t * x2;
let y = (1 - t) * (1 - t) * y0 + 2 * t * (1 - t) * y1 + t * t * y2;
let r = lastRadius + ((this.radius - lastRadius) / n) * i;
point.push({ x: x, y: y, r: r });
if (point.length == 3) {
let a = this.ctaCalc(point[0].x, point[0].y, point[0].r, point[1].x, point[1].y, point[1].r, point[2].x, point[2].y, point[2].r);
a[0].color = this.lineColor;
// let bethelPoint = this.bethelPoint;
// bethelPoint = bethelPoint.push(a);
this.bethelDraw(a, 1);
point = [{ x: x, y: y, r: r }];
}
}
this.currentLine = line;
},
//求两点之间距离
distance(a, b) {
let x = b.x - a.x;
let y = b.y - a.y;
return Math.sqrt(x * x + y * y);
},
ctaCalc(x0, y0, r0, x1, y1, r1, x2, y2, r2) {
let a = [],
vx01,
vy01,
norm,
n_x0,
n_y0,
vx21,
vy21,
n_x2,
n_y2;
vx01 = x1 - x0;
vy01 = y1 - y0;
norm = Math.sqrt(vx01 * vx01 + vy01 * vy01 + 0.0001) * 2;
vx01 = (vx01 / norm) * r0;
vy01 = (vy01 / norm) * r0;
n_x0 = vy01;
n_y0 = -vx01;
vx21 = x1 - x2;
vy21 = y1 - y2;
norm = Math.sqrt(vx21 * vx21 + vy21 * vy21 + 0.0001) * 2;
vx21 = (vx21 / norm) * r2;
vy21 = (vy21 / norm) * r2;
n_x2 = -vy21;
n_y2 = vx21;
a.push({ mx: x0 + n_x0, my: y0 + n_y0, color: '#1A1A1A' });
a.push({ c1x: x1 + n_x0, c1y: y1 + n_y0, c2x: x1 + n_x2, c2y: y1 + n_y2, ex: x2 + n_x2, ey: y2 + n_y2 });
a.push({ c1x: x2 + n_x2 - vx21, c1y: y2 + n_y2 - vy21, c2x: x2 - n_x2 - vx21, c2y: y2 - n_y2 - vy21, ex: x2 - n_x2, ey: y2 - n_y2 });
a.push({ c1x: x1 - n_x2, c1y: y1 - n_y2, c2x: x1 - n_x0, c2y: y1 - n_y0, ex: x0 - n_x0, ey: y0 - n_y0 });
a.push({ c1x: x0 - n_x0 - vx01, c1y: y0 - n_y0 - vy01, c2x: x0 + n_x0 - vx01, c2y: y0 + n_y0 - vy01, ex: x0 + n_x0, ey: y0 + n_y0 });
a[0].mx = a[0].mx.toFixed(1);
a[0].mx = parseFloat(a[0].mx);
a[0].my = a[0].my.toFixed(1);
a[0].my = parseFloat(a[0].my);
for (let i = 1; i < a.length; i++) {
a[i].c1x = a[i].c1x.toFixed(1);
a[i].c1x = parseFloat(a[i].c1x);
a[i].c1y = a[i].c1y.toFixed(1);
a[i].c1y = parseFloat(a[i].c1y);
a[i].c2x = a[i].c2x.toFixed(1);
a[i].c2x = parseFloat(a[i].c2x);
a[i].c2y = a[i].c2y.toFixed(1);
a[i].c2y = parseFloat(a[i].c2y);
a[i].ex = a[i].ex.toFixed(1);
a[i].ex = parseFloat(a[i].ex);
a[i].ey = a[i].ey.toFixed(1);
a[i].ey = parseFloat(a[i].ey);
}
return a;
},
bethelDraw(point, is_fill, color) {
let ctx = this.ctx;
ctx.beginPath();
ctx.moveTo(point[0].mx, point[0].my);
if (undefined != color) {
ctx.setFillStyle(color);
ctx.setStrokeStyle(color);
} else {
ctx.setFillStyle(point[0].color);
ctx.setStrokeStyle(point[0].color);
}
for (let i = 1; i < point.length; i++) {
ctx.bezierCurveTo(point[i].c1x, point[i].c1y, point[i].c2x, point[i].c2y, point[i].ex, point[i].ey);
}
ctx.stroke();
if (undefined != is_fill) {
ctx.fill(); //填充图形 ( 后绘制的图形会覆盖前面的图形, 绘制时注意先后顺序 )
}
ctx.draw(true);
},
selectColorEvent(str,color) {
this.selectColor = str;
this.lineColor = color;
},
//将Canvas内容转成 临时图片 --> cb 为回调函数 形参 tempImgPath 为 生成的图片临时路径
canvasToImg(cb) {
//这种写法移动端 出不来
this.ctx.draw(true, () => {
uni.canvasToTempFilePath({
canvasId: 'handWriting',
fileType: 'png',
quality: 1, //图片质量
success(res) {
// console.log(res.tempFilePath, 'canvas生成图片地址');
uni.showToast({
title: '执行了吗?'
});
cb(res.tempFilePath);
}
});
});
},
//完成
subCanvas() {
var _this = this;
this.ctx.draw(true, () => {
uni.canvasToTempFilePath({
canvasId: 'handWriting',
fileType: 'jpg',
quality: 1, //图片质量
destWidth:900,
destHeight:435,
success(res) {
console.info("第一处")
_this.imgList.splice(0,_this.imgList.length);
let img={};
img.id='';
img.filePath=res.tempFilePath;
console.info(img.filePath);
_this.imgList.push(img)
// console.log(res.tempFilePath, 'canvas生成图片地址');
// uni.showToast({
// title: '以保存'
// });
_this.hideModal();
_this.retDraw();
// //保存到系统相册
// uni.saveImageToPhotosAlbum({
// filePath: res.tempFilePath,
// success(res) {
// uni.showToast({
// title: '已成功保存到相册',
// duration: 2000
// });
// }
// });
}
});
});
},
//保存到相册
saveCanvasAsImg() {
/*
this.canvasToImg( tempImgPath=>{
// console.log(tempImgPath, '临时路径');
uni.saveImageToPhotosAlbum({
filePath: tempImgPath,
success(res) {
uni.showToast({
title: '已保存到相册',
duration: 2000
});
}
})
} );
*/
uni.canvasToTempFilePath({
canvasId: 'handWriting',
fileType: 'png',
quality: 1, //图片质量
success(res) {
// console.log(res.tempFilePath, 'canvas生成图片地址');
uni.saveImageToPhotosAlbum({
filePath: res.tempFilePath,
success(res) {
uni.showToast({
title: '已保存到相册',
duration: 2000
});
}
});
}
});
},
//预览
previewCanvasImg() {
uni.canvasToTempFilePath({
canvasId: 'handWriting',
fileType: 'jpg',
quality: 1, //图片质量
success(res) {
// console.log(res.tempFilePath, 'canvas生成图片地址');
uni.previewImage({
urls: [res.tempFilePath] //预览图片 数组
});
}
});
/* //移动端出不来 ^~^
this.canvasToImg( tempImgPath=>{
uni.previewImage({
urls: [tempImgPath], //预览图片 数组
})
} );
*/
},
//上传
uploadCanvasImg() {
uni.canvasToTempFilePath({
canvasId: 'handWriting',
fileType: 'png',
quality: 1, //图片质量
success(res) {
// console.log(res.tempFilePath, 'canvas生成图片地址');
//上传
uni.uploadFile({
url: 'https://example.weixin.qq.com/upload', // 仅为示例,非真实的接口地址
filePath: res.tempFilePath,
name: 'file_signature',
formData: {
user: 'test'
},
success(res) {
const data = res.data;
// do something
}
});
}
});
},
//设置canvas背景色 不设置 导出的canvas的背景为透明
//@params字符串 color
setCanvasBg(color) {
/* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
//rect() 参数说明 矩形路径左上角的横坐标,左上角的纵坐标, 矩形路径的宽度, 矩形路径的高度
//这里是 canvasHeight - 4 是因为下边盖住边框了,所以手动减了写
this.ctx.rect(0, 0, this.canvasWidth, this.canvasHeight - 4);
// ctx.setFillStyle('red')
this.ctx.setFillStyle(color);
this.ctx.fill(); //设置填充
this.ctx.draw(); //开画
}
}
}
</script>
<style>
.prevent {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
overflow: hidden;
}
.cu-form-title{
padding: 20upx 0;
}
.cu-form-textarea{
background-color: #ffffff;
padding: 1upx 30upx 20upx;
min-height: 100upx;
}
.cu-form-textarea textarea {
height: 4.6em;
width: 100%;
line-height: 1.2em;
flex: 1;
font-size: 28upx;
padding: 0;
}
.selected{
display: flex;
align-items: center;
height: 100upx;
}
.selected .radio{
transform:scale(0.8);
margin-right: 10upx;
}
.group{
display: flex;
align-items: center;
}
.cu-form-group .title{
font-size: 28upx;
color: #666;
}
.cu-bar .action:first-child {
font-size: 28upx;
}
.wrapper {
width: 100%;
height: 24vh;
margin: 0;
overflow: hidden;
display: flex;
align-content: center;
flex-direction: row;
justify-content: center;
font-size: 28rpx;
}
.handWriting {
background: #fff;
width: 100%;
height: 100%;
}
.handRight {
display: inline-flex;
align-items: center;
}
.handCenter {
border: 4rpx dashed #e9e9e9;
flex: 5;
overflow: hidden;
box-sizing: border-box;
}
.handBtn button {
font-size: 28rpx;
}
.handBtn {
height: 95vh;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
align-content: space-between;
flex: 1;
}
.delBtn {
position: absolute;
top: 250rpx;
left: 0rpx;
color: #666;
}
.delBtn image {
position: absolute;
top: 13rpx;
left: 25rpx;
}
.subBtn {
/* position: absolute; */
bottom: 0rpx;
left: -32rpx;
display: inline-flex;
background: #008ef6;
color: #fff;
margin-bottom: 30rpx;
text-align: center;
justify-content: center;
}
/*Peach - 新增 - 保存*/
.saveBtn {
position: absolute;
top: 375rpx;
left: 0rpx;
color: #666;
}
.previewBtn {
position: absolute;
top: 500rpx;
left: 0rpx;
color: #666;
}
.uploadBtn {
position: absolute;
top: 625rpx;
left: 0rpx;
color: #666;
}
/*Peach - 新增 - 保存*/
.black-select {
width: 60rpx;
height: 60rpx;
position: absolute;
top: 30rpx;
left: 25rpx;
}
.black-select.color_select {
width: 90rpx;
height: 90rpx;
top: 100rpx;
left: 10rpx;
}
.red-select {
width: 60rpx;
height: 60rpx;
position: absolute;
top: 140rpx;
left: 25rpx;
}
.red-select.color_select {
width: 90rpx;
height: 90rpx;
top: 120rpx;
left: 10rpx;
}
</style>