signContract.vue 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  1. <template>
  2. <view class="content">
  3. <!-- <view class="content1">
  4. <view style='width:70px'>付款方式</view>
  5. <u-radio-group v-model="dataDetails.advanceFreightService" placement="row">
  6. <u-radio :customStyle="radioCustomStyle" v-for="(item, index) in radiolist1" :key="index"
  7. :label="item.name" :name="item.name" @change="radioChange">
  8. </u-radio>
  9. </u-radio-group>
  10. </view> -->
  11. <view class="content2">
  12. <view class="title">
  13. 合同摘要
  14. </view>
  15. <view class='row-between'>
  16. <view class="gray">发货单位</view>
  17. <view class="">{{dataDetails.compName?dataDetails.compName:'个人货主'}}</view>
  18. </view>
  19. <view class='row-between'>
  20. <view class="gray">发货地</view>
  21. <view class="place">
  22. {{dataDetails.sendPrivate}}{{dataDetails.sendCity}}{{dataDetails.sendArea}}{{dataDetails.sendDetailedAddress}}
  23. </view>
  24. </view>
  25. <view class='row-between'>
  26. <view class="gray">卸货地</view>
  27. <view class=" place">
  28. {{dataDetails.unloadPrivate}}{{dataDetails.unloadCity}}{{dataDetails.unloadArea}}{{dataDetails.unloadDetailedAddress}}
  29. </view>
  30. </view>
  31. <view class='row-between'>
  32. <view class="gray">货名</view>
  33. <view class="">{{dataDetails.goodsName}}</view>
  34. </view>
  35. <view class='row-between'>
  36. <view class="gray">距离</view>
  37. <view class="">约{{dataDetails.distance}}公里</view>
  38. </view>
  39. <view class="title">
  40. 完善信息
  41. </view>
  42. <view class='row-between'>
  43. <view class="gray">运费</view>
  44. <!-- <view class="">{{dataDetails.freight}}{{dataDetails.illingMethod==0?'元/吨':'元/车'}}</view> -->
  45. <!-- <view class="flex"><input type="text" placeholder="请输入运费" v-model="dataDetails.freight"
  46. class="text-align-right yf-input">{{dataDetails.freight}}元/车</view> -->
  47. <view class="flex">
  48. <u--input placeholder="请输入运费" border="none" type="number" v-model="dataDetails.freightCars"
  49. inputAlign='right' clearable></u--input>
  50. <!-- <span>元/车</span> -->
  51. </view>
  52. </view>
  53. <view class='row-between'>
  54. <view class="gray">车牌号</view>
  55. <view class="flex">
  56. <input class="" v-model='dataDetails.carrierInfo.carNo' @click.stop="handleShowKeyboard"
  57. :disabled="true" placeholder="输入车牌号" name="input" style="text-align: right;"></input>
  58. </view>
  59. </view>
  60. <view class='row-between'>
  61. <view class="gray">挂车号(选填)</view>
  62. <view class="flex">
  63. <u--input placeholder="请输入挂车号" border="none" v-model="dataDetails.trailerNumber" inputAlign='right'
  64. clearable></u--input>
  65. </view>
  66. </view>
  67. <view class='row-between'>
  68. <view class="gray">运输开始日期</view>
  69. <view class="">
  70. <view @click="dateShow">{{dataDetails.startDates?dataDetails.startDates:'请选择运输开始日期'}}
  71. </view>
  72. <u-datetime-picker :show="startShow" mode="date" @cancel="removeStart" @confirm="startDate"
  73. @close="removeStart"></u-datetime-picker>
  74. </view>
  75. </view>
  76. <view class='row-between'>
  77. <view class="gray">运输截止日期</view>
  78. <view class="">
  79. <!-- <u--input placeholder="请输入内容" border="none" v-model="dataDetails.value" inputAlign='right'
  80. clearable></u--input> -->
  81. <view class="" @click="endShow = true">{{dataDetails.endDates?dataDetails.endDates:'请选择运输截止日期'}}
  82. </view>
  83. <u-datetime-picker :show="endShow" mode="date" @cancel="removeEnd" @confirm="endDate"
  84. @close="removeEnd"></u-datetime-picker>
  85. </view>
  86. </view>
  87. <view class='row-between'>
  88. <view class="gray">联络人姓名</view>
  89. <view class="">
  90. <u--input placeholder="请输入联络人姓名" border="none" v-model="dataDetails.contactPersonName"
  91. inputAlign='right' clearable></u--input>
  92. </view>
  93. </view>
  94. <view class='row-between'>
  95. <view class="gray">联络人电话</view>
  96. <view class="">
  97. <u--input placeholder="请输入联络人电话" border="none" type="number" maxlength="11"
  98. v-model="dataDetails.contactPersonPhone" inputAlign='right' clearable></u--input>
  99. </view>
  100. </view>
  101. <view class='row-between'>
  102. <view class="gray">装车后预付款</view>
  103. <view class="">
  104. <u--input placeholder="请输入装车后预付款" border="none" v-model="dataDetails.advanceCharge"
  105. inputAlign='right' clearable></u--input>
  106. </view>
  107. </view>
  108. </view>
  109. <view class="wrapper content3">
  110. <view class="qm-row">
  111. <view class="handTitle">手写签名</view>
  112. <image src="@/static/xiangpica@2x.png" mode="widthFix" @click="retDraw" class="retDraw-image"></image>
  113. <!-- <button @click="retDraw" class="delBtn">重写</button> -->
  114. </view>
  115. <view class="handCenter">
  116. <canvas class="handWriting" :disable-scroll="true" @touchstart="uploadScaleStart"
  117. @touchmove="uploadScaleMove" canvas-id="handWriting"></canvas>
  118. </view>
  119. <view class="handRight">
  120. </view>
  121. <view class="handBtn">
  122. <!-- <image @click="selectColorEvent('black','#1A1A1A')"
  123. :src="selectColor === 'black' ? '/static/other/color_black_selected.png' : '/static/other/color_black.png'"
  124. :class="[selectColor === 'black' ? 'color_select' : '', 'black-select']"></image>
  125. <image @click="selectColorEvent('red','#ca262a')"
  126. :src="selectColor === 'red' ? '/static/other/color_red_selected.png' : '/static/other/color_red.png'"
  127. :class="[selectColor === 'red' ? 'color_select' : '', 'black-select']"></image> -->
  128. <!-- <button @click="saveCanvasAsImg" class="saveBtn">保存</button> -->
  129. <view @click="submit" class="saveBtn">提交</view>
  130. <!-- <button @click="previewCanvasImg" class="previewBtn">预览</button> -->
  131. <!-- <button @click="subCanvas" class="subBtn">完成</button> -->
  132. </view>
  133. </view>
  134. <master-keyboard ref="keyboard" keyboardtype="car" :show="keyShow" :randomNumber="true" :newCar="false"
  135. :defaultValue="carNumber" @keyboardClick="handleClick"></master-keyboard>
  136. <u-toast ref="uToast"></u-toast>
  137. <u-toast ref="uToast"></u-toast>
  138. </view>
  139. </template>
  140. <script>
  141. var that;
  142. import uploadImage from '@/components/ossutil/uploadFile.js';
  143. export default {
  144. data() {
  145. return {
  146. keyShow: false,
  147. carNumber: '',
  148. isScaleStart: false,
  149. radioCustomStyle: {
  150. margin: '0 0 0 10rpx'
  151. },
  152. canvasName: 'handWriting',
  153. ctx: "",
  154. startX: null,
  155. startY: null,
  156. canvasWidth: 0,
  157. canvasHeight: 0,
  158. selectColor: 'black',
  159. lineColor: '#1A1A1A', // 颜色
  160. lineSize: 5, // 笔记倍数
  161. value: true,
  162. dataDetails: {},
  163. radiolist1: [{
  164. name: '平台垫付运费',
  165. disabled: false
  166. },
  167. {
  168. name: '无需平台垫付运费',
  169. disabled: false
  170. },
  171. ],
  172. startShow: false,
  173. endShow: false,
  174. };
  175. },
  176. onLoad(options) {debugger
  177. that = this
  178. console.log(JSON.parse(options.obj))
  179. // this.dataDetails = JSON.parse(options.obj)
  180. this.dataDetails = JSON.parse(decodeURIComponent(options.obj))
  181. this.dataDetails.advanceFreightService = '平台垫付运费'
  182. this.ctx = uni.createCanvasContext("handWriting");
  183. this.$nextTick(() => {
  184. uni.createSelectorQuery().select('.handCenter').boundingClientRect(rect => {
  185. this.canvasWidth = rect.width;
  186. this.canvasHeight = rect.height;
  187. /* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
  188. this.setCanvasBg('#fff');
  189. })
  190. .exec();
  191. });
  192. },
  193. methods: {
  194. //车牌号弹出键盘
  195. handleShowKeyboard() {
  196. debugger
  197. if (this.dataDetails.carrierInfo.carNo == '') {
  198. this.carNumber = ''
  199. } else {
  200. this.carNumber = this.dataDetails.carrierInfo.carNo
  201. }
  202. if (this.$refs.keyboard.open) {
  203. this.$refs.keyboard.open(false) //true 键盘显示 false 键盘隐藏
  204. } else {
  205. this.$refs.keyboard[0].open(false)
  206. }
  207. if (this.$refs.keyboard.open) {
  208. this.$refs.keyboard.open(true) //true 键盘显示 false 键盘隐藏
  209. } else {
  210. this.$refs.keyboard[0].open(true)
  211. }
  212. },
  213. //车牌号弹出键盘
  214. handleClick(e) {
  215. this.carNumber = e.value
  216. this.dataDetails.carrierInfo.carNo = e.value //键盘输入值
  217. },
  218. dateShow() {
  219. this.startShow = true
  220. },
  221. removeStart() {
  222. this.startShow = false
  223. },
  224. removeEnd() {
  225. this.endShow = false
  226. },
  227. startDate(e) {
  228. let timeFormat = uni.$u.timeFormat
  229. this.dataDetails.startDates = timeFormat(e.value, "yyyy-mm-dd")
  230. this.startShow = false
  231. },
  232. endDate(e) {
  233. let timeFormat = uni.$u.timeFormat
  234. this.dataDetails.endDates = timeFormat(e.value, "yyyy-mm-dd")
  235. this.endShow = false
  236. },
  237. submit() {
  238. if (!that.isScaleStart) {
  239. that.$refs.uToast.show({
  240. type: 'error',
  241. message: "手写签名不能为空!",
  242. })
  243. return
  244. }
  245. if (uni.$u.test.isEmpty(that.dataDetails.freightCars)) {
  246. that.$refs.uToast.show({
  247. type: 'error',
  248. message: "运费不能为空!",
  249. })
  250. return
  251. }
  252. if (uni.$u.test.isEmpty(that.dataDetails.startDates)) {
  253. that.$refs.uToast.show({
  254. type: 'error',
  255. message: "运输起始日期不能为空!",
  256. })
  257. return
  258. }
  259. if (uni.$u.test.isEmpty(that.dataDetails.endDates)) {
  260. that.$refs.uToast.show({
  261. type: 'error',
  262. message: "运输截止日期不能为空!",
  263. })
  264. return
  265. }
  266. if (uni.$u.test.isEmpty(that.dataDetails.contactPersonName)) {
  267. that.$refs.uToast.show({
  268. type: 'error',
  269. message: "联络人姓名不能为空!",
  270. })
  271. return
  272. }
  273. if (uni.$u.test.isEmpty(that.dataDetails.contactPersonPhone)) {
  274. that.$refs.uToast.show({
  275. type: 'error',
  276. message: "联络人电话不能为空!",
  277. })
  278. return
  279. }
  280. if (uni.$u.test.isEmpty(that.dataDetails.advanceCharge)) {
  281. that.$refs.uToast.show({
  282. type: 'error',
  283. message: "装车后预付款不能为空!",
  284. })
  285. return
  286. }
  287. console.log(that.dataDetails)
  288. let _obj = {}
  289. debugger
  290. _obj.trailerNumber = that.dataDetails.trailerNumber
  291. _obj.startDates = that.dataDetails.startDates
  292. _obj.endDates = that.dataDetails.endDates
  293. _obj.contactPersonName = that.dataDetails.contactPersonName
  294. _obj.contactPersonPhone = that.dataDetails.contactPersonPhone
  295. _obj.freightCars = that.dataDetails.freightCars
  296. _obj.advanceCharge = that.dataDetails.advanceCharge
  297. _obj.id = that.dataDetails.id
  298. _obj.carNumber =that.dataDetails.carrierInfo.carNo
  299. uni.canvasToTempFilePath({
  300. canvasId: 'handWriting',
  301. fileType: 'png',
  302. quality: 1, //图片质量
  303. success(res) {
  304. console.log(res.tempFilePath, 'canvas生成图片地址');
  305. uploadImage('image', res.tempFilePath, 'appData/',
  306. result => {
  307. // 上传成功
  308. that.dataDetails.cargoOwnerAutograph = result
  309. _obj.driverAutograph = result
  310. uni.showLoading({
  311. title: '加载中',
  312. mask: true
  313. })
  314. that.$request.baseRequest('get', '/orderInfo/setPdf', _obj).then(
  315. res => {
  316. if (res.code == 200) {
  317. uni.hideLoading()
  318. that.contractSrc = res.data
  319. uni.downloadFile({
  320. url: res.data,
  321. success: function(res) {
  322. var filePath = res.tempFilePath;
  323. uni.openDocument({
  324. filePath: filePath,
  325. showMenu: true,
  326. success: function(res) {
  327. console.log('打开文档成功');
  328. }
  329. });
  330. }
  331. });
  332. that.$refs.uToast.show({
  333. type: 'success',
  334. message: "提交成功",
  335. complete() {
  336. that.upCallback({
  337. size: 10,
  338. num: 1
  339. })
  340. }
  341. })
  342. }
  343. })
  344. .catch(res => {
  345. uni.$u.toast(res.message);
  346. });
  347. }
  348. )
  349. }
  350. });
  351. },
  352. // change(e){
  353. // if(this.value){
  354. // this.$set(this.dataDetails,'advanceFreightService',1)
  355. // }else{
  356. // this.$set(this.dataDetails,'advanceFreightService',0)
  357. // }
  358. // },
  359. // 笔迹开始
  360. uploadScaleStart(e) {
  361. this.isScaleStart = true
  362. this.startX = e.changedTouches[0].x
  363. this.startY = e.changedTouches[0].y
  364. //设置画笔参数
  365. //画笔颜色
  366. this.ctx.setStrokeStyle(this.lineColor)
  367. //设置线条粗细
  368. this.ctx.setLineWidth(this.lineSize)
  369. //设置线条的结束端点样式
  370. this.ctx.setLineCap("round") //'butt'、'round'、'square'
  371. //开始画笔
  372. this.ctx.beginPath()
  373. },
  374. // 笔迹移动
  375. uploadScaleMove(e) {
  376. //取点
  377. let temX = e.changedTouches[0].x
  378. let temY = e.changedTouches[0].y
  379. //画线条
  380. this.ctx.moveTo(this.startX, this.startY)
  381. this.ctx.lineTo(temX, temY)
  382. this.ctx.stroke()
  383. this.startX = temX
  384. this.startY = temY
  385. this.ctx.draw(true)
  386. },
  387. /**
  388. * 重写
  389. */
  390. retDraw() {
  391. this.ctx.clearRect(0, 0, 700, 730);
  392. this.ctx.draw();
  393. //设置canvas背景
  394. this.setCanvasBg('#fff');
  395. },
  396. /**
  397. * @param {Object} str
  398. * @param {Object} color
  399. * 选择颜色
  400. */
  401. selectColorEvent(str, color) {
  402. this.selectColor = str;
  403. this.lineColor = color;
  404. },
  405. //完成
  406. subCanvas() {
  407. uni.canvasToTempFilePath({
  408. canvasId: 'handWriting',
  409. fileType: 'png',
  410. quality: 1, //图片质量
  411. success(res) {
  412. // console.log(res.tempFilePath, 'canvas生成图片地址');
  413. uni.showToast({
  414. title: '以保存'
  415. });
  416. //保存到系统相册
  417. uni.saveImageToPhotosAlbum({
  418. filePath: res.tempFilePath,
  419. success(res) {
  420. uni.showToast({
  421. title: '已成功保存到相册',
  422. duration: 2000
  423. });
  424. }
  425. });
  426. }
  427. });
  428. },
  429. //保存到相册
  430. saveCanvasAsImg() {
  431. uni.canvasToTempFilePath({
  432. canvasId: 'handWriting',
  433. fileType: 'png',
  434. quality: 1, //图片质量
  435. success(res) {
  436. console.log(res.tempFilePath, 'canvas生成图片地址');
  437. uni.saveImageToPhotosAlbum({
  438. filePath: res.tempFilePath,
  439. success(res) {
  440. uni.showToast({
  441. title: '已保存到相册',
  442. duration: 2000
  443. });
  444. }
  445. });
  446. }
  447. });
  448. },
  449. //预览
  450. previewCanvasImg() {
  451. uni.canvasToTempFilePath({
  452. canvasId: 'handWriting',
  453. fileType: 'jpg',
  454. quality: 1, //图片质量
  455. success(res) {
  456. uni.previewImage({
  457. urls: [res.tempFilePath] //预览图片 数组
  458. });
  459. }
  460. });
  461. },
  462. //设置canvas背景色 不设置 导出的canvas的背景为透明
  463. //@params:字符串 color
  464. setCanvasBg(color) {
  465. /* 将canvas背景设置为 白底,不设置 导出的canvas的背景为透明 */
  466. //rect() 参数说明 矩形路径左上角的横坐标,左上角的纵坐标, 矩形路径的宽度, 矩形路径的高度
  467. //这里是 canvasHeight - 4 是因为下边盖住边框了,所以手动减了写
  468. this.ctx.rect(0, 0, this.canvasWidth, this.canvasHeight - 4);
  469. // ctx.setFillStyle('red')
  470. this.ctx.setFillStyle(color);
  471. this.ctx.fill(); //设置填充
  472. this.ctx.draw(); //开画
  473. }
  474. }
  475. };
  476. </script>
  477. <style lang="scss" scoped>
  478. page {
  479. background: #fbfbfb;
  480. height: auto;
  481. }
  482. .content1 {
  483. background: white;
  484. border-radius: 20rpx;
  485. margin: 20rpx;
  486. padding: 30rpx 20rpx;
  487. display: flex;
  488. justify-content: space-between;
  489. .right {
  490. display: flex;
  491. }
  492. }
  493. .content2 {
  494. background: white;
  495. border-radius: 20rpx;
  496. margin: 20rpx;
  497. padding: 30rpx 20rpx;
  498. .title {
  499. font-size: 36rpx;
  500. font-weight: 700;
  501. margin-bottom: 20rpx;
  502. }
  503. .row-between {
  504. margin-bottom: 20rpx;
  505. }
  506. .left-text {
  507. margin-right: 20rpx;
  508. }
  509. .yf-input {
  510. padding-right: 10rpx;
  511. }
  512. }
  513. .content3 {
  514. background: white;
  515. border-radius: 20rpx;
  516. margin: 20rpx;
  517. padding: 30rpx 20rpx;
  518. }
  519. .place {
  520. width: 80%;
  521. text-align: right;
  522. }
  523. .handCenter {
  524. border: 4rpx dashed #e9e9e9;
  525. overflow: hidden;
  526. box-sizing: border-box;
  527. height: 500rpx;
  528. }
  529. .handWriting {
  530. background: #F9F9FB;
  531. width: 100%;
  532. height: 100%;
  533. }
  534. .handRight {
  535. display: inline-flex;
  536. align-items: center;
  537. }
  538. .handCenter {
  539. border: 4rpx dashed #e9e9e9;
  540. flex: 5;
  541. overflow: hidden;
  542. box-sizing: border-box;
  543. }
  544. .handTitle {
  545. font-size: 36rpx;
  546. color: #666;
  547. font-weight: 700;
  548. color: #333333;
  549. margin-bottom: 20rpx;
  550. }
  551. .retDraw-image {
  552. width: 50rpx;
  553. }
  554. .qm-row {
  555. display: flex;
  556. justify-content: space-between;
  557. }
  558. .saveBtn {
  559. width: 80%;
  560. background: #2772FB;
  561. color: white;
  562. text-align: center;
  563. border-radius: 50rpx;
  564. padding: 20rpx;
  565. }
  566. .handBtn {
  567. display: flex;
  568. justify-content: center;
  569. }
  570. /*
  571. .wrapper {
  572. width: 100%;
  573. height: 95vh;
  574. margin: 30rpx 0;
  575. overflow: hidden;
  576. display: flex;
  577. align-content: center;
  578. flex-direction: row;
  579. justify-content: center;
  580. font-size: 28rpx;
  581. }
  582. .handBtn button {
  583. font-size: 28rpx;
  584. }
  585. .handBtn {
  586. height: 95vh;
  587. display: inline-flex;
  588. flex-direction: column;
  589. justify-content: space-between;
  590. align-content: space-between;
  591. flex: 1;
  592. }
  593. .delBtn {
  594. position: absolute;
  595. top: 250rpx;
  596. left: 0rpx;
  597. transform: rotate(90deg);
  598. color: #666;
  599. }
  600. .delBtn image {
  601. position: absolute;
  602. top: 13rpx;
  603. left: 25rpx;
  604. }
  605. .subBtn {
  606. position: absolute;
  607. bottom: 52rpx;
  608. left: -3rpx;
  609. display: inline-flex;
  610. transform: rotate(90deg);
  611. background: #008ef6;
  612. color: #fff;
  613. margin-bottom: 30rpx;
  614. text-align: center;
  615. justify-content: center;
  616. }
  617. .saveBtn {
  618. position: absolute;
  619. top: 375rpx;
  620. left: 0rpx;
  621. transform: rotate(90deg);
  622. color: #666;
  623. }
  624. .previewBtn {
  625. position: absolute;
  626. top: 500rpx;
  627. left: 0rpx;
  628. transform: rotate(90deg);
  629. color: #666;
  630. }
  631. .uploadBtn {
  632. position: absolute;
  633. top: 625rpx;
  634. left: 0rpx;
  635. transform: rotate(90deg);
  636. color: #666;
  637. }
  638. .black-select {
  639. width: 60rpx;
  640. height: 60rpx;
  641. position: absolute;
  642. top: 30rpx;
  643. left: 25rpx;
  644. }
  645. .black-select.color_select {
  646. width: 90rpx;
  647. height: 90rpx;
  648. top: 100rpx;
  649. left: 10rpx;
  650. }
  651. .red-select {
  652. width: 60rpx;
  653. height: 60rpx;
  654. position: absolute;
  655. top: 140rpx;
  656. left: 25rpx;
  657. }
  658. .red-select.color_select {
  659. width: 90rpx;
  660. height: 90rpx;
  661. top: 120rpx;
  662. left: 10rpx;
  663. } */
  664. </style>