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.
 
 
 
 
 
 

329 lines
9.0 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. const success = await this.HTTP_POST(
  108. this.type === 'sign' ? 'learun/adms/newwf/sign' : 'learun/adms/newwf/auditors',
  109. this.submitPostData,
  110. `提交[${this.typeText}]时发生错误`
  111. )
  112. if (!success) {
  113. return
  114. }
  115. this.EMIT('task-list-change')
  116. this.NAV_BACK(2)
  117. this.TOAST(`已成功提交${this.typeText}`, 'success')
  118. },
  119. // 点击「提交」按钮
  120. async submit() {
  121. if (this.type === 'sign' && !this.staff) {
  122. this.CONFIRM('请补全必填项', '必须指定一个加签用户')
  123. return
  124. }
  125. const postData = {
  126. operationCode: this.taskParam.code,
  127. operationName: this.taskParam.name,
  128. processId: this.taskParam.processId,
  129. taskId: this.taskParam.taskId,
  130. des: this.remark,
  131. formreq: this.taskParam.formreq
  132. }
  133. if (this.type === 'sign') {
  134. postData.userId = this.staff
  135. } else {
  136. postData.auditors = this.taskParam.auditors
  137. }
  138. // 需要手写签名时,将 canvas 导出为 base64 格式
  139. // 各个平台写法均不相同,需要注意
  140. if (Number(this.taskParam.isSign) === 1) {
  141. // H5 平台,canvasToTempFilePath 的结果直接为画布的 base64
  142. // #ifdef H5
  143. const [err, { tempFilePath }] = await uni.canvasToTempFilePath({ canvasId: 'sign-canvas' })
  144. postData.signUrl = tempFilePath
  145. // #endif
  146. // App 平台,canvasToTempFilePath 输出文件,上传后台转为 base64 格式
  147. // #ifdef APP-VUE
  148. const [err, { tempFilePath }] = await uni.canvasToTempFilePath({ canvasId: 'sign-canvas' })
  149. const signBase64 = await this.HTTP_UPLOAD('/annexes/wxtobase64', tempFilePath)
  150. postData.signUrl = 'data:image/png;base64,' + signBase64
  151. // #endif
  152. // 微信小程序,canvasToTempFilePath 输出文件,使用文件管理器以 base64 格式读取文件即可
  153. // #ifdef MP-WEIXIN
  154. const [err, { tempFilePath }] = await uni.canvasToTempFilePath({ canvasId: 'sign-canvas' })
  155. postData.signUrl = 'data:image/png;base64,' + uni.getFileSystemManager().readFileSync(tempFilePath, 'base64')
  156. // #endif
  157. // #ifdef MP-ALIPAY
  158. // 钉钉小程序,context.toTempFilePath 输出文件,上传后台转为 base64 格式
  159. // #ifdef MP-DINGTALK
  160. const filePath = await new Promise((res, rej) => {
  161. context.toTempFilePath({
  162. success: ({ filePath }) => {
  163. res(filePath)
  164. },
  165. fail: () => {
  166. rej()
  167. }
  168. })
  169. })
  170. const signBase64 = await this.HTTP_UPLOAD('/annexes/wxtobase64', filePath)
  171. postData.signUrl = 'data:image/png;base64,' + signBase64
  172. // #endif
  173. // 支付宝小程序,context.toDataURL 直接输出 base64 字符串
  174. // #ifndef MP-DINGTALK
  175. postData.signUrl = await context.toDataURL('image/png', 1)
  176. // #endif
  177. // #endif
  178. }
  179. // 是否需要指派审核人
  180. let isNext = this.taskParam.currentNode.isNext
  181. if (this.taskParam.next == '2') {
  182. isNext = '1';
  183. }
  184. if (isNext == '1') {
  185. let params = {
  186. code: this.taskParam.schemeCode,
  187. processId: this.taskParam.processId,
  188. taskId: this.taskParam.taskId,
  189. nodeId: this.taskParam.currentNode.id,
  190. operationCode: this.taskParam.code,
  191. }
  192. const userList = await this.HTTP_GET('learun/adms/newwf/auditer', params, `获取审核人时发生错误`)
  193. if (!userList) {
  194. return
  195. }
  196. let arr = Object.entries(userList)
  197. this.reviewerListId = arr[0][0]
  198. this.reviewerList = arr[0][1].map(item => {
  199. return {
  200. text: item.Name,
  201. value: item.Id
  202. }
  203. })
  204. this.submitPostData = postData
  205. this.modal = true
  206. return
  207. }
  208. const success = await this.HTTP_POST(
  209. this.type === 'sign' ? 'learun/adms/newwf/sign' : 'learun/adms/newwf/audit',
  210. postData,
  211. `提交[${this.typeText}]时发生错误`
  212. )
  213. if (!success) {
  214. return
  215. }
  216. this.EMIT('task-list-change')
  217. this.NAV_BACK(2)
  218. this.TOAST(`已成功提交${this.typeText}`, 'success')
  219. },
  220. // 手写板事件(开始拖动)
  221. signStart(e) {
  222. touchs.push({
  223. x: e.changedTouches[0].x,
  224. y: e.changedTouches[0].y
  225. })
  226. },
  227. // 手写板事件(拖动签名)
  228. signMove(e) {
  229. touchs.push({
  230. x: e.touches[0].x,
  231. y: e.touches[0].y
  232. })
  233. this.drawLine()
  234. },
  235. // 手写板事件(签名结束)
  236. signEnd(e) {
  237. touchs = []
  238. },
  239. // 手写板事件(绘出线型)
  240. drawLine() {
  241. if (touchs.length < 2) {
  242. return
  243. }
  244. const [p1, p2] = touchs
  245. touchs.shift()
  246. context.moveTo(p1.x, p1.y)
  247. context.lineTo(p2.x, p2.y)
  248. context.stroke()
  249. context.draw(true)
  250. },
  251. // 清除手写板
  252. // 阿里小程序无法使用 clearRect 来清空,因此直接重新渲染 canvas
  253. clearSign() {
  254. // #ifndef MP-ALIPAY
  255. context.clearRect(0, 0, 9999, 9999)
  256. context.draw()
  257. context.setStrokeStyle('#000')
  258. context.setLineWidth(5)
  259. context.setLineCap('round')
  260. context.setLineJoin('round')
  261. // #endif
  262. // #ifdef MP-ALIPAY
  263. // 阿里系小程序无法 clearRect 清空画布,必须重新渲染 canvas
  264. this.canvas = false
  265. this.$nextTick(() => {
  266. this.canvasInit()
  267. })
  268. // #endif
  269. }
  270. }
  271. }
  272. </script>
  273. <style lang="less" scoped>
  274. .sign-area {
  275. min-height: 500rpx;
  276. margin: 23rpx;
  277. border: 2rpx dashed #444444;
  278. .sign-canvas {
  279. width: 700rpx;
  280. height: 500rpx;
  281. }
  282. .sign-action {
  283. text-align: right;
  284. }
  285. }
  286. </style>