dev4
Panzihang 2023-11-13 10:11:34 +08:00
parent 50c0452f43
commit 62c351d1f1
43 changed files with 3190 additions and 1181 deletions

View File

@ -406,7 +406,10 @@
border-radius: 1px; border-radius: 1px;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
position: relative; position: fixed;
top: 0;
left: 0;
z-index: 999;
.infoLeft { .infoLeft {
display: flex; display: flex;

View File

@ -19,7 +19,8 @@
}, },
/* */ /* */
"modules" : { "modules" : {
"SQLite" : {} "SQLite" : {},
"Camera" : {}
}, },
/* */ /* */
"distribute" : { "distribute" : {

View File

@ -261,6 +261,12 @@
"navigationBarTitleText": "质损详情" "navigationBarTitleText": "质损详情"
} }
}, },
{
"path": "pages/quality/zsEdit",
"style": {
"navigationBarTitleText": "绘制残损图"
}
},
{ {
"path": "pages/quality/sign", "path": "pages/quality/sign",
"style": { "style": {

View File

@ -9,7 +9,8 @@
placeholder="请选择贸易类型" v-model="tradeName" @select="tradeSelect"></superwei-combox> placeholder="请选择贸易类型" v-model="tradeName" @select="tradeSelect"></superwei-combox>
</uni-easyinput> </uni-easyinput>
<superwei-combox class="input" :candidates="shipList" :isJSON="true" keyName="vvyShip" <superwei-combox class="input" :candidates="shipList" :isJSON="true" keyName="vvyShip"
placeholder="请选择船名/航次" v-model="vvyShip" @select="shipSelect"></superwei-combox> placeholder="请选择船名/航次" v-model="vvyShip" @select="shipSelect"
@input="shipInput"></superwei-combox>
</uni-easyinput> </uni-easyinput>
<button class="btn" @click="onSearch"></button> <button class="btn" @click="onSearch"></button>
</view> </view>
@ -52,10 +53,10 @@
</template> </template>
<o-empty v-else height="70vh" bg="#f5f6fa" /> <o-empty v-else height="70vh" bg="#f5f6fa" />
</view> </view>
<view class="pageBox" v-if="itemList.length > 0"> <!-- <view class="pageBox" v-if="itemList.length > 0">
<uni-pagination :show-icon="true" :total="total" :pageSize="pageSize" :current="current" <uni-pagination :show-icon="true" :total="total" :pageSize="pageSize" :current="current"
@change="changePage" /> @change="changePage" />
</view> </view> -->
</view> </view>
</view> </view>
</view> </view>
@ -86,6 +87,7 @@
vvyId: "", vvyId: "",
shipId: "", shipId: "",
shipName: '', shipName: '',
shipValue: "",
shipList: [], shipList: [],
// //
@ -102,6 +104,10 @@
this.loginObj = uni.getStorageSync('loginObj') this.loginObj = uni.getStorageSync('loginObj')
this.getShip() this.getShip()
}, },
onReachBottom() {
this.current++
this.initData()
},
onBackPress(options) { onBackPress(options) {
// uni.navigateBack 使 // uni.navigateBack 使
if (options.from == 'backbutton') { if (options.from == 'backbutton') {
@ -134,6 +140,11 @@
this.vvyId = e.vvyId this.vvyId = e.vvyId
this.vvyShip = e.vvyShip this.vvyShip = e.vvyShip
}, },
//
shipInput(e) {
this.shipValue = e
this.getShip()
},
// //
getShip() { getShip() {
if (this.tradeName == '外贸') { if (this.tradeName == '外贸') {
@ -145,7 +156,7 @@
let key = "" let key = ""
let spmId = "" let spmId = ""
uni.request({ uni.request({
url: `${this.$local}/api/shipInstructions/queryByKey?ieType=${ieType}&key=${ieType}&pamId=${this.portObj.portId}&spmId=${spmId}&tradeType=${this.tradeType}`, url: `${this.$local}/api/shipInstructions/queryByKey?ieType=${ieType}&key=${this.shipValue}&pamId=${this.portObj.portId}&spmId=${spmId}&tradeType=${this.tradeType}`,
header: { header: {
'Content-Type': 'application/json', // 'Content-Type': 'application/json', //
'Authorization': `Bearer ${this.loginObj.access_token}` 'Authorization': `Bearer ${this.loginObj.access_token}`
@ -182,7 +193,7 @@
method: 'GET', // method: 'GET', //
success: (res) => { success: (res) => {
this.total = res.data.data.total this.total = res.data.data.total
this.itemList = res.data.data.records this.itemList.push(...res.data.data.records)
} }
}) })
}, },
@ -206,18 +217,22 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container {
display: flex;
}
.content { .content {
flex: 1;
padding: 20px; padding: 20px;
min-height: calc(100vh - 68px - 40px); min-height: calc(100vh - 68px - 40px);
margin-top: 66px;
margin-bottom: 20px;
.form { .form {
width: 100%;
height: 50px;
background: #f5f6fa;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
position: fixed;
top: 66px;
right: 0;
z-index: 999;
.end { .end {
display: flex; display: flex;
@ -229,6 +244,7 @@
line-height: 35px; line-height: 35px;
padding-left: 10px; padding-left: 10px;
margin-right: 15px; margin-right: 15px;
margin-top: 8px;
} }
.btn { .btn {
@ -239,6 +255,7 @@
color: #fff; color: #fff;
background-color: #0067CF; background-color: #0067CF;
margin-right: 10px; margin-right: 10px;
margin-top: 8px;
} }
} }
@ -250,12 +267,11 @@
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
position: relative; position: relative;
margin-top: 15px; margin-top: 40px;
gap: 16px; gap: 16px;
/deep/.o-empty { /deep/.o-empty {
width: 100%; width: 100%;
margin-top: 15px;
} }
.item { .item {
@ -296,12 +312,20 @@
font-size: 16px; font-size: 16px;
.nitem { .nitem {
width: 46%; // width: 49%;
.text { .text {
color: #929292; color: #929292;
} }
} }
.nitem:nth-of-type(2n) {
width: 35%;
}
.nitem:nth-of-type(2n - 1) {
width: 63%;
}
} }
.status { .status {
@ -324,7 +348,16 @@
} }
.pageBox { .pageBox {
width: 100%;
height: 50px;
background-color: #fff;
margin-top: 20px; margin-top: 20px;
position: fixed;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: center;
} }
} }
</style> </style>

View File

@ -2,24 +2,37 @@
<view class="app"> <view class="app">
<head-view title="卸船指令"></head-view> <head-view title="卸船指令"></head-view>
<view class="content contentFixed"> <view class="content contentFixed">
<view class="buttonlist">
<template v-if="tabsValue == 0">
<button class="button" type="default" @click="ask"></button>
<button class="button" type="default" @click="distribute('center','all')"></button>
</template>
<template v-if="tabsValue == 1">
<button class="button" type="default" @click="distribute('center','solo')"></button>
</template>
<template v-if="tabsValue == 2">
<button class="button" type="default" @click="ask"></button>
</template>
</view>
<custom-tabs type="c1" :value="tabsValue" @change="changeTabs"> <custom-tabs type="c1" :value="tabsValue" @change="changeTabs">
<custom-tab-pane label="总指令" name="c1_1"> <custom-tab-pane label="总指令" name="c1_1">
<view></view> <view></view>
<view class="main"> <view class="main">
<view class="form"> <view class="form">
<view class="inputBox"> <view class="inputBox">
<uni-easyinput class="uni-mt-5" suffixIcon="search" v-model="mnfBl" <view class="leftInput">
placeholder="船名/航次/提单号" @iconClick="search"></uni-easyinput> <uni-easyinput class="uni-mt-5" suffixIcon="search" v-model="mnfBl"
<superwei-combox class="input" :candidates="brandList" :isJSON="true" keyName="brdName" placeholder="船名/航次/提单号" @iconClick="search"></uni-easyinput>
placeholder="品牌" v-model="brdName" @select="brandSelect"></superwei-combox> </view>
<superwei-combox class="input" :candidates="bvmList" :isJSON="true" keyName="name" <view class="rightInput">
placeholder="车型" v-model="bvmName" @select="bvmSelect"></superwei-combox> <superwei-combox class="input" :candidates="brandList" :isJSON="true"
keyName="brdName" placeholder="品牌" v-model="brdName"
@select="brandSelect"></superwei-combox>
<superwei-combox class="input" :candidates="bvmList" :isJSON="true" keyName="name"
placeholder="车型" v-model="bvmName" @select="bvmSelect"></superwei-combox>
</view>
</view> </view>
</view> </view>
<view class="buttonlist">
<button class="button" type="default" @click="distribute('center','all')"></button>
<button class="button" type="default" @click="ask"></button>
</view>
<view class="tjList"> <view class="tjList">
<view class="tjHead" @click="clickTjHead('zzl')"> <view class="tjHead" @click="clickTjHead('zzl')">
<view class="title"> <view class="title">
@ -104,6 +117,10 @@
<text>备件数量</text> <text>备件数量</text>
<text>{{item.sparePartsCount}}</text> <text>{{item.sparePartsCount}}</text>
</view> </view>
<view class="col">
<text>总指令发送人</text>
<text>{{item.totalSendUser}}</text>
</view>
</view> </view>
<view class="rowInfo"> <view class="rowInfo">
<view class="col"> <view class="col">
@ -115,12 +132,6 @@
<text>{{item.totalSendTime}}</text> <text>{{item.totalSendTime}}</text>
</view> </view>
</view> </view>
<view class="rowInfo">
<view class="col">
<text>总指令发送人</text>
<text>{{item.totalSendUser}}</text>
</view>
</view>
</view> </view>
<view class="expand" v-if="itemActive != index" @click="isActive(index)"> <view class="expand" v-if="itemActive != index" @click="isActive(index)">
展开 展开
@ -174,18 +185,21 @@
<view class="main"> <view class="main">
<view class="form"> <view class="form">
<view class="inputBox"> <view class="inputBox">
<uni-easyinput class="uni-mt-5" suffixIcon="search" v-model="mnfBl" <view class="leftInput">
placeholder="船名/航次/提单号" @iconClick="search"></uni-easyinput> <uni-easyinput class="uni-mt-5" suffixIcon="search" v-model="mnfBl"
<superwei-combox class="input" :candidates="brandList" :isJSON="true" keyName="brdName" placeholder="船名/航次/提单号" @iconClick="search"></uni-easyinput>
placeholder="品牌" v-model="brdName" @select="brandSelect"></superwei-combox> </view>
<superwei-combox class="input" :candidates="bvmList" :isJSON="true" keyName="bvmName" <view class="rightInput">
placeholder="车型" v-model="bvmName" @select="bvmSelect"></superwei-combox> <superwei-combox class="input" :candidates="sendList" :isJSON="true" keyName="text"
placeholder="发送状态" v-model="sendText" @select="sendSelect"></superwei-combox>
<superwei-combox class="input" :candidates="brandList" :isJSON="true"
keyName="brdName" placeholder="品牌" v-model="brdName"
@select="brandSelect"></superwei-combox>
<superwei-combox class="input" :candidates="bvmList" :isJSON="true" keyName="name"
placeholder="车型" v-model="bvmName" @select="bvmSelect"></superwei-combox>
</view>
</view> </view>
</view> </view>
<view class="buttonlist">
<button class="button" type="default" @click="distribute('center','solo','')"></button>
<button class="button" type="default" @click="ask"></button>
</view>
<view class="tjList"> <view class="tjList">
<view class="tjHead" @click="clickTjHead('fzl')"> <view class="tjHead" @click="clickTjHead('fzl')">
<view class="title"> <view class="title">
@ -225,251 +239,119 @@
</view> </view>
</template> </template>
</view> </view>
<custom-tabs type="c2" :value="tabsValue2" @change="changeTabs2"> <template v-if="itemList.length > 0">
<custom-tab-pane label="未发送" name="c2_1"> <checkbox-group @change="checkChange">
<template v-if="itemList.length > 0"> <view class="itemList">
<checkbox-group @change="checkChange"> <view class="exp" v-for="(item,index) in itemList" :key="item.ndex">
<view class="itemList"> <view class="item">
<view class="exp" v-for="(item,index) in itemList" :key="item.ndex"> <view class="row">
<view class="item"> <view class="title">
<view class="row"> <view class="rowHead">
<view class="title"> <checkbox :value="item.lwpId" :checked="false" />
<view class="rowHead">
<checkbox :value="item.lwpId" :checked="false" />
</view>
<image class="titleImg" src="../../static/images/zlIcon.png"
mode="widthFix">
</image>
<view class="text">
品牌{{item.brdName}}
</view>
</view>
<view class="schedule">
<text class="text">卸船进度</text>
<view class="progressBox">
<van-progress color="#0067CF" stroke-width="6px"
:show-pivot="false" track-color="#DEE9F5"
:percentage="itemSum(item.loadingProgress.workProgress, item.loadingProgress.totalProgress)" />
</view>
<text>{{itemSum(item.loadingProgress.workProgress, item.loadingProgress.totalProgress)}}%</text>
</view>
<view class="planStatus planStatus0"
v-if="item.branchPlanStatus == 0">
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
<view class="planStatus planStatus3"
v-else-if="item.branchPlanStatus == 2">
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
<view class="planStatus planStatus5"
v-else-if="item.branchPlanStatus == 4">
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
<view class="planStatus planStatus1" v-else>
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
</view> </view>
<view class="row"> <image class="titleImg" src="../../static/images/zlIcon.png"
<view class="rowInfo"> mode="widthFix">
<view class="col"> </image>
<text>车辆数量</text> <view class="text">
<text>{{item.vehicleCount}}</text> 品牌{{item.brdName}}
</view>
<view class="col">
<text>备件数量</text>
<text>{{item.sparePartsCount}}</text>
</view>
</view>
<view class="rowInfo">
<view class="col">
<text>负责人</text>
<text>{{item.responsiblePerson}}</text>
</view>
<view class="col">
<text>发送时间</text>
<text>{{item.totalSendTime}}</text>
</view>
</view>
<view class="rowInfo">
<view class="col">
<text>分指令发送人</text>
<text>{{item.totalSendUser}}</text>
</view>
</view>
</view>
<view class="xfBtn">
<view class="btn" @click="distribute('center','solo',item)">
</view>
</view>
<view class="expand" v-if="itemActive != index"
@click="isActive(index)">
展开
</view>
<view class="expand" v-else @click="itemActive = '-1'">
收起
</view> </view>
</view> </view>
<view class="details"> <view class="schedule">
<view class="itemDetails" v-show="itemActive == index"> <text class="text">卸船进度</text>
<template v-for="(item2,index2) in item.infoList"> <view class="progressBox">
<view class="detailsBox" :key="index2"> <van-progress color="#0067CF" stroke-width="6px"
<view class="title"> :show-pivot="false" track-color="#DEE9F5"
<text>{{item2.mnfBl}}</text> :percentage="itemSum(item.loadingProgress.workProgress, item.loadingProgress.totalProgress)" />
<button @click="toDetails(item,item2)"></button> </view>
</view> <text>{{itemSum(item.loadingProgress.workProgress, item.loadingProgress.totalProgress)}}%</text>
<view class="info"> </view>
<view class="cell"> <view class="planStatus planStatus0" v-if="item.branchPlanStatus == 0">
<text>中转港</text> <text class="text">{{item.branchPlanStatusDesc}}</text>
<text>{{item2.transitPortName}}</text> </view>
</view> <view class="planStatus planStatus3"
<view class="cell"> v-else-if="item.branchPlanStatus == 2">
<text>品牌</text> <text class="text">{{item.branchPlanStatusDesc}}</text>
<text>{{item2.brdName}}</text> </view>
</view> <view class="planStatus planStatus5"
<view class="cell"> v-else-if="item.branchPlanStatus == 4">
<text>车型</text> <text class="text">{{item.branchPlanStatusDesc}}</text>
<text>{{item2.goodsTypeName}}</text> </view>
</view> <view class="planStatus planStatus1" v-else>
<view class="cell"> <text class="text">{{item.branchPlanStatusDesc}}</text>
<text>型号</text> </view>
<text>{{item2.bvdName}}</text> </view>
</view> <view class="row">
</view> <view class="rowInfo">
</view> <view class="col">
</template> <text>车辆数量</text>
<text>{{item.vehicleCount}}</text>
</view>
<view class="col">
<text>备件数量</text>
<text>{{item.sparePartsCount}}</text>
</view>
<view class="col">
<text>分指令发送人</text>
<text>{{item.totalSendUser}}</text>
</view>
</view>
<view class="rowInfo">
<view class="col">
<text>负责人</text>
<text>{{item.responsiblePerson}}</text>
</view>
<view class="col">
<text>发送时间</text>
<text>{{item.totalSendTime}}</text>
</view> </view>
</view> </view>
</view> </view>
</view> <view class="xfBtn">
</checkbox-group> <view class="btn" @click="distribute('center','solo',item)">
</template>
<o-empty v-else height="70vh" bg="#f5f6fa" />
</custom-tab-pane>
<custom-tab-pane label="已发送" name="c2_2">
<template v-if="itemList.length > 0">
<checkbox-group @change="checkChange">
<view class="itemList">
<view class="exp" v-for="(item,index) in itemList" :key="item.ndex">
<view class="item">
<view class="row">
<view class="title">
<view class="rowHead">
<checkbox :value="item.lwpId" :checked="false" />
</view>
<image class="titleImg" src="../../static/images/zlIcon.png"
mode="widthFix">
</image>
<view class="text">
品牌{{item.brdName}}
</view>
</view>
<view class="schedule">
<text class="text">卸船进度</text>
<view class="progressBox">
<van-progress color="#0067CF" stroke-width="6px"
:show-pivot="false" track-color="#DEE9F5"
:percentage="itemSum(item.loadingProgress.workProgress, item.loadingProgress.totalProgress)" />
</view>
<text>{{itemSum(item.loadingProgress.workProgress, item.loadingProgress.totalProgress)}}%</text>
</view>
<view class="planStatus planStatus0"
v-if="item.branchPlanStatus == 0">
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
<view class="planStatus planStatus3"
v-else-if="item.branchPlanStatus == 2">
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
<view class="planStatus planStatus5"
v-else-if="item.branchPlanStatus == 4">
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
<view class="planStatus planStatus1" v-else>
<text class="text">{{item.branchPlanStatusDesc}}</text>
</view>
</view>
<view class="row">
<view class="rowInfo">
<view class="col">
<text>车辆数量</text>
<text>{{item.vehicleCount}}</text>
</view>
<view class="col">
<text>备件数量</text>
<text>{{item.sparePartsCount}}</text>
</view>
</view>
<view class="rowInfo">
<view class="col">
<text>负责人</text>
<text>{{item.responsiblePerson}}</text>
</view>
<view class="col">
<text>发送时间</text>
<text>{{item.totalSendTime}}</text>
</view>
</view>
<view class="rowInfo">
<view class="col">
<text>分指令发送人</text>
<text>{{item.totalSendUser}}</text>
</view>
</view>
</view>
<view class="xfBtn">
<view class="btn stopbtn" @click="suspend(item)"
v-if="item.branchPlanStatus != 4">暂停
</view>
<view class="btn stopbtn"
@click="distribute('center','again',item)"
v-if="item.branchPlanStatus == 4">重新发送
</view>
</view>
<view class="expand" v-if="itemActive != index"
@click="isActive(index)">
展开
</view>
<view class="expand" v-else @click="itemActive = '-1'">
收起
</view>
</view>
<view class="details">
<view class="itemDetails" v-show="itemActive == index">
<template v-for="(item2,index2) in item.infoList">
<view class="detailsBox" :key="index2">
<view class="title">
<text>{{item2.mnfBl}}</text>
<button @click="toDetails(item,item2)"></button>
</view>
<view class="info">
<view class="cell">
<text>中转港</text>
<text>{{item2.transitPortName}}</text>
</view>
<view class="cell">
<text>品牌</text>
<text>{{item2.brdName}}</text>
</view>
<view class="cell">
<text>车型</text>
<text>{{item2.goodsTypeName}}</text>
</view>
<view class="cell">
<text>型号</text>
<text>{{item2.bvdName}}</text>
</view>
</view>
</view>
</template>
</view>
</view> </view>
</view> </view>
<view class="expand" v-if="itemActive != index" @click="isActive(index)">
展开
</view>
<view class="expand" v-else @click="itemActive = '-1'">
收起
</view>
</view> </view>
</checkbox-group> <view class="details">
</template> <view class="itemDetails" v-show="itemActive == index">
<o-empty v-else height="70vh" bg="#f5f6fa" /> <template v-for="(item2,index2) in item.infoList">
</custom-tab-pane> <view class="detailsBox" :key="index2">
</custom-tabs> <view class="title">
<text>{{item2.mnfBl}}</text>
<button @click="toDetails(item,item2)"></button>
</view>
<view class="info">
<view class="cell">
<text>中转港</text>
<text>{{item2.transitPortName}}</text>
</view>
<view class="cell">
<text>品牌</text>
<text>{{item2.brdName}}</text>
</view>
<view class="cell">
<text>车型</text>
<text>{{item2.goodsTypeName}}</text>
</view>
<view class="cell">
<text>型号</text>
<text>{{item2.bvdName}}</text>
</view>
</view>
</view>
</template>
</view>
</view>
</view>
</view>
</checkbox-group>
</template>
<o-empty v-else height="70vh" bg="#f5f6fa" />
<view class="pageBox" v-if="itemList.length > 0"> <view class="pageBox" v-if="itemList.length > 0">
<uni-pagination :show-icon="true" :total="total" :pageSize="pageSize" :current="current" <uni-pagination :show-icon="true" :total="total" :pageSize="pageSize" :current="current"
@change="changePage" /> @change="changePage" />
@ -489,9 +371,6 @@
placeholder="车型" v-model="bvmName" @select="bvmSelect"></superwei-combox> placeholder="车型" v-model="bvmName" @select="bvmSelect"></superwei-combox>
</view> </view>
</view> </view>
<view class="buttonlist">
<button class="button" type="default" @click="ask"></button>
</view>
<template v-if="itemList.length > 0"> <template v-if="itemList.length > 0">
<view class="itemList"> <view class="itemList">
<view class="exp" v-for="(item,index) in itemList" :key="item.ndex"> <view class="exp" v-for="(item,index) in itemList" :key="item.ndex">
@ -762,13 +641,13 @@
<view class="popupBtn"> <view class="popupBtn">
<view class="btnList"> <view class="btnList">
<button class="button" type="default" @click="zlCancel"> </button> <button class="button" type="default" @click="zlCancel"> </button>
<button class="button" type="primary" @click="zlConfirm"></button> <button class="button" type="primary" @click="zlConfirm"></button>
</view> </view>
</view> </view>
</view> </view>
</uni-popup> </uni-popup>
<uni-popup ref="popup2" type="dialog"> <uni-popup ref="popup2" type="dialog">
<view class="popupBox"> <view class="popupBox popupBox2">
<view class="popupTitle"> <view class="popupTitle">
卸船要求 卸船要求
</view> </view>
@ -804,6 +683,16 @@
mnfBl: '', // mnfBl: '', //
mnfBlItem: {}, mnfBlItem: {},
mnfBlList: [], mnfBlList: [],
//
sendList: [{
vale: "1",
text: "已发送"
}, {
vale: "0",
text: "未发送"
}],
sendValue: "",
sendText: "",
// //
brdId: '', brdId: '',
brdName: '', brdName: '',
@ -866,14 +755,14 @@
// //
total: 0, total: 0,
pageSize: 5, pageSize: 4,
current: 1, current: 1,
} }
}, },
computed: { computed: {
itemSum() { itemSum() {
return function(item, item2) { return function(item, item2) {
let sum = ((item / item2) * 100).toFixed(2) let sum = ((item / item2) * 100).toFixed(1)
return sum return sum
}; };
}, },
@ -1003,7 +892,7 @@
success: (res) => { success: (res) => {
console.log(res) console.log(res)
this.itemList = res.data.data.records this.itemList = res.data.data.records
this.total = this.itemList.length this.total = res.data.data.total
this.itemList.forEach((v, index) => { this.itemList.forEach((v, index) => {
// if (v.branchPlanStatus == 0) { // if (v.branchPlanStatus == 0) {
this.zzlLwpIdList.push(v.lwpId) this.zzlLwpIdList.push(v.lwpId)
@ -1021,10 +910,9 @@
let teamFlag = "" let teamFlag = ""
if (this.tabsValue == 2) { if (this.tabsValue == 2) {
teamFlag = true teamFlag = true
this.tabsValue2 = 1
} }
uni.request({ uni.request({
url: `${this.$local}/api/unload/command/pageCommandForBranch?vvyId=${this.shipInfo.vvyId}&brdId=${this.brdId}&mnfBl=${this.mnfBl}&bvmId=${this.bvmId}&sendStatus=${this.tabsValue2}&size=${this.pageSize}&current=${this.current}&tradeType=${this.tradeType}`, url: `${this.$local}/api/unload/command/pageCommandForBranch?vvyId=${this.shipInfo.vvyId}&brdId=${this.brdId}&mnfBl=${this.mnfBl}&bvmId=${this.bvmId}&sendStatus=${this.sendValue}&size=${this.pageSize}&current=${this.current}&tradeType=${this.tradeType}`,
header: { header: {
'Content-Type': 'application/json', // 'Content-Type': 'application/json', //
'Authorization': `Bearer ${this.loginObj.access_token}` 'Authorization': `Bearer ${this.loginObj.access_token}`
@ -1033,7 +921,7 @@
success: (res) => { success: (res) => {
console.log(res) console.log(res)
this.itemList = res.data.data.records this.itemList = res.data.data.records
this.total = this.itemList.length this.total = res.data.data.total
this.itemList.forEach((v, index) => { this.itemList.forEach((v, index) => {
this.getBottomInfo(v.lwpId, index) this.getBottomInfo(v.lwpId, index)
}) })
@ -1334,6 +1222,11 @@
this.askValue = "" this.askValue = ""
this.$refs.popup2.close() this.$refs.popup2.close()
}, },
sendSelect(e) {
this.sendText = e.text
this.sendValue = e.vale
this.loadOtherOrder()
},
// //
getBrand() { getBrand() {
uni.request({ uni.request({
@ -1416,6 +1309,7 @@
.content { .content {
background-color: #F6F7F9; background-color: #F6F7F9;
position: relative;
/deep/.tab .tab-bar { /deep/.tab .tab-bar {
height: 66px; height: 66px;
@ -1428,6 +1322,7 @@
line-height: 66px; line-height: 66px;
font-size: 18px; font-size: 18px;
color: #23262E; color: #23262E;
font-weight: bold;
font-family: PingFangSC-Semibold; font-family: PingFangSC-Semibold;
} }
@ -1453,20 +1348,58 @@
margin-top: 20px; margin-top: 20px;
} }
/deep/.tab .tab-cont {
padding: 0;
}
.form { .form {
display: flex; background: #FAFAFA;
justify-content: space-between; border-top: 1px solid #EEEEEE;
padding: 10px; border-bottom: 1px solid #EEEEEE;
.inputBox { .inputBox {
width: 100%;
display: flex; display: flex;
justify-content: space-between;
padding: 5px 10px;
.leftInput {
width: 400px;
}
/deep/.uni-easyinput {
width: 400px;
/deep/.content-clear-icon {
padding-right: 16px;
}
}
/deep/.is-input-border {
border-radius: 18.5px;
}
.rightInput {
display: flex;
gap: 10px;
}
} }
.input { .input {
width: 120px; width: 100px;
height: 35px; height: 35px;
line-height: 35px; line-height: 35px;
margin-left: 20px; background: transparent;
border: none;
/deep/.superwei-combox__input {
text-align: right;
padding-right: 6px;
}
/deep/.superwei-combox__input-plac {
color: #000;
}
} }
.btn { .btn {
@ -1479,6 +1412,10 @@
.buttonlist { .buttonlist {
padding: 10px; padding: 10px;
position: absolute;
top: 5px;
right: 0px;
z-index: 999;
.button { .button {
display: inline-block; display: inline-block;
@ -1489,18 +1426,26 @@
border-radius: 4px; border-radius: 4px;
} }
button:first-child { .button:first-child {
border: 1px solid #0067CF; border: 1px solid #0067CF;
color: #0067CF; color: #0067CF;
background: #fff; background: #fff;
} }
button:last-child { .button:last-child {
color: #fff; color: #fff;
background: #0067CF; background: #0067CF;
} }
} }
.buttonlist2 {
.button {
border: 1px solid #999 !important;
color: #999 !important;
background-color: #fff !important;
}
}
.tablist { .tablist {
width: 175px; width: 175px;
height: 60px; height: 60px;
@ -1523,7 +1468,7 @@
} }
.tjList { .tjList {
width: 256px; width: 240px;
background: #EBEDF1; background: #EBEDF1;
box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.10); box-shadow: 0 2px 6px 0 rgba(0, 0, 0, 0.10);
float: left; float: left;
@ -1648,12 +1593,12 @@
overflow: scroll; overflow: scroll;
.exp { .exp {
width: 100%; // width: 100%;
// width: 49.5%; width: 49.5%;
margin-bottom: 15px; margin-bottom: 15px;
background: #FFFFFF; background: #FFFFFF;
border-radius: 8px; border-radius: 8px;
padding: 16px; padding: 12px;
padding-right: 0; padding-right: 0;
position: relative; position: relative;
@ -1676,14 +1621,15 @@
.titleImg { .titleImg {
width: 18px; width: 18px;
height: 18px; height: 18px;
margin-right: 10px; margin-right: 5px;
margin-top: 2px;
} }
} }
.schedule { .schedule {
padding: 5px 8px; padding: 5px 8px;
background: #F7F7F7; background: #F7F7F7;
margin-left: 16px; margin-left: 8px;
display: flex; display: flex;
.text { .text {
@ -1692,7 +1638,7 @@
} }
.progressBox { .progressBox {
width: 100px; width: 50px;
margin-top: 5px; margin-top: 5px;
margin: 5px 8px; margin: 5px 8px;
} }
@ -1752,13 +1698,10 @@
flex-direction: column; flex-direction: column;
font-size: 14px; font-size: 14px;
width: 48%; width: 48%;
margin-right: 1%;
margin-top: 10px; margin-top: 10px;
border-right: 1px solid #eee; border-right: 1px solid #eee;
gap: 12px;
.col:first-child { margin-left: 10px;
margin-bottom: 12px;
}
text:first-child { text:first-child {
color: #999999; color: #999999;
@ -1869,19 +1812,159 @@
} }
} }
} }
}
}
.pzPot {
width: 100%;
.title {
width: 100%;
height: 50px;
line-height: 50px;
font-size: 28px;
font-weight: bold;
text-align: center;
border: 1px solid #000;
box-sizing: border-box;
}
.ul {
width: 100%;
margin-bottom: 20px;
display: flex;
flex-wrap: wrap;
border: 1px solid #000;
border-top: none;
box-sizing: border-box;
.li {
width: 25%;
height: 30px;
line-height: 30px;
display: flex;
border: 1px solid #000;
border-top: none;
border-left: none;
box-sizing: border-box;
.xuhao {
width: 20px;
text-align: center;
box-sizing: border-box;
}
.name {
flex: 1;
text-align: center;
border: 1px solid #000;
box-sizing: border-box;
border-top: none;
border-bottom: none;
}
.color {
flex: 1;
box-sizing: border-box;
}
}
} }
} }
.currentList { .imgTable {
width: 85%; margin-top: 20px;
margin: 10px auto;
.title {
font-size: 20px;
font-weight: bold;
}
.nr {
margin: 10px 0;
font-size: 16px;
}
.imgLi {
display: flex;
position: relative;
.shipImg {
width: 100%;
height: 171px;
}
.maskBox {
width: calc(100% - 200px);
height: 150px;
background-color: transparent;
display: flex;
position: absolute;
top: 11px;
left: 60px;
.testLine {
flex: 1;
height: 100%;
border-left: 1px solid #999;
}
.testLine:first-child {
border-left: none;
}
.testInfo {
height: 30px;
background-color: #0067CF;
}
}
.heightBox {
display: flex;
flex-direction: column;
justify-content: center;
margin-left: 10px;
}
.imgSize {
width: 28px;
height: 28px;
position: absolute;
}
.leftTopImg {
transform: rotate(90deg);
top: 10px;
left: 8px;
}
.imgSize2 {
width: 100px;
height: 30px;
position: absolute;
}
.leftBotImg {
bottom: 10px;
left: 8px;
}
.topImg {
top: -5px;
left: 40%;
}
.botImg {
transform: rotate(180deg);
bottom: -6px;
left: 40%;
}
}
.tableHead { .tableHead {
margin-top: 10px; margin-top: 10px;
height: 50px; height: 50px;
line-height: 50px; line-height: 50px;
background-color: #fff;
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 0 12px; padding: 0 12px;
@ -1890,12 +1973,9 @@
} }
.gray { .gray {
background-color: #f9f9f9; background-color: #fff;
} }
.imgLi {
margin-bottom: 5px;
}
.title { .title {
line-height: 50px; line-height: 50px;
@ -1903,13 +1983,13 @@
font-weight: 900; font-weight: 900;
} }
.nr { .text {
font-size: 16px; display: inline-block;
margin-right: 50px;
}
.text { /deep/.table--border {
display: inline-block; background-color: #fff;
margin-right: 50px;
}
} }
} }
@ -2111,22 +2191,22 @@
} }
.popupBox { .popupBox {
width: 500px; width: 400px;
background-color: #fff; background-color: #fff;
padding: 30px; border-radius: 8px;
.popupTitle { .popupTitle {
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
border-bottom: 1px solid #ccc; border-bottom: 1px solid #ccc;
padding-bottom: 20px; padding: 15px 0;
} }
.popupInfo { .popupInfo {
display: flex; display: flex;
margin-top: 20px; margin-top: 20px;
line-height: 35px; line-height: 35px;
padding: 30px 0; margin-left: 20px;
/deep/.superwei-combox { /deep/.superwei-combox {
border: none; border: none;
@ -2144,6 +2224,8 @@
/deep/.uni-easyinput { /deep/.uni-easyinput {
margin-top: 20px; margin-top: 20px;
width: 460px;
margin-left: 20px;
} }
/deep/.uni-select__input-placeholder { /deep/.uni-select__input-placeholder {
@ -2156,20 +2238,33 @@
.popupBtn { .popupBtn {
margin-top: 20px; margin-top: 20px;
padding-top: 20px; padding: 14px 0;
border-top: 1px solid #ccc;
display: flex; display: flex;
justify-content: flex-end; justify-content: center;
.btnList { .btnList {
display: flex; display: flex;
.button { .button {
margin-left: 10px; width: 125px;
height: 36px;
line-height: 36px;
margin-left: 15px;
border-radius: 4px;
}
.button:first-child {
background-color: #fff;
border: 1px solid #0067CF;
color: #0067CF;
} }
} }
} }
} }
.popupBox2 {
width: 500px;
}
} }
</style> </style>

View File

@ -313,6 +313,8 @@
margin-bottom: 12px; margin-bottom: 12px;
display: flex; display: flex;
font-size: 14px; font-size: 14px;
height: 20px;
line-height: 20px;
p { p {
color: #999; color: #999;

View File

@ -9,7 +9,8 @@
placeholder="请选择贸易类型" v-model="tradeName" @select="tradeSelect"></superwei-combox> placeholder="请选择贸易类型" v-model="tradeName" @select="tradeSelect"></superwei-combox>
</uni-easyinput> </uni-easyinput>
<superwei-combox class="input" :candidates="shipList" :isJSON="true" keyName="vvyShip" <superwei-combox class="input" :candidates="shipList" :isJSON="true" keyName="vvyShip"
placeholder="请选择船名/航次" v-model="vvyShip" @select="shipSelect"></superwei-combox> placeholder="请选择船名/航次" v-model="vvyShip" @select="shipSelect"
@input="shipInput"></superwei-combox>
</uni-easyinput> </uni-easyinput>
<button class="btn" @click="onSearch"></button> <button class="btn" @click="onSearch"></button>
</view> </view>
@ -52,10 +53,10 @@
</template> </template>
<o-empty v-else height="70vh" bg="#f5f6fa" /> <o-empty v-else height="70vh" bg="#f5f6fa" />
</view> </view>
<view class="pageBox" v-if="itemList.length > 0"> <!-- <view class="pageBox" v-if="itemList.length > 0">
<uni-pagination :show-icon="true" :total="total" :pageSize="pageSize" :current="current" <uni-pagination :show-icon="true" :total="total" :pageSize="pageSize" :current="current"
@change="changePage" /> @change="changePage" />
</view> </view> -->
</view> </view>
</view> </view>
</view> </view>
@ -86,6 +87,7 @@
vvyId: "", vvyId: "",
shipId: "", shipId: "",
shipName: '', shipName: '',
shipValue: "",
shipList: [], shipList: [],
// //
@ -97,6 +99,10 @@
portObj: {} portObj: {}
} }
}, },
onReachBottom() {
this.current++
this.initData()
},
onLoad() { onLoad() {
this.portObj = uni.getStorageSync('portObj') this.portObj = uni.getStorageSync('portObj')
this.loginObj = uni.getStorageSync('loginObj') this.loginObj = uni.getStorageSync('loginObj')
@ -134,6 +140,11 @@
this.vvyId = e.vvyId this.vvyId = e.vvyId
this.vvyShip = e.vvyShip this.vvyShip = e.vvyShip
}, },
//
shipInput(e) {
this.shipValue = e
this.getShip()
},
// //
getShip() { getShip() {
if (this.tradeName == '外贸') { if (this.tradeName == '外贸') {
@ -145,13 +156,14 @@
let key = "" let key = ""
let spmId = "" let spmId = ""
uni.request({ uni.request({
url: `${this.$local}/api/shipInstructions/queryByKey?ieType=${ieType}&key=${ieType}&pamId=${this.portObj.portId}&spmId=${spmId}&tradeType=${this.tradeType}`, url: `${this.$local}/api/shipInstructions/queryByKey?ieType=${ieType}&key=${this.shipValue}&pamId=${this.portObj.portId}&spmId=${spmId}&tradeType=${this.tradeType}`,
header: { header: {
'Content-Type': 'application/json', // 'Content-Type': 'application/json', //
'Authorization': `Bearer ${this.loginObj.access_token}` 'Authorization': `Bearer ${this.loginObj.access_token}`
}, },
method: 'GET', // method: 'GET', //
success: (res) => { success: (res) => {
console.log(res)
if (res.data.status == "200") { if (res.data.status == "200") {
this.shipList = res.data.data this.shipList = res.data.data
this.shipList.forEach(v => { this.shipList.forEach(v => {
@ -185,7 +197,7 @@
success: (res) => { success: (res) => {
console.log(res) console.log(res)
this.total = res.data.data.total this.total = res.data.data.total
this.itemList = res.data.data.records this.itemList.push(...res.data.data.records)
} }
}) })
}, },
@ -214,18 +226,22 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container {
display: flex;
}
.content { .content {
flex: 1;
padding: 20px; padding: 20px;
min-height: calc(100vh - 68px - 40px); min-height: calc(100vh - 68px - 40px);
margin-top: 66px;
margin-bottom: 20px;
.form { .form {
width: 100%;
height: 50px;
background: #f5f6fa;
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
position: fixed;
top: 66px;
right: 0;
z-index: 999;
.end { .end {
display: flex; display: flex;
@ -237,6 +253,7 @@
line-height: 35px; line-height: 35px;
padding-left: 10px; padding-left: 10px;
margin-right: 15px; margin-right: 15px;
margin-top: 8px;
} }
.btn { .btn {
@ -247,6 +264,7 @@
color: #fff; color: #fff;
background-color: #0067CF; background-color: #0067CF;
margin-right: 10px; margin-right: 10px;
margin-top: 8px;
} }
} }
@ -258,12 +276,11 @@
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
position: relative; position: relative;
margin-top: 15px; margin-top: 40px;
gap: 16px; gap: 16px;
/deep/.o-empty { /deep/.o-empty {
width: 100%; width: 100%;
margin-top: 15px;
} }
.item { .item {
@ -304,12 +321,20 @@
font-size: 16px; font-size: 16px;
.nitem { .nitem {
width: 46%; // width: 49%;
.text { .text {
color: #929292; color: #929292;
} }
} }
.nitem:nth-of-type(2n) {
width: 35%;
}
.nitem:nth-of-type(2n - 1) {
width: 63%;
}
} }
.status { .status {
@ -332,7 +357,16 @@
} }
.pageBox { .pageBox {
width: 100%;
height: 50px;
background-color: #fff;
margin-top: 20px; margin-top: 20px;
position: fixed;
bottom: 0;
left: 0;
display: flex;
flex-direction: column;
justify-content: center;
} }
} }
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -416,6 +416,8 @@
margin-bottom: 12px; margin-bottom: 12px;
display: flex; display: flex;
font-size: 14px; font-size: 14px;
height: 20px;
line-height: 20px;
p { p {
color: #999; color: #999;

View File

@ -62,11 +62,11 @@
data() { data() {
return { return {
// rtoswuhan1 // rtoswuhan1
account: 'rtoswuhan1', account: '',
// q123456 // q123456
password: 'q123456', password: '',
// pad // pad
mediaType: "app", mediaType: "pad",
// //
errorTitle: "", errorTitle: "",
// //

View File

@ -1,145 +1,155 @@
<template> <template>
<view class="details"> <view class="details">
<head-view title="船名/航次"></head-view> <head-view :title="title"></head-view>
<view class="container contentFixed"> <view class="container contentFixed">
<view class="userInfo"> <!-- <view class="userInfo">
<p>填报人{{infoData.qdReportPerson}}</p> <p>填报人{{infoData.qdReportPerson}}</p>
<p>上报部门{{infoData.qrpDept}}</p> <p>上报部门{{infoData.qrpDept}}</p>
</view> </view> -->
<view class="formTitle"> <view class="itemBox">
基本信息 <view class="formTitle">
</view> <image src="../../static/images/goodsImg2.png"></image>
<view class="ul zsInfo"> <text>基本信息</text>
<view class="li"> </view>
<p>质损发生环节</p> <view class="ul zsInfo">
<view class="rightInfo"> <view class="li">
<p>{{infoData.qdLinkName}} </p> <p>质损发生环节</p>
<p v-if="infoData.linkFeedback != '' || infoData.linkOther != ''"> <view class="rightInfo">
备注{{infoData.linkFeedback}}{{infoData.linkOther}} <p>{{infoData.qdLinkName}} </p>
</p> <p v-if="infoData.qdLinkName == '客户反馈' || infoData.qdLinkName == '其他'">
备注{{infoData.linkFeedback}}{{infoData.linkOther}}
</p>
</view>
</view> </view>
</view> </view>
</view> </view>
<view class="ul"> <view class="itemBox">
<view class="li"> <view class="formTitle">
<p class="liTitle">板车照片</p> <image class="titleImg" src="../../static/images/zlIcon.png"></image>
<view class="picture"> <text>板车照片</text>
<template v-for="item in boardCarPhotos">
<image :key="item" :src="item" mode="widthFix"></image>
</template>
</view>
</view> </view>
<view class="li"> <view class="picture">
<p class="liTitle">板车车牌照</p> <template v-for="item in boardCarPhotos">
<view class="picture"> <image :key="item" :src="item"></image>
<template v-for="item in boardCarList"> </template>
<image :key="item" :src="item" mode="widthFix"></image> </view>
</template> </view>
<view class="itemBox">
<view class="formTitle">
<image class="titleImg" src="../../static/images/cpIcon.png"></image>
<text>板车车牌照</text>
</view>
<view class="picture">
<template v-for="item in boardCarList">
<image :key="item" :src="item"></image>
</template>
</view>
</view>
<view class="itemBox">
<view class="formTitle">
<image class="titleImg" src="../../static/images/zxIcon.png"></image>
<text>质损信息</text>
</view>
<view class="zsInfo">
<view class="li">
<p>车架号/条形码</p>
<p>{{infoData.vinCode}}</p>
</view>
<view class="li">
<p>船名/航次</p>
<p>{{infoData.spmIdAndVvyId}}</p>
</view>
<view class="li">
<p>车型</p>
<p>{{infoData.bvmName}}</p>
</view>
<view class="li">
<p>品牌</p>
<p>{{infoData.brdName}}</p>
</view>
<view class="li">
<p>场位</p>
<p>{{infoData.pos}}</p>
</view>
<view class="li">
<p>质损时间</p>
<p>{{infoData.qualityDamageTime}}</p>
</view>
<view class="li">
<p>质损货物品类</p>
<view class="rightInfo">
<p>{{infoData.qdGodsCategoryName}}</p>
<p v-if="infoData.qdGodsCategoryName == '其他'">
备注{{infoData.qdGcOther}}
</p>
</view>
</view>
<view class="li imageLi">
<image :src="zsImg"></image>
</view>
<view class="li tsLi">
<p>质损概况</p>
<view class="rightInfo">
<p>{{infoData.qdGodsCategoryName}}</p>
<p v-if="infoData.qdGodsCategoryName == '其他'">
备注{{infoData.qdsOther}}
</p>
</view>
</view>
<view class="li tsLi">
<p>损伤情况</p>
<view class="rightInfo">
<p>{{infoData.damageSituationName}}</p>
<p v-if="infoData.damageSituationName == '其他'">
备注{{infoData.dsOther}}
</p>
</view>
</view>
<view class="li tsLi">
<p>处置情况</p>
<view class="rightInfo">
<p>{{infoData.disposalSituationName}}</p>
<p v-if="infoData.disposalSituationName == '其他'">
备注{{infoData.dpsOther}}
</p>
</view>
</view> </view>
</view> </view>
</view> </view>
<view class="formTitle"> <view class="itemBox">
质损信息 <view class="formTitle">
</view> <image class="titleImg" src="../../static/images/zsIcon.png"></image>
<view class="ul zsInfo"> <text>质损照片</text>
<view class="li">
<p>车架号/条形码</p>
<p>{{infoData.vinCode}}</p>
</view> </view>
<view class="li"> <view class="picture">
<p>船名/航次</p> <template v-for="item in qualityDamage">
<p>{{infoData.spmIdAndVvyId}}</p> <image :key="item" :src="item"></image>
</view> </template>
<view class="li">
<p>车型</p>
<p>{{infoData.bvmName}}</p>
</view>
<view class="li">
<p>品牌</p>
<p>{{infoData.brdName}}</p>
</view>
<view class="li">
<p>场位</p>
<p>{{infoData.pos}}</p>
</view>
<view class="li">
<p>质损时间</p>
<p>{{infoData.qualityDamageTime}}</p>
</view>
<view class="li">
<p>质损货物品类</p>
<view class="rightInfo">
<p>{{infoData.qdGodsCategoryName}}</p>
<p v-if="infoData.qdGcOther != ''">
备注{{infoData.qdGcOther}}
</p>
</view>
</view>
<view class="li imageLi">
<image :src="zsImg" mode="widthFix"></image>
</view>
<view class="li tsLi">
<p>质损概况</p>
<view class="rightInfo">
<p>{{infoData.qdGodsCategoryName}}</p>
<p v-if="infoData.qdGcOther != ''">
备注{{infoData.qdGcOther}}
</p>
</view>
</view>
<view class="li tsLi">
<p>损伤情况</p>
<view class="rightInfo">
<p>{{infoData.damageSituationName}}</p>
<p v-if="infoData.dsOther != ''">
备注{{infoData.dsOther}}
</p>
</view>
</view>
<view class="li tsLi">
<p>处置情况</p>
<view class="rightInfo">
<p>{{infoData.disposalSituationName}}</p>
<p v-if="infoData.dpsOther != ''">
备注{{infoData.dpsOther}}
</p>
</view>
</view>
<view class="li zpLi">
<p class="liTitle">质损照片</p>
<view class="picture">
<template v-for="item in qualityDamage">
<image :key="item" :src="item" mode="widthFix"></image>
</template>
</view>
</view>
<view class="li zpLi">
<p class="liTitle">车架号图片</p>
<view class="picture">
<template v-for="item in carFrameNumber">
<image :key="item" :src="item" mode="widthFix"></image>
</template>
</view>
</view> </view>
</view> </view>
<view class="formTitle"> <view class="itemBox">
签字 <view class="formTitle">
</view> <image class="titleImg" src="../../static/images/cjhIcon.png"></image>
<view class="ul"> <text>车架号图片</text>
<view class="li flexLi">
<p class="liTitle">质损负责人</p>
<p>{{infoData.qdLiablePerson}}</p>
</view> </view>
<view class="li flexLi"> <view class="picture">
<p class="liTitle">签名</p> <template v-for="item in carFrameNumber">
<view class="picture"> <image :key="item" :src="item"></image>
<image :src="signImg" mode="widthFix"></image> </template>
</view>
</view> </view>
</view> </view>
<view class="btnList"> <view class="btnSign">
<view class="signLeft">
<p>质损负责人签名:</p>
<p>Quality loss responsible:</p>
</view>
<view class="signRightft">
<image :src="signImg"></image>
</view>
</view>
<!-- <view class="btnList">
<van-button type="default" @click="cancel"></van-button> <van-button type="default" @click="cancel"></van-button>
</view> </view> -->
</view> </view>
</view> </view>
</template> </template>
@ -148,6 +158,7 @@
export default { export default {
data() { data() {
return { return {
title: "",
ygqId: "", ygqId: "",
loginObj: {}, loginObj: {},
infoData: {}, infoData: {},
@ -186,6 +197,7 @@
console.log('接口返回------', res); console.log('接口返回------', res);
if (res.statusCode == 200) { if (res.statusCode == 200) {
this.infoData = res.data.data this.infoData = res.data.data
this.title = `${this.infoData.vinCode} - 质损详情`
// //
this.infoData.boardCarPhotos.forEach(v => { this.infoData.boardCarPhotos.forEach(v => {
this.initImg(v.filePath, "1") this.initImg(v.filePath, "1")
@ -249,7 +261,8 @@
<style lang="less" scoped> <style lang="less" scoped>
.details { .details {
.container { .container {
padding: 20px 30px; padding: 16px;
padding-bottom: 80px;
.userInfo { .userInfo {
display: flex; display: flex;
@ -261,64 +274,51 @@
} }
} }
.formTitle { .itemBox {
padding-left: 10px; padding: 24px 16px;
border-left: 5px solid #2979ff; background: #fff;
font-size: 20px; margin-bottom: 16px;
font-weight: bold;
} }
.ul { .formTitle {
margin-bottom: 30px; font-size: 18px;
font-weight: bold;
display: flex;
.rightInfo { image {
display: flex; width: 18px;
height: 18px;
p { margin-right: 10px;
width: 120px; margin-top: 5px;
}
} }
}
.flexLi { .picture {
display: flex; margin-top: 20px;
} display: flex;
flex-wrap: wrap;
.li {
margin-top: 30px;
.liTitle {
min-width: 100px;
margin-right: 20px;
font-size: 16px;
font-weight: bold;
}
.picture {
margin-top: 20px;
display: flex;
flex-wrap: wrap;
image {
width: 120px;
height: 120px;
margin: 10px;
}
}
image {
width: 120px;
height: 120px;
margin: 10px;
} }
} }
.zsInfo { .zsInfo {
display: flex; display: flex;
flex-wrap: wrap; flex-wrap: wrap;
margin-top: 24px;
.li { .li {
width: 48%; width: 48%;
display: flex; display: flex;
margin-bottom: 12px;
font-size: 14px;
color: #23262E;
p:first-child { p:first-child {
width: 120px; width: 105px;
} }
} }
@ -337,6 +337,41 @@
} }
} }
.btnSign {
width: 100%;
height: 66px;
position: fixed;
bottom: 0;
left: 0;
border: 1px solid #E1E5ED;
box-shadow: 0 -1px 4px 0 rgba(0, 0, 0, 0.05);
display: flex;
justify-content: flex-end;
background-color: #fff;
.signLeft {
display: flex;
flex-direction: column;
justify-content: center;
gap: 3px;
p {
text-align: right;
}
}
.signRightft {
display: flex;
flex-direction: column;
justify-content: center;
image {
width: 100px;
height: 40px;
}
}
}
.btnList { .btnList {
display: flex; display: flex;
justify-content: center; justify-content: center;

View File

@ -1,6 +1,6 @@
<template> <template>
<view class="edit"> <view class="edit">
<head-view title="船名/航次" url="/pages/quality/index"></head-view> <head-view title="货物质损" url="/pages/quality/index"></head-view>
<view class="container contentFixed"> <view class="container contentFixed">
<uni-steps :options="stepList" :active="active" /> <uni-steps :options="stepList" :active="active" />
<view class="ul"> <view class="ul">
@ -115,8 +115,8 @@
</radio-group> </radio-group>
</view> </view>
<view class="li imageLi"> <view class="li imageLi">
<!-- <canvas style="width: 100%; height: 440px;" canvas-id="myCanvas"></canvas> --> <image :src="zsImg" mode="widthFix" @click="togoCs"></image>
<image :src="zsImg" mode="widthFix"></image> <!-- <image :src="zsImg2" class="zshz"></image> -->
</view> </view>
<view class="li zsLi"> <view class="li zsLi">
<p class="liTitle"><text class="required">*</text>资损概况:</p> <p class="liTitle"><text class="required">*</text>资损概况:</p>
@ -261,8 +261,7 @@
zsImg: "", // zsImg: "", //
scZsImg: "", // scZsImg: "", //
canvasContext: null, zsImg2: "", //
imageSrc: '../../static/images/zs.png',
// //
vinDisabled: false, // vinDisabled: false, //
@ -349,29 +348,6 @@
this.initImg(this.signObj.signImg, '5') this.initImg(this.signObj.signImg, '5')
} }
}, },
onReady() {
// Canvas
this.canvasContext = uni.createCanvasContext('myCanvas');
//
uni.getImageInfo({
src: this.imageSrc,
success: (res) => {
// Canvas
this.canvasContext.drawImage(res.path, 0, 0, res.width, res.height);
//
this.canvasContext.setStrokeStyle('#FF0000');
this.canvasContext.setLineWidth(5);
//
this.canvasContext.beginPath();
this.canvasContext.moveTo(50, 50); //
this.canvasContext.lineTo(100, 100); //
this.canvasContext.stroke(); // Canvas
}
});
},
onLoad(options) { onLoad(options) {
if ('params' in options) { if ('params' in options) {
// 使decodeURIComponent // 使decodeURIComponent
@ -394,6 +370,11 @@
if (this.type == 'edit') { if (this.type == 'edit') {
this.getRowInfo() this.getRowInfo()
} }
let zsImg = uni.getStorageSync("zsImg")
if (zsImg != null && zsImg != "" && zsImg != undefined) {
this.zsImg2 = uni.getStorageSync("zsImg")
console.log(this.zsImg2)
}
}, },
methods: { methods: {
// //
@ -684,6 +665,12 @@
this.other3 = '' this.other3 = ''
} }
}, },
//
togoCs() {
uni.navigateTo({
url: '/pages/quality/zsEdit'
})
},
// //
sign() { sign() {
uni.navigateTo({ uni.navigateTo({
@ -1527,6 +1514,15 @@
.imageLi { .imageLi {
width: 100%; width: 100%;
height: 440px; height: 440px;
position: relative;
.zshz {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
}
} }
.cwLi { .cwLi {

View File

@ -4,69 +4,79 @@
<view class="container"> <view class="container">
<view class="content"> <view class="content">
<view class="form"> <view class="form">
<button type="primary" class="button" @click="modify('add','')"> <!-- <button type="primary" class="button" @click="modify('add','')">
<uni-icons type="plusempty" color="#fff" size="20"></uni-icons> <uni-icons type="plusempty" color="#fff" size="20"></uni-icons>
</button> </button> -->
<view class="right"> <view class="right">
<superwei-combox class="select" :candidates="shipList" :isJSON="true" keyName="vslCnname" <superwei-combox class="select" :candidates="shipList" :isJSON="true" keyName="shipVvy"
placeholder="请选择船名" v-model="shipValue" @select="shipChange"></superwei-combox> placeholder="船名/航次" v-model="shipValue" @select="shipChange"
@input="shipInput"></superwei-combox>
<superwei-combox class="select" :candidates="brandList" :isJSON="true" keyName="brdName" <superwei-combox class="select" :candidates="brandList" :isJSON="true" keyName="brdName"
placeholder="请选择品牌" v-model="brandValue" @select="brandChange"></superwei-combox> placeholder="品牌" v-model="brandValue" @select="brandChange"></superwei-combox>
</view> </view>
</view> </view>
<view class="itemList"> <view class="itemList">
<template v-if="itemList.length > 0"> <template v-if="itemList.length > 0">
<view class="item" v-for="(item,index) in itemList" :key="index" @click="details(item)"> <view class="item" v-for="(item,index) in itemList" :key="index" @click="details(item)">
<view class="row"> <view class="headTop">
<view class="col weight"> <view class="leftHead">
{{item.vinCode}} <image src="../../static/images/zlIcon.png" mode=""></image>
<text>{{item.vinCode}}</text>
</view> </view>
<view class="col"> <view class="rightHead" @click.stop="modify('edit',item)">
品牌{{item.brdName}} <image src="../../static/images/editBtn.png"></image>
</view> <text>编辑</text>
<view class="col">
货物状态{{item.godStatusName}}
</view> </view>
</view> </view>
<view class="row"> <view class="row">
<view class="col"> <view class="col">
航次/船名{{item.spmIdAndVvyId}} 航次/船名{{item.spmIdDesc}}
</view>
<view class="col">
作业时间{{item.workTime}}
</view>
</view>
<view class="row">
<view class="col">
货物状态{{item.godStatusName}}
</view>
<view class="col">
质损概况{{item.damageSituationName}}
</view>
</view>
<view class="row">
<view class="col">
质损发生环节{{item.qdLinkName}}
</view> </view>
<view class="col"> <view class="col">
车型{{item.bvmName}} 车型{{item.bvmName}}
</view> </view>
</view>
<view class="row">
<view class="col">
品牌{{item.brdName}}
</view>
<view class="col"> <view class="col">
场位{{item.pos}} 场位{{item.pos}}
</view> </view>
</view> </view>
<view class="row"> <view class="row">
<view class="col">
作业时间{{item.workTime}}
</view>
<view class="col"> <view class="col">
作业人{{item.qdLiablePerson}} 作业人{{item.qdLiablePerson}}
</view> </view>
<view class="col">
质损发生环节{{item.qdLinkName}}
</view>
</view>
<view class="row">
<view class="col">
质损概况{{item.damageSituationName}}
</view>
<view class="col"> <view class="col">
处置情况{{item.disposalSituationName}} 处置情况{{item.disposalSituationName}}
</view> </view>
</view> </view>
<view class="rowFoot"> <!-- <view class="rowFoot">
<view class="col" @click.stop="modify('edit',item)"> <view class="col">
编辑 编辑
</view> </view>
<view class="col" @click.stop="del(item)"> <view class="col" @click.stop="del(item)">
删除 删除
</view> </view>
</view> </view> -->
</view> </view>
</template> </template>
<o-empty v-else height="70vh" bg="#f5f6fa" /> <o-empty v-else height="70vh" bg="#f5f6fa" />
@ -112,6 +122,7 @@
shipList: [], shipList: [],
shipId: "", shipId: "",
shipValue: "", shipValue: "",
shipSr: "",
vvyId: "", vvyId: "",
} }
}, },
@ -148,6 +159,7 @@
console.log('接口返回------', res); console.log('接口返回------', res);
if (res.statusCode == 200) { if (res.statusCode == 200) {
this.itemList = res.data.data.records this.itemList = res.data.data.records
console.log(this.itemList)
this.total = res.data.data.total this.total = res.data.data.total
} }
} }
@ -156,12 +168,11 @@
// //
getShip() { getShip() {
let ieType = "" let ieType = ""
let key = ""
let pamId = this.portObj.portId let pamId = this.portObj.portId
let spmId = "" let spmId = ""
let tradeType = "" let tradeType = ""
uni.request({ uni.request({
url: `${this.$local}/api/shipInstructions/queryByKey?ieType=${ieType}&key=${ieType}&pamId=${this.portObj.portId}&spmId=${spmId}&tradeType=${tradeType}`, url: `${this.$local}/api/shipInstructions/queryByKey?ieType=${ieType}&key=${this.shipSr}&pamId=${this.portObj.portId}&spmId=${spmId}&tradeType=${tradeType}`,
header: { header: {
'Content-Type': 'application/json', // 'Content-Type': 'application/json', //
'Authorization': `Bearer ${this.loginObj.access_token}` 'Authorization': `Bearer ${this.loginObj.access_token}`
@ -170,6 +181,10 @@
success: (res) => { success: (res) => {
if (res.statusCode == 200) { if (res.statusCode == 200) {
this.shipList = res.data.data this.shipList = res.data.data
this.shipList.forEach(v => {
this.$set(v, "shipVvy", `${v.vslCnname} / ${v.vvyName} `)
})
console.log(this.shipList)
} }
} }
}) })
@ -177,11 +192,16 @@
// / // /
shipChange(e) { shipChange(e) {
this.shipId = e.vslCd this.shipId = e.vslCd
this.shipValue = e.vslCnname this.shipValue = e.shipVvy
this.vvyId = e.vvyId this.vvyId = e.vvyId
this.current = 1 this.current = 1
this.initData() this.initData()
}, },
//
shipInput(e) {
this.shipSr = e
this.getShip()
},
// //
getBrand() { getBrand() {
uni.request({ uni.request({
@ -218,7 +238,6 @@
}, },
// //
details(item) { details(item) {
console.log(123)
let obj = { let obj = {
ygqId: item.ygqId ygqId: item.ygqId
} }
@ -271,19 +290,22 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container {
display: flex;
}
.content { .content {
flex: 1; flex: 1;
padding: 20px; padding-bottom: 20px;
margin-top: 115px;
.form { .form {
width: 100%;
display: flex; display: flex;
justify-content: space-between; justify-content: flex-end;
height: 40px; background: #FAFAFA;
line-height: 40px; border-top: 1px solid #EEEEEE;
border-bottom: 1px solid #EEEEEE;
padding: 6px 10px;
position: fixed;
top: 66px;
z-index: 999;
.button { .button {
width: 90px; width: 90px;
@ -298,9 +320,24 @@
justify-content: space-between; justify-content: space-between;
.select { .select {
width: 130px; width: 170px;
height: 35px; height: 35px;
margin-left: 20px; line-height: 35px;
background: transparent;
border: none;
/deep/.superwei-combox__input {
text-align: right;
padding-right: 6px;
}
/deep/.superwei-combox__input-plac {
color: #000;
}
}
.select:last-child {
width: 100px;
} }
/deep/.is-input-border { /deep/.is-input-border {
@ -310,20 +347,57 @@
} }
.itemList { .itemList {
margin-top: 30px; padding: 16px;
display: flex;
flex-direction: column;
gap: 16px;
.item { .item {
padding: 20px 0; padding: 15px;
border-bottom: 2px solid #e9e9e9; border-radius: 8px;
background-color: #fff;
display: flex; display: flex;
flex-wrap: wrap;
justify-content: space-between; justify-content: space-between;
font-family: PingFangSC-Regular;
font-size: 14px;
color: #23262E;
gap: 12px;
.weight { .headTop {
font-weight: 900; width: 100%;
display: flex;
justify-content: space-between;
.leftHead {
font-size: 16px;
color: #23262E;
font-weight: bold;
display: flex;
image {
width: 18px;
height: 18px;
margin-right: 7px;
}
}
.rightHead {
font-size: 16px;
color: #1677FF;
display: flex;
image {
width: 16px;
height: 16px;
margin-right: 8px;
margin-top: 3px;
}
}
} }
.row { .row {
width: 22%; width: 18%;
flex-direction: column; flex-direction: column;
display: flex; display: flex;
} }
@ -331,23 +405,6 @@
.col { .col {
margin-bottom: 10px; margin-bottom: 10px;
} }
.rowFoot {
width: 12%;
display: flex;
justify-content: space-around;
color: #1890ff;
.col {
display: flex;
flex-direction: column;
justify-content: center;
}
.col:last-child {
color: red;
}
}
} }
} }

View File

@ -42,6 +42,7 @@
height: 0, height: 0,
loginObj: {}, loginObj: {},
signImg: "", signImg: "",
url: "",
}; };
}, },
onLoad(option) { onLoad(option) {
@ -148,9 +149,20 @@
uni.canvasToTempFilePath({ uni.canvasToTempFilePath({
canvasId: 'mycanvas', canvasId: 'mycanvas',
success: function(e) { success: function(e) {
const myPromise = new Promise((resolve, reject) => {
//
// resolve()reject()
pathToBase64(e.tempFilePath).then(path => {
that.url = path
})
.catch(error => {
console.error(error)
})
});
myPromise.then(result => {}).catch(error => {});
let timestamp = new Date().getTime(); let timestamp = new Date().getTime();
let sunumber = Math.floor(Math.random() * 999); let sunumber = Math.floor(Math.random() * 999);
var file = that.base64ToFile(e.tempFilePath, timestamp + sunumber) var file = that.base64ToFile(that.url, timestamp + sunumber)
uni.uploadFile({ uni.uploadFile({
url: `${that.$local}/api/file/upload`, //api url: `${that.$local}/api/file/upload`, //api
header: { header: {
@ -162,6 +174,7 @@
success: (res) => { success: (res) => {
console.log(JSON.parse(res.data)) console.log(JSON.parse(res.data))
that.signImg = JSON.parse(res.data).data.filePath that.signImg = JSON.parse(res.data).data.filePath
console.log(that.signImg)
let signObj = { let signObj = {
signImg: that.signImg, signImg: that.signImg,
} }

View File

@ -1,12 +1,13 @@
<template> <template>
<view class="sign"> <view class="sign">
<head-view title="签名"></head-view> <head-view title="绘制质损图"></head-view>
<view class="containe contentFixedr"> <view class="containe contentFixedr">
<view class="sign-box"> <view class="sign-box">
<canvas class="mycanvas" :style="{width:width +'px',height:height +'px'}" canvas-id="mycanvas" <canvas class="mycanvas" :style="{width:width +'px',height:height +'px'}" canvas-id="mycanvas"
@touchstart="touchstart" @touchmove="touchmove" @touchend="touchend"></canvas> @touchstart="touchstart" @touchmove="touchmove" @touchend="touchend" disable-scroll="true"></canvas>
<canvas canvas-id="camCacnvs" :style="{width:height +'px',height:width +'px'}" <view class="canvasBg">
class="canvsborder"></canvas> <image src="../../static/images/zs2.jpg" mode=""></image>
</view>
</view> </view>
<view class="sigh-btns"> <view class="sigh-btns">
<van-button class="btn" type="default" @tap="handleCancel"></van-button> <van-button class="btn" type="default" @tap="handleCancel"></van-button>
@ -42,29 +43,34 @@
height: 0, height: 0,
loginObj: {}, loginObj: {},
signImg: "", signImg: "",
url: "",
}; };
}, },
onLoad(option) { onLoad(option) {
that = this; that = this;
id = option.id; id = option.id;
type = option.type; type = option.type;
this.ctx = uni.createCanvasContext('mycanvas', this); // this.init()
//
this.ctx.lineWidth = 4;
this.ctx.lineCap = 'round';
this.ctx.lineJoin = 'round';
uni.getSystemInfo({
success: function(res) {
console.log(res);
that.width = res.windowWidth * 0.8;
that.height = res.windowHeight * 0.85;
}
});
this.loginObj = uni.getStorageSync('loginObj') this.loginObj = uni.getStorageSync('loginObj')
}, },
methods: { methods: {
init() {
this.ctx = uni.createCanvasContext('mycanvas', this); //
this.ctx.drawImage('../../static/images/zs2.jpg', 0, 0, 1000, 400)
//
this.ctx.lineWidth = 4;
this.ctx.lineCap = 'round';
this.ctx.lineJoin = 'round';
uni.getSystemInfo({
success: function(res) {
console.log(res);
that.width = res.windowWidth * 0.8;
that.height = res.windowHeight * 0.5;
}
});
},
// //
touchstart: function(e) { touchstart: function(e) {
let startX = e.changedTouches[0].x; let startX = e.changedTouches[0].x;
@ -131,52 +137,54 @@
that.ctx.clearRect(0, 0, that.width, that.height); that.ctx.clearRect(0, 0, that.width, that.height);
that.ctx.draw(true); that.ctx.draw(true);
tempPoint = []; tempPoint = [];
that.init()
}, },
// //
handleConfirm: function() { handleConfirm: function() {
let that = this let that = this
if (tempPoint.length == 0) { uni.canvasToTempFilePath({
uni.showToast({ canvasId: 'mycanvas',
title: '请先签名', success: function(e) {
icon: 'none', const myPromise = new Promise((resolve, reject) => {
duration: 2000 console.log(e.tempFilePath)
}); //
return; // resolve()reject()
} else { pathToBase64(e.tempFilePath).then(path => {
let that = this that.url = path
uni.canvasToTempFilePath({ console.log(that.url)
canvasId: 'mycanvas', })
success: function(e) { .catch(error => {
let timestamp = new Date().getTime(); console.error(error)
let sunumber = Math.floor(Math.random() * 999); })
var file = that.base64ToFile(e.tempFilePath, timestamp + sunumber) });
uni.uploadFile({ myPromise.then(result => {}).catch(error => {});
url: `${that.$local}/api/file/upload`, //api let timestamp = new Date().getTime();
header: { let sunumber = Math.floor(Math.random() * 999);
'Authorization': `Bearer ${that.loginObj.access_token}` var file = that.base64ToFile(that.url, timestamp + sunumber)
}, uni.uploadFile({
file: file, url: `${that.$local}/api/file/upload`, //api
fileType: 'image', header: {
name: 'file', 'Authorization': `Bearer ${that.loginObj.access_token}`
success: (res) => { },
console.log(JSON.parse(res.data)) file: file,
that.signImg = JSON.parse(res.data).data.filePath fileType: 'image',
let signObj = { name: 'file',
signImg: that.signImg, success: (res) => {
} console.log(res)
uni.setStorageSync('signObj', signObj) console.log(JSON.parse(res.data))
uni.navigateBack({ that.signImg = JSON.parse(res.data).data.filePath
delta: 1 console.log(that.signImg)
}); // uni.navigateBack({
}, // delta: 1
fail: (err) => { // });
console.log(err) },
} fail: (err) => {
}) console.log(err)
} }
}); })
} }
});
}, },
base64ToFile(base64, name) { base64ToFile(base64, name) {
if (typeof base64 != 'string') { if (typeof base64 != 'string') {
@ -207,11 +215,9 @@
} }
.sign-box { .sign-box {
height: 90%;
margin-left: 10%;
display: flex; display: flex;
flex-direction: column; justify-content: center;
text-align: center; position: relative;
} }
.sign-view { .sign-view {
@ -235,7 +241,18 @@
.mycanvas { .mycanvas {
margin: auto 0rpx; margin: auto 0rpx;
background-color: #ececec; background-color: transparent;
margin-top: 80px;
width: 1000px !important;
height: 400px !important;
z-index: 999;
}
.canvasBg {
width: 1000px;
height: 400px;
position: absolute;
top: 80px;
} }
.canvsborder { .canvsborder {

View File

@ -105,7 +105,7 @@
// //
total: 0, total: 0,
pageSize: 9, pageSize: 6,
current: 1, current: 1,
} }
}, },
@ -230,14 +230,10 @@
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.container {
display: flex;
}
.content { .content {
flex: 1;
padding: 20px; padding: 20px;
min-height: calc(100vh - 68px - 40px); min-height: calc(100vh - 68px - 40px);
margin-top: 68px;
.form { .form {
display: flex; display: flex;

View File

@ -200,10 +200,10 @@
} }
const params = encodeURIComponent(JSON const params = encodeURIComponent(JSON
.stringify(obj)); .stringify(obj));
uni.navigateTo({ // uni.navigateTo({
url: '/pages/receipt/details?params=' + // url: '/pages/receipt/details?params=' +
params // params
}) // })
} }
}) })
}, },

View File

@ -11,10 +11,10 @@
</view> </view>
<button class="searchBtn" type="default" @click="search"></button> <button class="searchBtn" type="default" @click="search"></button>
<!-- <button class="searchBtn" type="default" @click="dropTable"></button> <!-- <button class="searchBtn" type="default" @click="dropTable"></button> -->
<button class="searchBtn" type="default" @click="dropData"></button> --> <!-- <button class="searchBtn" type="default" @click="dropData"></button>
<!-- <button class="searchBtn" type="default" @click="createTable"></button> <button class="searchBtn" type="default" @click="createTable"></button> -->
<button class="searchBtn" type="default" @click="delAll"></button> <!-- <button class="searchBtn" type="default" @click="delAll"></button>
<button class="searchBtn" type="default" @click="delAllData"></button> --> <button class="searchBtn" type="default" @click="delAllData"></button> -->
</view> </view>
<view class="itemList"> <view class="itemList">
@ -235,12 +235,12 @@
}, },
dropTable() { dropTable() {
console.log('删除表'); console.log('删除表');
let sql = 'DROP TABLE abnormalConditionRespList;' let sql = 'DROP TABLE workSignTable;'
this.executeSql(sql) this.executeSql(sql)
}, },
dropData() { dropData() {
console.log('删除数据'); console.log('删除数据');
let sql = "delete from shipOption" let sql = "delete from shipInfoTable"
this.executeSql(sql) this.executeSql(sql)
}, },
// //
@ -334,12 +334,14 @@
} }
}, },
// //
shipDataInfo(info) { shipDataInfo(info, vtpId) {
console.log(vtpId)
console.log(info)
let date = new Date().getTime() let date = new Date().getTime()
let webId = uuidv4() let webId = uuidv4()
let webDate = api.getDate(date) let webDate = api.getDate(date)
let sql = let sql =
`insert into shipInfoTable values('${webId}','${this.vtpId}','${info.agencyCname}','${info.ctyCnname}','${info.ctyCode}','${info.dataVersion}','${info.shipCname}', `insert into shipInfoTable values('${webId}','${vtpId}','${info.agencyCname}','${info.ctyCnname}','${info.ctyCode}','${info.dataVersion}','${info.shipCname}',
'${info.shipTypeName}','${info.spmBoardCentrele}','${info.spmBoardCentrerg}','${info.spmBoardFrontle}','${info.spmBoardFrontrg}','${info.spmBoardLaterle}', '${info.shipTypeName}','${info.spmBoardCentrele}','${info.spmBoardCentrerg}','${info.spmBoardFrontle}','${info.spmBoardFrontrg}','${info.spmBoardLaterle}',
'${info.spmBoardLaterrg}','${info.spmCab}','${info.spmCabinht}','${info.spmCountrycd}','${info.spmEdicd}','${info.spmId}', '${info.spmBoardLaterrg}','${info.spmCab}','${info.spmCabinht}','${info.spmCountrycd}','${info.spmEdicd}','${info.spmId}',
'${info.spmLightWeight}','${info.spmMadeTime}','${info.spmMintide}','${info.spmMmsi}','${info.spmNationality}','${info.spmPilot}', '${info.spmLightWeight}','${info.spmMadeTime}','${info.spmMintide}','${info.spmMmsi}','${info.spmNationality}','${info.spmPilot}',
@ -418,7 +420,7 @@
this.vtpId = item.vtpId this.vtpId = item.vtpId
uni.setStorageSync('vtpId', item.vtpId); uni.setStorageSync('vtpId', item.vtpId);
this.downloadData = res.data.data this.downloadData = res.data.data
this.shipDataInfo(this.downloadData.shipmentShipManage) this.shipDataInfo(this.downloadData.shipmentShipManage, item.vtpId)
this.optionData = [] this.optionData = []
// //
this.downloadData.epTypeList.forEach(v => { this.downloadData.epTypeList.forEach(v => {
@ -730,6 +732,7 @@
}, },
// //
upload(item) { upload(item) {
console.log(item)
if (item.padLockStatus == 0) { if (item.padLockStatus == 0) {
this.lotusLoadingData.isShow = true this.lotusLoadingData.isShow = true
this.allArr.forEach(v => { this.allArr.forEach(v => {
@ -907,6 +910,7 @@
that.mafiListRespList = value that.mafiListRespList = value
} else if (tableName == "workSignTable") { } else if (tableName == "workSignTable") {
that.workSignTable = value that.workSignTable = value
console.log(that.workSignTable)
} }
}).catch((error) => { }).catch((error) => {
// reject // reject
@ -953,6 +957,7 @@
background-color: #f5f6fa; background-color: #f5f6fa;
display: flex; display: flex;
min-height: calc(100vh - 68px); min-height: calc(100vh - 68px);
margin-top: 66px;
} }
.content { .content {

View File

@ -199,6 +199,7 @@
title: "杂项单证签名", title: "杂项单证签名",
tabsValue: 0, tabsValue: 0,
tabsList: [], tabsList: [],
vvyId: "",
vvyName: "", vvyName: "",
webId: "", webId: "",
aIdList: [], aIdList: [],
@ -325,8 +326,8 @@
} }
that.tabsList = that.tabsArr that.tabsList = that.tabsArr
that.shiftInfo = that.tabsList[that.tabsValue].shiftArr that.shiftInfo = that.tabsList[that.tabsValue].shiftArr
console.log(that.shiftInfo)
that.shiftList = that.tabsList[that.tabsValue].shiftArr that.shiftList = that.tabsList[that.tabsValue].shiftArr
that.vvyId = that.tabsList[0].shiftArr[0].vvyId
that.vvyName = that.tabsList[0].shiftArr[0].vvyName that.vvyName = that.tabsList[0].shiftArr[0].vvyName
let dateId = that.tabsList[that.tabsValue].shiftArr[0].workEndTime let dateId = that.tabsList[that.tabsValue].shiftArr[0].workEndTime
that.dateId = dateId.slice(0, 10) that.dateId = dateId.slice(0, 10)
@ -515,7 +516,7 @@
signType: Number(signType), // 0 1 / signType: Number(signType), // 0 1 /
signTable: "2", signTable: "2",
tabsValue: this.tabsValue, tabsValue: this.tabsValue,
vvyId: this.qtList.vvyId, vvyId: this.vvyId,
} }
const params = encodeURIComponent(JSON.stringify(obj)); const params = encodeURIComponent(JSON.stringify(obj));
uni.navigateTo({ uni.navigateTo({

View File

@ -297,44 +297,10 @@
// //
// //
fcList: [], fcList: [],
fcUlList: [{ fcUlList: [],
retallyType: "",
retallyTypeName: "",
retallyOrigin: "",
retallyTerminus: "",
carType: "",
carTypeName: "",
datetime: ['', ''],
retallyStartTime: "",
retallyEndTime: "",
goodsNumber: 0,
goodsVolume: 0,
goodsWeight: 0,
mafiGroupNum: 0,
mfType: false,
editStatus: 0,
}],
// //
otherArr: [{ otherArr: [],
webId: '',
contactId: '',
jsworker: 0,
datetime: ['', ''],
startTime: '',
endTime: '',
zlValue: 0,
tjValue: 0,
ptworker: 0,
datetime2: ['', ''],
startTime2: '',
endTime2: '',
zlValue2: 0,
tjValue2: 0,
describe: '',
dgWork: '',
remark: ''
}],
// //
optionData: [], optionData: [],
@ -725,7 +691,7 @@
}) })
this.sShiftDate = beginTime this.sShiftDate = beginTime
this.eShiftDate = endTime this.eShiftDate = endTime
}, },
// //
changeLog(item, type) { changeLog(item, type) {

View File

@ -65,6 +65,7 @@
this.signTable = JSON.parse(decodeURIComponent(option.params)).signTable this.signTable = JSON.parse(decodeURIComponent(option.params)).signTable
this.tabsValue = JSON.parse(decodeURIComponent(option.params)).tabsValue this.tabsValue = JSON.parse(decodeURIComponent(option.params)).tabsValue
this.vvyId = JSON.parse(decodeURIComponent(option.params)).vvyId this.vvyId = JSON.parse(decodeURIComponent(option.params)).vvyId
console.log(this.vvyId)
this.backUrl = `/pages/shipWork/${this.nextUrl}` this.backUrl = `/pages/shipWork/${this.nextUrl}`
that = this; that = this;
id = option.id; id = option.id;
@ -162,7 +163,6 @@
}); });
return; return;
} else { } else {
let info = that.shipInfo
let signId = that.sginId let signId = that.sginId
uni.canvasToTempFilePath({ uni.canvasToTempFilePath({
canvasId: 'mycanvas', canvasId: 'mycanvas',
@ -177,7 +177,8 @@
let webId = uuidv4() let webId = uuidv4()
let webDate = api.getDate(date) let webDate = api.getDate(date)
let sql = let sql =
`insert into workSignTable values('${webId}','${info.vtpId}','${signId}','${that.signImgUrl}','${that.signTable}','${that.signType}','${that.vvyId}','${webDate}')` `insert into workSignTable values('${webId}','${that.shipInfo.vtpId}','${signId}','${that.signImgUrl}','${that.signTable}','${that.signType}','${that.vvyId}','${webDate}')`
console.log(sql)
sqlite.executeSqlCeshi(sql).then(( sqlite.executeSqlCeshi(sql).then((
value) => { value) => {
// resolve // resolve
@ -212,6 +213,7 @@
// resolve // resolve
if (tableName == 'shipInfoTable') { if (tableName == 'shipInfoTable') {
this.shipInfo = value[0] this.shipInfo = value[0]
console.log(this.shipInfo)
} }
}).catch((error) => { }).catch((error) => {
// reject // reject

View File

@ -246,12 +246,10 @@
// //
changeLog2(e) { changeLog2(e) {
this.unmoorTime = e this.unmoorTime = e
console.log(e)
}, },
// //
changeLog3(e) { changeLog3(e) {
this.shiftingBerthTime = e this.shiftingBerthTime = e
console.log(e)
}, },
// //
changeLog(e) { changeLog(e) {
@ -299,7 +297,6 @@
`insert into attachUnmoorRespList values('${sauId}','${this.vtpId}','${this.zlShip}','${this.vvyId}','${this.vvyName}', `insert into attachUnmoorRespList values('${sauId}','${this.vtpId}','${this.zlShip}','${this.vvyId}','${this.vvyName}',
'${this.importExportFlagName}','${this.bthId}','${this.bthIdName}','${this.attachTime}','${this.unmoorTime}', '${this.importExportFlagName}','${this.bthId}','${this.bthIdName}','${this.attachTime}','${this.unmoorTime}',
'${this.shiftingBerthTime}','${this.noProductBerthStTime}','${this.noProductBerthEdTime}','${0}','${webStatus}','${webDate}')` '${this.shiftingBerthTime}','${this.noProductBerthStTime}','${this.noProductBerthEdTime}','${0}','${webStatus}','${webDate}')`
console.log(sql)
this.executeSql(sql) this.executeSql(sql)
} }
uni.navigateTo({ uni.navigateTo({

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

View File

@ -0,0 +1,6 @@
## 2.2.22023-08-31
修复部分问题
## 2.2.12023-08-31
修改部分小bug
## 2.22023-08-17
新增弹框签名笔锋

View File

@ -0,0 +1,448 @@
<template>
<div class="signature">
<div class="inputs" v-if="!popup">
<div class="label" :class="required?'labelqr':''">{{label}}</div>
<div>
<div v-if="value" class="images">
<image class="images" mode="aspectFit" :src="value"></image>
<view v-if="!readonly" @click="toDeleteImg" class="icons">
<!-- #ifndef MP-WEIXIN -->
<svg t="1685617606397" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="3710" width="32" height="32">
<path
d="M202.666667 256h-42.666667a32 32 0 0 1 0-64h704a32 32 0 0 1 0 64H266.666667v565.333333a53.333333 53.333333 0 0 0 53.333333 53.333334h384a53.333333 53.333333 0 0 0 53.333333-53.333334V352a32 32 0 0 1 64 0v469.333333c0 64.8-52.533333 117.333333-117.333333 117.333334H320c-64.8 0-117.333333-52.533333-117.333333-117.333334V256z m224-106.666667a32 32 0 0 1 0-64h170.666666a32 32 0 0 1 0 64H426.666667z m-32 288a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z m170.666666 0a32 32 0 0 1 64 0v256a32 32 0 0 1-64 0V437.333333z"
fill="#d81e06" p-id="3711"></path>
</svg>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<view class="Deletes">X</view>
<!-- #endif -->
</view>
</div>
<div v-if="!value && !readonly" class="explain" @click="toPop">
{{placeholder?placeholder:'点击签名'}}
</div>
</div>
</div>
<view class="bottomPopup" v-if="showPopup">
<transition name="slide-up" appear>
<view class="popup-content">
<view class="popup">
<div class="hader" v-if="!isHeight">
<div @click="toclear"></div>
<div class="text">{{label}}</div>
<div @click="isEmpty"></div>
</div>
<div class="wgSignature">
<div v-if="isHeight" key="999" style="width: 750rpx ;height: 100vh;">
<jp-signature v-if="" :beforeDelay="200" landscape disableScroll ref="signatureRef"
:openSmooth="true" :penSize="6" :bounding-box="true"></jp-signature>
</div>
<div v-else key="888" style="width: 750rpx ;height: 35vh;">
<jp-signature :beforeDelay="200" :penSize="4" disableScroll ref="signatureRef" :openSmooth="true"
:bounding-box="true"></jp-signature>
</div>
<div v-if="!isHeight" class="magnify" @click="Tomagnify">
<!-- #ifndef MP-WEIXIN -->
<svg t="1686894300542" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="3201" width="32" height="32">
<path
d="M853.333333 0h-682.666666C75.093333 0 0 75.093333 0 170.666667v682.666666C0 948.906667 75.093333 1024 170.666667 1024h682.666666c95.573333 0 170.666667-75.093333 170.666667-170.666667v-682.666666C1024 75.093333 948.906667 0 853.333333 0zM955.733333 853.333333c0 54.613333-47.786667 102.4-102.4 102.4h-682.666666c-54.613333 0-102.4-47.786667-102.4-102.4v-682.666666C68.266667 116.053333 116.053333 68.266667 170.666667 68.266667h682.666666c54.613333 0 102.4 47.786667 102.4 102.4v682.666666z"
fill="#777777" p-id="3202"></path>
<path
d="M402.773333 573.44L204.8 771.413333V648.533333c0-20.48-13.653333-34.133333-34.133333-34.133333s-34.133333 13.653333-34.133334 34.133333v204.8c0 20.48 13.653333 34.133333 34.133334 34.133334h204.8c20.48 0 34.133333-13.653333 34.133333-34.133334s-13.653333-34.133333-34.133333-34.133333H252.586667l197.973333-197.973333c13.653333-13.653333 13.653333-34.133333 0-47.786667-13.653333-13.653333-34.133333-13.653333-47.786667 0zM853.333333 136.533333h-204.8c-20.48 0-34.133333 13.653333-34.133333 34.133334s13.653333 34.133333 34.133333 34.133333h122.88L573.44 402.773333c-13.653333 13.653333-13.653333 34.133333 0 47.786667 13.653333 13.653333 34.133333 13.653333 47.786667 0L819.2 252.586667v122.88c0 20.48 13.653333 34.133333 34.133333 34.133333s34.133333-13.653333 34.133334-34.133333v-204.8c0-20.48-13.653333-34.133333-34.133334-34.133334z"
fill="#777777" p-id="3203"></path>
</svg>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
全屏
<!-- #endif -->
</div>
<!-- #ifndef MP-WEIXIN -->
<div v-if="isHeight" class="magnify" @click="Tomagnify">
<svg t="1685611713082" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="1741" width="32" height="32">
<path
d="M872.3 899.1h-718c-14.3 0-26-11.7-26-26v-718c0-14.3 11.7-26 26-26h718c14.3 0 26 11.7 26 26v718c0 14.3-11.6 26-26 26z m-711.9-32h706v-706h-706v706z"
fill="" p-id="1742"></path>
<path
d="M487.4 488.6l-166.1-0.2c-8.8 0-16-7.2-16-16s7.2-16 16-16l134.1 0.1 0.1-134.1c0-8.8 7.2-16 16-16s16 7.2 16 16l-0.1 166.2z"
fill="" p-id="1743"></path>
<path
d="M438.5 461.1L256 278.6c-6.2-6.2-6.2-16.4 0-22.6 6.2-6.2 16.4-6.2 22.6 0l182.5 182.5c6.2 6.2 6.2 16.4 0 22.6-6.3 6.2-16.4 6.2-22.6 0zM553.2 719.7c-8.8 0-16-7.2-16-16l0.2-166.1 166.1 0.2c8.8 0 16 7.2 16 16s-7.2 16-16 16l-134.1-0.1-0.1 134.1c-0.1 8.8-7.3 15.9-16.1 15.9z"
fill="" p-id="1744"></path>
<path
d="M745.2 767.9L548.5 572.6l22.5-22.7 196.7 195.3c6.3 6.2 6.3 16.4 0.1 22.6-6.2 6.3-16.4 6.3-22.6 0.1z"
fill="" p-id="1745"></path>
</svg>
</div>
<!-- #endif -->
<div v-if="isHeight" class="gather">
<div class="imgs" @click="undo">
<!-- #ifndef MP-WEIXIN -->
<svg t="1692082493252" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="4026" width="22" height="22">
<path
d="M396.8 200.533333l64 64L384 341.333333h298.666667c119.466667 0 213.333333 93.866667 213.333333 213.333334s-93.866667 213.333333-213.333333 213.333333H298.666667v-85.333333h384c72.533333 0 128-55.466667 128-128s-55.466667-128-128-128H170.666667l226.133333-226.133334z"
fill="#444444" p-id="4027"></path>
</svg>
<!-- #endif -->
<text>撤销</text>
</div>
<div class="imgs" @click="deleteImg">
<!-- #ifndef MP-WEIXIN -->
<svg t="1686205282563" class="icon" viewBox="0 0 1050 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="2409" width="20" height="20">
<path
d="M1024 1024H26.25641a26.25641 26.25641 0 1 1 0-52.512821h997.74359a26.25641 26.25641 0 0 1 0 52.512821zM630.153846 887.466667l-21.005128 31.507692H262.564103l-180.434052-155.017846L36.758974 729.928205l31.507693-42.010256L503.020308 12.077949l36.023795-8.086975L966.235897 288.820513l45.42359 30.299897-30.877538 42.482872zM532.795077 63.015385l-422.203077 656.410256L262.564103 867.774359V866.461538h318.542769l355.98441-534.002871z"
fill="#484D55" p-id="2410"></path>
<path
d="M525.128205 26.25641l472.615385 262.564103-210.051282 315.076923-472.615385-262.564103z"
fill="#484D55" p-id="2411"></path>
</svg>
<!-- #endif -->
<text>清除</text>
</div>
<div class="qx" @click="toclear"></div>
<div class="wc" @click="isEmpty"></div>
</div>
<div v-else class="gather2">
<div class="imgs" @click="undo">
<!-- #ifndef MP-WEIXIN -->
<svg t="1692082493252" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="4026" width="30" height="30">
<path
d="M396.8 200.533333l64 64L384 341.333333h298.666667c119.466667 0 213.333333 93.866667 213.333333 213.333334s-93.866667 213.333333-213.333333 213.333333H298.666667v-85.333333h384c72.533333 0 128-55.466667 128-128s-55.466667-128-128-128H170.666667l226.133333-226.133334z"
fill="#444444" p-id="4027"></path>
</svg>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
撤销
<!-- #endif -->
</div>
<div class="imgs" @click="deleteImg">
<!-- #ifndef MP-WEIXIN -->
<svg t="1686205282563" class="icon" viewBox="0 0 1050 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" p-id="2409" width="25" height="25">
<path
d="M1024 1024H26.25641a26.25641 26.25641 0 1 1 0-52.512821h997.74359a26.25641 26.25641 0 0 1 0 52.512821zM630.153846 887.466667l-21.005128 31.507692H262.564103l-180.434052-155.017846L36.758974 729.928205l31.507693-42.010256L503.020308 12.077949l36.023795-8.086975L966.235897 288.820513l45.42359 30.299897-30.877538 42.482872zM532.795077 63.015385l-422.203077 656.410256L262.564103 867.774359V866.461538h318.542769l355.98441-534.002871z"
fill="#484D55" p-id="2410"></path>
<path
d="M525.128205 26.25641l472.615385 262.564103-210.051282 315.076923-472.615385-262.564103z"
fill="#484D55" p-id="2411"></path>
</svg>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
清除
<!-- #endif -->
</div>
</div>
</div>
</view>
</view>
</transition>
</view>
</div>
</template>
<script>
/**
* 手写签名组件
* 用于手写签名弹框签名支持小屏和全屏
*
*********参数********
* label 选项名称
* value 初始值String支持bas64url 等图片显示
* required 是否显示必填
* placeholder 默认值
* readonly 是否只读
*
* *********回调********
* @input(e) 点击确认 e生成的图片数据(bas64)
*
*********方法********
* isEmpty() 生成图片
* deleteImg() 删除图片
*/
export default {
props: {
popup: {
type: [Boolean, String],
default: false,
},
label: {
type: String,
default: '手写签名',
},
value: {
type: String,
default: '',
},
required: {
type: [Boolean, String],
default: false,
},
placeholder: {
type: String,
default: '点击签名',
},
readonly: {
type: [Boolean, String],
default: false,
},
},
data() {
return {
showPopup: false,
isHeight: false,
height1: uni.getSystemInfoSync().windowWidth / 2,
width: uni.getSystemInfoSync().windowWidth, //
height: uni.getSystemInfoSync().windowHeight, //
showPicker: false
}
},
methods: {
undo() {
this.$refs.signatureRef.undo()
},
toPop() {
this.showPopup = true
},
toDeleteImg() {
this.$emit('input', '')
},
toclear() {
this.isHeight = false
this.showPopup = false
},
close() {
this.isHeight = false
this.showPopup = false
this.$refs.signatureRef.clear()
},
deleteImg() {
this.$refs.signatureRef.clear()
},
toDataURL(url) {
this.$emit('input', url)
this.showPicker = false
console.log(url)
},
Tomagnify() {
this.isHeight = !this.isHeight
this.$refs.signatureRef.clear()
},
isEmpty() {
this.$refs.signatureRef.canvasToTempFilePath({
quality: 0.8,
success: (res) => {
if (this.required) {
if (!res.isEmpty) {
this.$emit('input', res.tempFilePath)
this.isHeight = false
this.showPopup = false
} else {
uni.showToast({
title: '请先签名',
icon: 'none'
});
}
} else {
this.$emit('input', res.tempFilePath)
this.isHeight = false
this.showPopup = false
}
}
})
},
},
beforeCreate() {},
created() {}
}
</script>
<style scoped lang="scss">
.bottomPopup {
position: fixed;
left: 0;
top: 0;
bottom: 0;
right: 0;
z-index: 999;
background-color: rgba(0, 0, 0, 0.5);
.popup-content {
position: fixed;
left: 0;
right: 0;
bottom: 0;
// top: 0;
background-color: #ffffff;
}
.slide-up-enter-active,
.slide-up-leave-active {
transition: all .3s ease;
}
.slide-up-enter,
.slide-up-leave-to {
transform: translateY(100%);
}
}
.signature {
.inputs {
background-color: #fff;
padding: 10px 16px;
.label {
line-height: 35px;
position: relative;
}
.labelqr:before {
content: "*";
color: #f00;
}
.explain {
width: 100%;
background-color: #f1f1f1;
text-align: center;
line-height: 40px;
border: 1px dotted #ccc;
color: #999;
}
.Deletes {
border: 1px solid #f00;
width: 30rpx;
height: 30rpx;
border-radius: 50%;
color: #f00;
text-align: center;
font-size: 30rpx;
line-height: 30rpx;
}
}
.images {
width: 300rpx;
height: 150rpx;
position: relative;
.icons {
position: absolute;
top: 0;
right: 0;
}
}
}
.popup {
background-color: #fff;
}
.hader {
display: flex;
justify-content: center;
text-align: center;
height: 45px;
border-bottom: 1px solid #f5f5f5;
align-items: center;
div {
text-align: center;
width: 80px;
color: #E59C36;
}
.text {
color: #333;
flex: 1;
}
}
.wgSignature {
position: relative;
.gather2 {
color: #00aaff;
position: absolute;
bottom: 20rpx;
right: 0rpx;
display: flex;
justify-content: center;
z-index: 2;
.imgs {
margin-right: 15px;
}
}
.gather {
position: absolute;
z-index: 2;
display: flex;
justify-content: center;
align-items: center;
transform: rotate(90deg);
bottom: 160px;
left: -250rpx;
text {
margin-left: 3px;
}
div {
width: 80px;
margin: 5px;
text-align: center;
line-height: 40px;
}
.qx {
background-color: #f5f5f5;
border-radius: 20px;
}
.wc {
color: #fff;
background-color: #E59C36;
border-radius: 20px;
}
img {
width: 25px;
height: 25px;
}
}
.magnify {
position: absolute;
top: 5px;
right: 5px;
z-index: 3;
color: #00aaff;
uni-image {
width: 25px;
height: 25px;
}
}
.eliminate {
position: absolute;
bottom: 5px;
right: 5px;
uni-image {
width: 25px;
height: 25px;
}
}
}
</style>

View File

@ -0,0 +1,118 @@
export const uniContext = (canvasId, context) => {
let ctx = uni.createCanvasContext(canvasId, context)
if (!ctx.uniDrawImage) {
ctx.uniDrawImage = ctx.drawImage
ctx.drawImage = (image, ...agrs) => {
ctx.uniDrawImage(image.src, ...agrs)
}
}
if (!ctx.getImageData) {
ctx.getImageData = (x, y, width, height) => {
return new Promise((resolve, reject) => {
// #ifdef MP || VUE2
if (context.proxy) context = context.proxy
// #endif
uni.canvasGetImageData({
canvasId,
x,
y,
width,
height,
success(res) {
resolve(res)
},
fail(error) {
reject(error)
}
}, context)
})
}
}
return ctx
}
class Image {
constructor() {
this.currentSrc = null
this.naturalHeight = 0
this.naturalWidth = 0
this.width = 0
this.height = 0
this.tagName = 'IMG'
}
set src(src) {
this.currentSrc = src
uni.getImageInfo({
src,
success: (res) => {
this.naturalWidth = this.width = res.width
this.naturalHeight = this.height = res.height
this.onload()
},
fail: () => {
this.onerror()
}
})
}
get src() {
return this.currentSrc
}
}
export const createImage = () => {
return new Image()
}
export function useCurrentPage() {
const pages = getCurrentPages();
return pages[pages.length - 1];
}
export const toDataURL = (canvasId, context, options = {}) => {
// #ifdef MP-QQ
// context = context.$scope
// #endif
// #ifdef MP-ALIPAY
context = ''
// #endif
return new Promise((resolve, reject) => {
let {canvas, width, height, destWidth = 0, destHeight = 0, x = 0, y = 0} = options
// #ifdef MP-ALIPAY
const {pixelRatio} =uni.getSystemInfoSync()
if(!destWidth || !destHeight) {
destWidth = width * pixelRatio;
destHeight = height * pixelRatio;
width = destWidth;
height = destHeight;
x = x * pixelRatio
y = y * pixelRatio
}
// #endif
const params = {
...options,
canvasId,
id: canvasId,
// #ifdef MP-ALIPAY
x,
y,
width,
height,
destWidth,
destHeight,
// #endif
canvas,
success: (res) => {
resolve(res.tempFilePath)
},
fail: (err) => {
reject(err)
}
}
if(canvas && canvas.toTempFilePath) {
canvas.toTempFilePath(params)
} else {
uni.canvasToTempFilePath(params, context)
}
})
}

View File

@ -0,0 +1,475 @@
<template>
<view class="lime-signature" v-if="show" :style="[canvasStyle, styles]" ref="limeSignature">
<!-- #ifndef APP-VUE || APP-NVUE -->
<canvas v-if="useCanvas2d" class="lime-signature__canvas" :id="canvasId" type="2d"
:disableScroll="disableScroll" @touchstart="touchStart" @touchmove="touchMove"
@touchend="touchEnd"></canvas>
<canvas v-else :disableScroll="disableScroll" class="lime-signature__canvas" :canvas-id="canvasId"
:id="canvasId" :width="canvasWidth" :height="canvasHeight" @touchstart="touchStart" @touchmove="touchMove"
@touchend="touchEnd" @mousedown="touchStart" @mousemove="touchMove" @mouseup="touchEnd"></canvas>
<canvas class="offscreen" canvas-id="offscreen" id="offscreen"
:style="'width:' + offscreenSize[0] + 'px;height:' + offscreenSize[1] + 'px'" :width="offscreenSize[0]"
:height="offscreenSize[1]">
</canvas>
<view v-if="showMask" class="mask" @touchstart="touchStart" @touchmove.stop.prevent="touchMove" @touchend="touchEnd"></view>
<!-- #endif -->
<!-- #ifdef APP-VUE -->
<view :id="canvasId" :disableScroll="disableScroll" :rparam="param" :change:rparam="sign.update"
:rclear="rclear" :change:rclear="sign.clear" :rundo="rundo" :change:rundo="sign.undo" :rsave="rsave"
:change:rsave="sign.save" :rempty="rempty" :change:rempty="sign.isEmpty"></view>
<!-- #endif -->
<!-- #ifdef APP-NVUE -->
<web-view src="/uni_modules/lime-signature/hybrid/html/index.html" class="lime-signature__canvas" ref="webview"
@pagefinish="onPageFinish" @error="onError" @onPostMessage="onMessage"></web-view>
<!-- #endif -->
</view>
</template>
<script>
// #ifndef APP-NVUE
import { canIUseCanvas2d, wrapEvent, requestAnimationFrame, sleep , isPC} from './utils'
import {Signature} from './signature'
// import {Signature} from '@signature';
import { uniContext, createImage, toDataURL } from './context'
// #endif
import props from './props';
import { base64ToPath, getRect } from './utils'
/**
* LimeSignature 手写板签名
* @description 手写板签名插件一款能跑在uniapp各端中的签名插件支持横屏背景色笔画颜色笔画大小等功能,可生成有内容的区域减小图片尺寸节省空间
* @tutorial https://ext.dcloud.net.cn/plugin?id=4354
* @property {Number} penSize 画笔大小
* @property {Number} minLineWidth 线条最小宽
* @property {Number} maxLineWidth 线条最大宽
* @property {String} penColor 画笔颜色
* @property {String} background 背景颜色,不填则为透明
* @property {type} 指定 canvas 类型
* @value 2d canvas 2d
* @value '' canvas 2d 旧接口微信不再维护
* @property {Boolean} openSmooth 模拟笔锋
* @property {Number} beforeDelay 延时初始化在放在弹窗里可以使用 毫秒
* @property {Number} maxHistoryLength 限制历史记录数即最大可撤销数传入0则关闭历史记录功能
* @property {Boolean} landscape 横屏使用后在最后生成图片时会图片旋转90度
* @property {Boolean} disableScroll 当在写字时禁止屏幕滚动以及下拉刷新nvue无效
* @property {Boolean} boundingBox 只生成内容区域即未画部分不生成有性能的损耗
*/
export default {
props,
data() {
return {
canvasWidth: null,
canvasHeight: null,
offscreenWidth: null,
offscreenHeight: null,
useCanvas2d: true,
show: true,
offscreenStyles: '',
showMask: false,
// #ifdef APP-PLUS
rclear: 0,
rundo: 0,
rsave: JSON.stringify({
n: 0,
fileType: 'png',
quality: 1
}),
rempty: 0,
risEmpty: true,
toDataURL: null,
tempFilePath: [],
// #endif
}
},
computed: {
canvasId() {
// #ifdef VUE2
return `lime-signature${this._uid}`
// #endif
// #ifdef VUE3
return `lime-signature${this._.uid}`
// #endif
},
offscreenId() {
return this.canvasId + 'offscreen'
},
offscreenSize() {
const {offscreenWidth,offscreenHeight} = this
return this.landscape ? [offscreenHeight, offscreenWidth] : [offscreenWidth, offscreenHeight]
},
canvasStyle() {
const { canvasWidth, canvasHeight, background } = this
return {
width: canvasWidth && (canvasWidth + 'px'),
height: canvasHeight && (canvasHeight + 'px'),
background: background
}
},
param() {
const {
penColor,
penSize,
background,
landscape,
boundingBox,
openSmooth,
minLineWidth,
maxLineWidth,
minSpeed,
maxWidthDiffRate,
maxHistoryLength,
disableScroll
} = this
return JSON.parse(JSON.stringify({
penColor,
penSize,
background,
landscape,
boundingBox,
openSmooth,
minLineWidth,
maxLineWidth,
minSpeed,
maxWidthDiffRate,
maxHistoryLength,
disableScroll
}))
}
},
// #ifdef APP-NVUE
watch: {
param(v) {
this.$refs.webview.evalJS(`update(${JSON.stringify(v)})`)
}
},
// #endif
// #ifndef APP-PLUS
created() {
this.useCanvas2d = this.type == '2d' && canIUseCanvas2d() && !isPC
this.showMask = isPC
},
// #endif
// #ifndef APP-PLUS
async mounted() {
if (this.beforeDelay) {
await sleep(this.beforeDelay)
}
const config = await this.getContext()
this.signature = new Signature(config)
this.canvasEl = this.signature.canvas.get('el')
this.offscreenWidth = this.canvasWidth = this.signature.canvas.get('width')
this.offscreenHeight = this.canvasHeight = this.signature.canvas.get('height')
this.stopWatch = this.$watch('param', (v) => {
this.signature.pen.setOption(v)
}, {
immediate: true
})
},
// #endif
// #ifndef APP-PLUS
// #ifdef VUE3
beforeUnmount() {
this.stopWatch && this.stopWatch()
this.signature.destroy()
this.signature = null
this.show = false;
},
// #endif
// #ifdef VUE2
beforeDestroy() {
this.stopWatch && this.stopWatch()
this.signature.destroy()
this.show = false;
this.signature = null
},
// #endif
// #endif
methods: {
// #ifdef MP-QQ
// toJSON() { return this },
// #endif
// #ifdef APP-PLUS
onPageFinish() {
this.$refs.webview.evalJS(`update(${JSON.stringify(this.param)})`)
},
onMessage(e = {}) {
const {
detail: {
data: [res]
}
} = e
if (res.event?.save) {
this.toDataURL = res.event.save
}
if (res.event?.changeSize) {
const {
width,
height
} = res.event.changeSize
}
if (res.event.hasOwnProperty('isEmpty')) {
this.risEmpty = res.event.isEmpty
}
if (res.event?.file) {
this.tempFilePath.push(res.event.file)
if (this.tempFilePath.length > 7) {
this.tempFilePath.shift()
}
return
}
if (res.event?.success) {
if (res.event.success) {
this.tempFilePath.push(res.event.success)
if (this.tempFilePath.length > 8) {
this.tempFilePath.shift()
}
this.toDataURL = this.tempFilePath.join('')
this.tempFilePath = []
} else {
this.$emit('fail', 'canvas no data')
}
return
}
},
// #endif
undo() {
// #ifdef APP-VUE || APP-NVUE
this.rundo += 1
// #endif
// #ifdef APP-NVUE
this.$refs.webview.evalJS(`undo()`)
// #endif
// #ifndef APP-VUE
if (this.signature)
this.signature.undo()
// #endif
},
clear() {
// #ifdef APP-VUE || APP-NVUE
this.rclear += 1
// #endif
// #ifdef APP-NVUE
this.$refs.webview.evalJS(`clear()`)
// #endif
// #ifndef APP-VUE
if (this.signature)
this.signature.clear()
// #endif
},
isEmpty() {
// #ifdef APP-NVUE
this.$refs.webview.evalJS(`isEmpty()`)
// #endif
// #ifdef APP-VUE || APP-NVUE
this.rempty += 1
// #endif
// #ifndef APP-VUE || APP-NVUE
return this.signature.isEmpty()
// #endif
},
canvasToTempFilePath(param) {
const isEmpty = this.isEmpty()
// #ifdef APP-NVUE
this.$refs.webview.evalJS(`save()`)
// #endif
// #ifdef APP-VUE || APP-NVUE
const stopURLWatch = this.$watch('toDataURL', (v, n) => {
if (v && v !== n) {
// if(param.pathType == 'url') {
base64ToPath(v).then(res => {
param.success({
tempFilePath: res,
isEmpty: this.risEmpty
})
})
// } else {
// param.success({tempFilePath: v,isEmpty: this.risEmpty })
// }
this.toDataURL = ''
}
stopURLWatch && stopURLWatch()
})
const {
fileType,
quality
} = param
const rsave = JSON.parse(this.rsave)
rsave.n++
rsave.fileType = fileType
rsave.quality = quality
this.rsave = JSON.stringify(rsave)
// #endif
// #ifndef APP-VUE || APP-NVUE
const success = (success) => param.success && param.success(success)
const fail = (err) => param.fail && param.fail(err)
const { canvas } = this.signature.canvas.get('el')
const {
background,
landscape,
boundingBox
} = this
let width = this.signature.canvas.get('width')
let height = this.signature.canvas.get('height')
let x = 0
let y = 0
const canvasToTempFilePath = (image) => {
const context = uni.createCanvasContext('offscreen', this)
context.save()
context.setTransform(1, 0, 0, 1, 0, 0)
if (landscape) {
context.translate(0, width)
context.rotate(-Math.PI / 2)
}
if (background) {
context.fillStyle = background
context.fillRect(0, 0, width, height)
}
context.drawImage(image, 0, 0, width, height);
context.draw(false, () => {
toDataURL('offscreen', this, param).then((res) => {
const size = Math.max(width, height)
context.restore()
context.clearRect(0, 0, size, size)
success({
tempFilePath: res,
isEmpty
})
})
})
}
const next = () => {
// #ifndef MP-WEIXIN
const param = { x, y, width, height, canvas }
// #endif
// #ifdef MP-WEIXIN
const param = { x, y, width, height, canvas: this.useCanvas2d ? canvas : null}
// #endif
toDataURL(this.canvasId, this, param).then(canvasToTempFilePath).catch(fail)
}
// PC ImageData 0
if (boundingBox && !isPC) {
this.signature.getContentBoundingBox(async res => {
this.offscreenWidth = width = res.width
this.offscreenHeight = height = res.height
x = res.startX
y = res.startY
await sleep(100)
next()
})
} else {
next()
}
// #endif
},
// #ifndef APP-PLUS
getContext() {
return getRect(`#${this.canvasId}`, {
context: this,
type: this.useCanvas2d ? 'fields' : 'boundingClientRect'
}).then(res => {
if (res) {
let { width, height, node: canvas, left, top, right} = res
let {pixelRatio} = uni.getSystemInfoSync()
let context;
if (canvas) {
context = canvas.getContext('2d')
canvas.width = width * pixelRatio;
canvas.height = height * pixelRatio;
} else {
pixelRatio = 1
context = uniContext(this.canvasId, this)
canvas = {
createImage,
toDataURL: () => toDataURL(this.canvasId, this),
requestAnimationFrame
}
}
// 使stroke
context.clearRect(0, 0, width, height)
return {
left,
top,
right,
width,
height,
context,
canvas,
pixelRatio
};
}
})
},
getTouch(e) {
if(isPC && this.canvasRect) {
e.touches = e.touches.map(item => {
return {
...item,
x: item.clientX - this.canvasRect.left,
y: item.clientY - this.canvasRect.top,
}
})
}
return e
},
touchStart(e) {
if (!this.canvasEl) return
this.isStart = true
// PC使
if(isPC) {
getRect(`#${this.canvasId}`, {context: this}).then(res => {
this.canvasRect = res
this.canvasEl.dispatchEvent('touchstart', wrapEvent(this.getTouch(e)))
})
return
}
this.canvasEl.dispatchEvent('touchstart', wrapEvent(e))
},
touchMove(e) {
if (!this.canvasEl || !this.isStart && this.canvasEl) return
this.canvasEl.dispatchEvent('touchmove', wrapEvent(this.getTouch(e)))
},
touchEnd(e) {
if (!this.canvasEl) return
this.isStart = false
this.canvasEl.dispatchEvent('touchend', wrapEvent(e))
},
// #endif
}
}
</script>
<!-- #ifdef APP-VUE -->
<script module="sign" lang="renderjs">
import sign from './render'
export default sign
</script>
<!-- #endif -->
<style lang="scss">
.lime-signature,
.lime-signature__canvas {
/* #ifndef APP-NVUE */
position: relative;
width: 100%;
height: 100%;
/* #endif */
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
}
.mask {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
}
.offscreen {
position: fixed;
top: 0;
left: 9999px;
}
</style>

View File

@ -0,0 +1,59 @@
export default {
styles: String,
disableScroll: {
type: Boolean,
default: true
},
type: {
type: String,
default: '2d'
},
// 画笔颜色
penColor: {
type: String,
default: 'black'
},
penSize: {
type: Number,
default: 2
},
// 画板背景颜色
background: String,
// 笔锋
openSmooth: Boolean,
// 画笔最小值
minLineWidth: {
type: Number,
default: 2
},
// 画笔最大值
maxLineWidth: {
type: Number,
default: 6
},
// 画笔达到最小宽度所需最小速度(px/ms)取值范围1.0-10.0,值越小,画笔越容易变细,笔锋效果会比较明显,可以自行调整查看效果,选出自己满意的值。
minSpeed: {
type: Number,
default: 1.5
},
// 相邻两线宽度增(减)量最大百分比取值范围1-100为了达到笔锋效果画笔宽度会随画笔速度而改变如果相邻两线宽度差太大过渡效果就会很突兀使用maxWidthDiffRate限制宽度差让过渡效果更自然。可以自行调整查看效果选出自己满意的值。
maxWidthDiffRate: {
type: Number,
default: 20
},
// 限制历史记录数即最大可撤销数传入0则关闭历史记录功能
maxHistoryLength: {
type: Number,
default: 20
},
beforeDelay: {
type: Number,
default: 10
},
landscape: {
type: Boolean
},
boundingBox: {
type: Boolean
}
}

View File

@ -0,0 +1,140 @@
// #ifdef APP-VUE
// import { Signature } from '@signature'
import { Signature } from './signature'
export default {
data() {
return {
canvasid: null,
signature: null,
observer: null,
options: {},
saveCount: 0,
}
},
mounted() {
this.$nextTick(this.init)
},
methods: {
init() {
const el = this.$refs.limeSignature||this.$ownerInstance.$el;
const canvas = document.createElement('canvas')
canvas.style = 'width: 100%; height: 100%;'
el.appendChild(canvas)
this.signature = new Signature({
el: canvas
})
this.signature.pen.setOption(this.options)
const width = this.signature.canvas.get('width')
const height = this.signature.canvas.get('height')
this.emit({
changeSize: {
width,
height
}
})
},
undo(v) {
if (v && this.signature) {
this.signature.undo()
}
},
clear(v) {
if (v && this.signature) {
this.signature.clear()
}
},
save(param) {
let {fileType = 'png', quality = 1, n} = JSON.parse(param)
const type = `image/${fileType}`.replace(/jpg/, 'jpeg');
if (n !== this.saveCount) {
this.saveCount = n;
const {background, landscape, boundingBox} = this.options
const flag = landscape || background || boundingBox
console.log('type', type)
console.log('flag', flag)
const image = this.signature.canvas.get('el').toDataURL(!flag && type, !flag && quality)
console.log('image', image.length)
if (flag) {
const canvas = document.createElement('canvas')
const pixelRatio = this.signature.canvas.get('pixelRatio')
let width = this.signature.canvas.get('width')
let height = this.signature.canvas.get('height')
let x = 0
let y = 0
const next = () => {
const size = [width, height]
console.log('size width', width)
console.log('size height', height)
console.log('size pixelRatio', pixelRatio)
if(landscape) {size.reverse()}
canvas.width = size[0] * pixelRatio
canvas.height = size[1] * pixelRatio
const param = [x, y, width, height, 0 , 0, width, height].map(item => item * pixelRatio)
const context = canvas.getContext('2d')
// context.scale(pixelRatio, pixelRatio)
if (landscape) {
context.translate(0, width * pixelRatio)
context.rotate(-Math.PI / 2)
}
console.log('background', background)
if (background) {
context.fillStyle = background
context.fillRect(0, 0, width * pixelRatio, height * pixelRatio)
}
// param
context.drawImage(this.signature.canvas.get('el'), ...param)
this.emit({
save: canvas.toDataURL(type, quality)
})
canvas.remove()
}
if(boundingBox) {
const res = this.signature.getContentBoundingBox()
width = res.width
height = res.height
x = res.startX
y = res.startY
next()
} else {
next()
}
} else {
this.emit({
save: image
})
}
}
},
isEmpty(v) {
if (v && this.signature) {
const isEmpty = this.signature.isEmpty()
this.emit({
isEmpty
})
}
},
emit(event) {
this.$ownerInstance.callMethod('onMessage', {
detail: {
data: [{
event
}]
}
})
},
update(v) {
if (v) {
if (this.signature) {
this.options = v
this.signature.pen.setOption(v)
} else {
this.options = v
}
}
}
}
}
// #endif

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,161 @@
export function compareVersion(v1, v2) {
v1 = v1.split('.')
v2 = v2.split('.')
const len = Math.max(v1.length, v2.length)
while (v1.length < len) {
v1.push('0')
}
while (v2.length < len) {
v2.push('0')
}
for (let i = 0; i < len; i++) {
const num1 = parseInt(v1[i], 10)
const num2 = parseInt(v2[i], 10)
if (num1 > num2) {
return 1
} else if (num1 < num2) {
return -1
}
}
return 0
}
let {platform, SDKVersion} = uni.getSystemInfoSync()
function gte(version) {
// #ifdef MP-ALIPAY
SDKVersion = my.SDKVersion
// #endif
return compareVersion(SDKVersion, version) >= 0;
}
export const isPC = /windows|mac/.test(platform)
export function canIUseCanvas2d() {
// #ifdef MP-WEIXIN
return gte('2.9.0');
// #endif
// #ifdef MP-ALIPAY
return gte('2.7.0');
// #endif
// #ifdef MP-TOUTIAO
return gte('1.78.0');
// #endif
return false
}
export const wrapEvent = (e) => {
if (!e) return;
if (!e.preventDefault) {
e.preventDefault = function() {};
}
return e;
}
export const requestAnimationFrame = (cb) => {
setTimeout(cb, 30)
}
// #ifdef MP
export const prefix = () => {
// #ifdef MP-TOUTIAO
return tt
// #endif
// #ifdef MP-WEIXIN
return wx
// #endif
// #ifdef MP-BAIDU
return swan
// #endif
// #ifdef MP-ALIPAY
return my
// #endif
// #ifdef MP-QQ
return qq
// #endif
// #ifdef MP-360
return qh
// #endif
}
// #endif
/**
* base64转路径
* @param {Object} base64
*/
export function base64ToPath(base64) {
const [, format, bodyData] = /data:image\/(\w+);base64,(.*)/.exec(base64) || [];
return new Promise((resolve, reject) => {
// #ifdef MP
const p = prefix()
const fs = p.getFileSystemManager()
//自定义文件名
if (!format) {
reject(new Error('ERROR_BASE64SRC_PARSE'))
}
const time = new Date().getTime();
const filePath = `${p.env.USER_DATA_PATH}/${time}.${format}`;
fs.writeFile({
filePath,
data: base64.split(',')[1],
encoding: 'base64',
success() {
resolve(filePath)
},
fail(err) {
reject(err)
}
})
// #endif
// #ifdef APP-PLUS
const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
bitmap.loadBase64Data(base64, () => {
if (!format) {
reject(new Error('ERROR_BASE64SRC_PARSE'))
}
const time = new Date().getTime();
const filePath = `_doc/uniapp_temp/${time}.${format}`
bitmap.save(filePath, {},
() => {
bitmap.clear()
resolve(filePath)
},
(error) => {
bitmap.clear()
reject(error)
})
}, (error) => {
bitmap.clear()
reject(error)
})
// #endif
})
}
export function sleep(delay) {
return new Promise(resolve => setTimeout(resolve, delay))
}
export function getRect(selector, options = {}) {
const typeDefault = 'boundingClientRect'
const { context, type = typeDefault} = options
return new Promise((resolve, reject) => {
const dom = uni.createSelectorQuery().in(context).select(selector);
const result = (rect) => {
if(rect) {
resolve(rect)
} else {
reject()
}
}
if(type == typeDefault) {
dom[type](result).exec()
} else {
dom[type]({
node: true,
size: true,
rect: true
}, result).exec()
}
});
};

View File

@ -0,0 +1,151 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title></title>
<style type="text/css">
html,
body,
canvas {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
overflow-y: hidden;
background-color: transparent;
}
</style>
</head>
<body>
<canvas id="lime-signature"></canvas>
<script type="text/javascript" src="./uni.webview.1.5.3.js"></script>
<script type="text/javascript" src="./signature.js"></script>
<script>
var signature = null;
var timer = null;
var isStart = false;
var options = null
console.log = function(...args) {
postMessage(args);
};
// function stringify(key, value) {
// if (typeof value === 'object' && value !== null) {
// if (cache.indexOf(value) !== -1) {
// return;
// }
// cache.push(value);
// }
// return value;
// };
function emit(event, data) {
postMessage({
event,
data: typeof data !== "object" && data !== null ? data : JSON.stringify(data),
});
// cache = [];
}
function postMessage(data) {
uni.postMessage({
data
});
}
function update(v = {}) {
if (signature) {
options = v
signature.pen.setOption(v);
} else {
signature = new Signature.Signature({el: "lime-signature"});
canvasEl = signature.canvas.get("el");
options = v
signature.pen.setOption(v)
const width = signature.canvas.get("width");
const height = signature.canvas.get("height");
emit({changeSize: {width,height}})
}
}
function clear() {
signature.clear()
}
function undo() {
signature.undo()
}
function isEmpty() {
const isEmpty = signature.isEmpty()
emit({isEmpty});
}
function save(param) {
// delete args.success;
// delete args.fail;
clearTimeout(timer);
timer = setTimeout(() => {
const {fileType = 'png', quality = 1, n} = param
const type = `image/${fileType}`.replace(/jpg/, 'jpeg');
const {backgroundColor, landscape, boundingBox} = options
const flag = backgroundColor || landscape || boundingBox
let path = canvasEl.toDataURL(!flag && type, !flag && quality)
if(flag) {
const canvas = document.createElement('canvas')
const pixelRatio = this.signature.canvas.get('pixelRatio')
let width = this.signature.canvas.get('width')
let height = this.signature.canvas.get('height')
let x = 0
let y = 0
const next = () => {
const size = [width, height]
if(landscape) {size.reverse()}
canvas.width = size[0] * pixelRatio
canvas.height = size[1] * pixelRatio
const param = [x, y, width, height, 0 , 0, width, height].map(item => item * pixelRatio)
const context = canvas.getContext('2d')
// context.scale(pixelRatio, pixelRatio)
if (landscape) {
context.translate(0, width * pixelRatio)
context.rotate(-Math.PI / 2)
}
if (backgroundColor) {
context.fillStyle = backgroundColor
context.fillRect(0, 0, width * pixelRatio, height * pixelRatio)
}
// param
context.drawImage(this.signature.canvas.get('el'), ...param)
path = canvas.toDataURL(type, quality)
canvas.remove()
}
if(boundingBox) {
const res = this.signature.getContentBoundingBox()
width = res.width
height = res.height
x = res.startX
y = res.startY
next()
} else {
next()
}
}
if (typeof path == "string") {
const index = Math.ceil(path.length / 8);
for (var i = 0; i < 8; i++) {
if (i == 7) {
emit({"success": path.substr(i * index, index)});
} else {
emit({"file": path.substr(i * index, index)});
}
}
} else {
console.error("canvas no data");
emit({"fail": "canvas no data"});
}
}, 30);
}
</script>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,77 @@
{
"id": "jp-signature",
"displayName": "手写签名组件弹框签名可配置签名签名返回base64签名专用手写一键使用 ",
"version": "2.2.2",
"description": "用于手写签名,同时内置了弹框签名组件,对于不想布局的同学来说可以开箱即用, 能跑在uniapp各端中的签名插件支持横屏、背景色、笔画颜色、笔画大小等功能,可生成有内容的区域,减小图片尺寸,节省空间。",
"keywords": [
"手写签名",
"弹框签名",
"手写一键使用",
"可配置签名",
"小白专用签名"
],
"repository": "",
"engines": {
"HBuilderX": "^3.5.4"
},
"dcloudext": {
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "无",
"permissions": "无"
},
"npmurl": "",
"type": "component-vue"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "y",
"aliyun": "y"
},
"client": {
"App": {
"app-vue": "y",
"app-nvue": "y"
},
"H5-mobile": {
"Safari": "y",
"Android Browser": "y",
"微信浏览器(Android)": "y",
"QQ浏览器(Android)": "y"
},
"H5-pc": {
"Chrome": "y",
"IE": "u",
"Edge": "u",
"Firefox": "y",
"Safari": "y"
},
"小程序": {
"微信": "y",
"阿里": "u",
"百度": "u",
"字节跳动": "u",
"QQ": "n"
},
"快应用": {
"华为": "u",
"联盟": "u"
}
}
}
}
}

View File

@ -0,0 +1,34 @@
<template>
<view class="h100">
<jp-signature-popup v-model="image" />
<view>{{image}}</view>
<view class="but" @click="toPop"></view>
<jp-signature-popup ref="signature" popup v-model="image2" />
{{image2}}
</view>
</template>
<script>
export default {
data() {
return {
image:'',
image2:''
}
},
methods: {
toPop(){
this.$refs.signature.toPop()
}
}
}
</script>
<style lang="scss">
.but{
margin: 25px;
line-height: 40px;
text-align: center;
background-color: #55aaff;
color: #fff;
}
</style>

View File

@ -0,0 +1,129 @@
# jp-signature及jp-signature-popup 写字板
## jp-signature 写字板,可用业务签名等场景,方便用户自行改造
## jp-signature-popup 小白专用弹框签名组件,方便小白开发使用,和输入框一样使用简单
# 有项目需要开发的请联系 QQ:371524845
## 开发不易,如果帮助到你的,请支持 有问题请留言,作者会积极更新
## 平台兼容
| H5 | 微信小程序 | 支付宝小程序 | 百度小程序 | 头条小程序 | QQ 小程序 | App |
| --- | ---------- | ------------ | ---------- | ---------- | --------- | --- |
| √ | √ | √ | 未测 | 未测 | 未测 | √ |
## 代码演示
### jp-signature 基本用法
```html
<view style="width: 750rpx ;height: 500rpx;">
<jp-signature ref="signatureRef" ></jp-signature>
</view>
<view>
<button @click="clear">清空</button>
<button @click="">撤消</button>
<button @click="save">保存</button>
</view>
export default {
data() {
return {
url: '',
}
},
methods: {
save(){
this.$refs.signatureRef.canvasToTempFilePath({
success: (res) => {
// 是否为空画板 无签名
console.log(res.isEmpty)
// 生成图片的临时路径
// H5 生成的是base64
this.url = res.tempFilePath
}
})
},
clear(){
this.$refs.signatureRef.clear()
},
undo(){
this.$refs.signatureRef.undo()
},
}
}
```
## API
### Props
| 参数 | 说明 | 类型 | 默认值 |
| -------------- | ------------ | ---------------- | ------------ |
| penSize | 画笔大小 | <em>number</em> | `2` |
| minLineWidth | 线条最小宽 | <em>number</em> | `2` |
| maxLineWidth | 线条最大宽 | <em>number</em> | `6` |
| penColor | 画笔颜色 | <em>string</em> | `black` |
| backgroundColor | 背景颜色 | <em>string</em> | `` |
| type | 指定 canvas 类型 | <em>string</em> | `2d` |
| openSmooth | 是否模拟压感 | <em>boolean</em> | `false` |
| beforeDelay | 延时初始化,在放在弹窗里可以使用 (毫秒) | <em>number</em> | `0` |
| maxHistoryLength | 限制历史记录数即最大可撤销数传入0则关闭历史记录功能 | <em>boolean</em> | `20` |
| landscape | 横屏 | <em>boolean</em> | `` |
| disableScroll | 当在写字时,禁止屏幕滚动以及下拉刷新 | <em>boolean</em> | `true` |
| boundingBox | 只生成内容区域即未画部分不生成有性能的损耗微信小程序pc不支持 | <em>boolean</em> | `false` |
### 事件 Events
| 事件名 | 说明 | 回调 |
| ------- | ------------ | -------------- |
| undo | 撤消,回退到上一步 | |
| clear | 清空,清空画板 | |
| canvasToTempFilePath | 保存生成图片与官方保持一致但不需要传canvasId | |
### 常见问题
- 放在弹窗里时,尺寸不对 可以延时手写板出现时机给手写板加vif或beforeDelay="300"
- boundingBox 微信小程序 pc 不支持, 因为获取不到 ImageData 数据
## jp-signature-popup 基础用法
```html
<template>
<view class="content">
<jp-signature-popup v-model="title"></jp-signature-popup>
{{title}}
</view>
</template>
<script>
export default {
data() {
return {
title: ''
}
},
}
</script>
```
####参数
| 参数名 | 类型 | 默认值 | 说明 |
| -------- | -------- | --------| --------|
| value | String | | 签名内容可以通过v-model绑定 |
| label | String | 手写签名 | |
| popup | Boolean | false | 是否隐藏原有样式,该模式只使用弹框 |
| required | Boolean | false | |
| placeholder | String | 点击签名 | 签名说明 |
| readonly | Boolean | false | 是否只能可读 |
####方法
| 方法名 | 返回参数 | 说明 |
| -------- | -------- | --------|
| toPop | | 打开弹窗 |
| close | | 关闭弹窗 |
| deleteImg | | 删除内容 |
####事假
| 事件名 | 返回参数 | 说明 |
| -------- | -------- | --------|
| input | 签名内容 | 签名内容 |