You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

338 lines
9.2 KiB

  1. <template>
  2. <view>
  3. <l-label title="流程名称:">{{ taskParam.taskName }}</l-label>
  4. <l-label title="当前操作:">{{ typeText }}{{ type === 'sign' ? '' : ` [${taskParam.name}]` }}</l-label>
  5. <l-organize-picker
  6. v-if="type === 'sign'"
  7. v-model="staff"
  8. title="加签人员"
  9. placeholder="请选择加签人员"
  10. type="user"
  11. required
  12. arrow
  13. />
  14. <!-- 手写签名 canvas 区 -->
  15. <template v-if="Number(taskParam.isSign) === 1">
  16. <view class="cu-form-group"><view class="title">手写签名:</view></view>
  17. <view class="sign-area bg-white">
  18. <canvas
  19. v-if="canvas"
  20. @touchmove="signMove"
  21. @touchstart="signStart($event)"
  22. @touchend="signEnd"
  23. @touchcancel="signEnd"
  24. disable-scroll="true"
  25. canvas-id="sign-canvas"
  26. id="sign-canvas"
  27. class="sign-canvas"
  28. ></canvas>
  29. </view>
  30. <view class="sign-action padding-bottom text-right">
  31. <l-button @click="clearSign" color="red" style="margin-right: 15px;">清空签名板</l-button>
  32. </view>
  33. </template>
  34. <l-textarea v-model="remark" :placeholder="`输入${typeText}意见`" title="审核意见:" />
  35. <!-- 弹层 -->
  36. <l-modal v-model="modal" @close="reviewer = ''" title="指派审核人">
  37. <l-checkbox-picker @input="(e)=>{reviewer = e}" :value="reviewer" :readonly="false" :range="reviewerList"
  38. required title="审核人" />
  39. <l-button @click="userAssign" color="blue" class="block" block>确定指派</l-button>
  40. <l-button @click="()=>{modal = false;reviewer = ''}" line="blue" class="block margin-top-sm" block>取消</l-button>
  41. </l-modal>
  42. <view class="padding margin-top bg-white">
  43. <l-button @click="submit" class="block" size="lg" color="green" block>提交流程{{ typeText }}</l-button>
  44. </view>
  45. </view>
  46. </template>
  47. <script>
  48. import get from 'lodash/get'
  49. let context = null
  50. let touchs = []
  51. export default {
  52. data() {
  53. return {
  54. type: 'sign',
  55. typeText: '',
  56. staff: '',
  57. remark: '',
  58. taskParam: {},
  59. canvas: true,
  60. modal: false,
  61. reviewer: [],
  62. reviewerList: [],
  63. reviewerListId:'',
  64. submitPostData:null,
  65. }
  66. },
  67. async onLoad() {
  68. await this.init()
  69. },
  70. methods: {
  71. // 页面初始化
  72. async init() {
  73. this.taskParam = this.GET_PARAM()
  74. this.type = this.taskParam.type
  75. this.typeText = this.taskParam.type === 'sign' ? '加签' : '审核'
  76. if (Number(this.taskParam.isSign) === 1) {
  77. this.canvasInit()
  78. }
  79. },
  80. // 初始化签名区 canvas
  81. canvasInit() {
  82. this.canvas = true
  83. context = uni.createCanvasContext('sign-canvas')
  84. context.setStrokeStyle('#000')
  85. context.setLineWidth(5)
  86. context.setLineCap('round')
  87. context.setLineJoin('round')
  88. touchs = []
  89. },
  90. // 指派审核人
  91. async userAssign() {
  92. if(!this.reviewer.length){
  93. this.modal = false
  94. this.TOAST('请选择审核人')
  95. return
  96. }
  97. // let formdata = new FormData()
  98. // formdata.append("data",this.taskParam.formreq)
  99. const res = await this.HTTP_POST('learun/adms/newwf/instance', this.taskParam.formreq, `指派审核人时发生错误`)
  100. if(!res){
  101. return
  102. }
  103. this.submitPostData.auditors = JSON.stringify({[this.reviewerListId]:this.reviewer.toString()})
  104. delete this.submitPostData.formreq
  105. // this.submitPostData.auditors[this.reviewerListId] = this.reviewer
  106. // console.log(this.submitPostData)
  107. uni.showLoading({
  108. title: '提交中...'
  109. });
  110. const success = await this.HTTP_POST(
  111. this.type === 'sign' ? 'learun/adms/newwf/sign' : 'learun/adms/newwf/auditors',
  112. this.submitPostData,
  113. `提交[${this.typeText}]时发生错误`
  114. )
  115. if (!success) {
  116. uni.hideLoading();
  117. return
  118. }
  119. this.EMIT('task-list-change')
  120. this.NAV_BACK(2)
  121. uni.hideLoading();
  122. this.TOAST(`已成功提交${this.typeText}`, 'success')
  123. },
  124. // 点击「提交」按钮
  125. async submit() {
  126. if (this.type === 'sign' && !this.staff) {
  127. this.CONFIRM('请补全必填项', '必须指定一个加签用户')
  128. return
  129. }
  130. const postData = {
  131. operationCode: this.taskParam.code,
  132. operationName: this.taskParam.name,
  133. processId: this.taskParam.processId,
  134. taskId: this.taskParam.taskId,
  135. des: this.remark,
  136. formreq: this.taskParam.formreq
  137. }
  138. if (this.type === 'sign') {
  139. postData.userId = this.staff
  140. } else {
  141. postData.auditors = this.taskParam.auditors
  142. }
  143. // 需要手写签名时,将 canvas 导出为 base64 格式
  144. // 各个平台写法均不相同,需要注意
  145. if (Number(this.taskParam.isSign) === 1) {
  146. // H5 平台,canvasToTempFilePath 的结果直接为画布的 base64
  147. // #ifdef H5
  148. const [err, { tempFilePath }] = await uni.canvasToTempFilePath({ canvasId: 'sign-canvas' })
  149. postData.signUrl = tempFilePath
  150. // #endif
  151. // App 平台,canvasToTempFilePath 输出文件,上传后台转为 base64 格式
  152. // #ifdef APP-VUE
  153. const [err, { tempFilePath }] = await uni.canvasToTempFilePath({ canvasId: 'sign-canvas' })
  154. const signBase64 = await this.HTTP_UPLOAD('/annexes/wxtobase64', tempFilePath)
  155. postData.signUrl = 'data:image/png;base64,' + signBase64
  156. // #endif
  157. // 微信小程序,canvasToTempFilePath 输出文件,使用文件管理器以 base64 格式读取文件即可
  158. // #ifdef MP-WEIXIN
  159. const [err, { tempFilePath }] = await uni.canvasToTempFilePath({ canvasId: 'sign-canvas' })
  160. postData.signUrl = 'data:image/png;base64,' + uni.getFileSystemManager().readFileSync(tempFilePath, 'base64')
  161. // #endif
  162. // #ifdef MP-ALIPAY
  163. // 钉钉小程序,context.toTempFilePath 输出文件,上传后台转为 base64 格式
  164. // #ifdef MP-DINGTALK
  165. const filePath = await new Promise((res, rej) => {
  166. context.toTempFilePath({
  167. success: ({ filePath }) => {
  168. res(filePath)
  169. },
  170. fail: () => {
  171. rej()
  172. }
  173. })
  174. })
  175. const signBase64 = await this.HTTP_UPLOAD('/annexes/wxtobase64', filePath)
  176. postData.signUrl = 'data:image/png;base64,' + signBase64
  177. // #endif
  178. // 支付宝小程序,context.toDataURL 直接输出 base64 字符串
  179. // #ifndef MP-DINGTALK
  180. postData.signUrl = await context.toDataURL('image/png', 1)
  181. // #endif
  182. // #endif
  183. }
  184. // 是否需要指派审核人
  185. let isNext = this.taskParam.currentNode.isNext
  186. if (this.taskParam.next == '2') {
  187. isNext = '1';
  188. }
  189. if (isNext == '1') {
  190. let params = {
  191. code: this.taskParam.schemeCode,
  192. processId: this.taskParam.processId,
  193. taskId: this.taskParam.taskId,
  194. nodeId: this.taskParam.currentNode.id,
  195. operationCode: this.taskParam.code,
  196. }
  197. const userList = await this.HTTP_GET('learun/adms/newwf/auditer', params, `获取审核人时发生错误`)
  198. if (!userList) {
  199. return
  200. }
  201. let arr = Object.entries(userList)
  202. this.reviewerListId = arr[0][0]
  203. this.reviewerList = arr[0][1].map(item => {
  204. return {
  205. text: item.Name,
  206. value: item.Id
  207. }
  208. })
  209. this.submitPostData = postData
  210. if(this.reviewerList.length>1){
  211. this.modal = true
  212. return
  213. }
  214. }
  215. const success = await this.HTTP_POST(
  216. this.type === 'sign' ? 'learun/adms/newwf/sign' : 'learun/adms/newwf/audit',
  217. postData,
  218. `提交[${this.typeText}]时发生错误`
  219. )
  220. if (!success) {
  221. return
  222. }
  223. this.EMIT('task-list-change')
  224. this.NAV_BACK(2)
  225. this.TOAST(`已成功提交${this.typeText}`, 'success')
  226. },
  227. // 手写板事件(开始拖动)
  228. signStart(e) {
  229. touchs.push({
  230. x: e.changedTouches[0].x,
  231. y: e.changedTouches[0].y
  232. })
  233. },
  234. // 手写板事件(拖动签名)
  235. signMove(e) {
  236. touchs.push({
  237. x: e.touches[0].x,
  238. y: e.touches[0].y
  239. })
  240. this.drawLine()
  241. },
  242. // 手写板事件(签名结束)
  243. signEnd(e) {
  244. touchs = []
  245. },
  246. // 手写板事件(绘出线型)
  247. drawLine() {
  248. if (touchs.length < 2) {
  249. return
  250. }
  251. const [p1, p2] = touchs
  252. touchs.shift()
  253. context.moveTo(p1.x, p1.y)
  254. context.lineTo(p2.x, p2.y)
  255. context.stroke()
  256. context.draw(true)
  257. },
  258. // 清除手写板
  259. // 阿里小程序无法使用 clearRect 来清空,因此直接重新渲染 canvas
  260. clearSign() {
  261. // #ifndef MP-ALIPAY
  262. context.clearRect(0, 0, 9999, 9999)
  263. context.draw()
  264. context.setStrokeStyle('#000')
  265. context.setLineWidth(5)
  266. context.setLineCap('round')
  267. context.setLineJoin('round')
  268. // #endif
  269. // #ifdef MP-ALIPAY
  270. // 阿里系小程序无法 clearRect 清空画布,必须重新渲染 canvas
  271. this.canvas = false
  272. this.$nextTick(() => {
  273. this.canvasInit()
  274. })
  275. // #endif
  276. }
  277. }
  278. }
  279. </script>
  280. <style lang="less" scoped>
  281. .sign-area {
  282. min-height: 500rpx;
  283. margin: 23rpx;
  284. border: 2rpx dashed #444444;
  285. .sign-canvas {
  286. width: 700rpx;
  287. height: 500rpx;
  288. }
  289. .sign-action {
  290. text-align: right;
  291. }
  292. }
  293. </style>