Prechádzať zdrojové kódy

feat(process/detail): 手写板签名

wangpx 1 rok pred
rodič
commit
08e2354cff
2 zmenil súbory, kde vykonal 212 pridanie a 37 odobranie
  1. 32 4
      api/process.js
  2. 180 33
      pages/process/detail/index.vue

+ 32 - 4
api/process.js

@@ -1,4 +1,6 @@
 import request from '@/utils/request.js'
+import upload from '@/utils/upload'
+
 const preUrl = '/clientServices.do?iscrypt=1'
 //获取用户所有流程
 export function getUserAllProcess({ staffId, page, pageNum }) {
@@ -84,7 +86,7 @@ export function getUnProcessNum(userId, startTime) {
 		}
 	})
 }
-
+// 获取流程详情
 export function getProcessFlowInfo(userId, { tinsId, control }) {
 	return request({
 		url: preUrl,
@@ -100,7 +102,7 @@ export function getProcessFlowInfo(userId, { tinsId, control }) {
 	})
 }
 
-//获取流程详情
+// 获取流程表单信息
 export function getProcessFormInfo(userId, insId) {
 	return request({
 		url: preUrl,
@@ -114,6 +116,7 @@ export function getProcessFormInfo(userId, insId) {
 		}
 	})
 }
+// 获取流程表单详情
 export function getProcessFormInfoInFlow(useId, {tinsId, insId, control}) {
 	return request({
 		url: preUrl,
@@ -129,7 +132,7 @@ export function getProcessFormInfoInFlow(useId, {tinsId, insId, control}) {
 		}
 	})
 }
-
+// 获取流程流转信息
 export function getProcessFlow(userId, { insId, control }) {
 	return request({
 		url: preUrl,
@@ -160,7 +163,8 @@ export function submitProcessFlow(flow, form, control) {
 	})
 }
 
-export function cancelProcessFlow(staffId, cancelRemark, {insId, control}) {return request({
+export function cancelProcessFlow(staffId, cancelRemark, {insId, control}) {
+	return request({
 		url: preUrl,
 		method: 'post',
 		data: {
@@ -173,4 +177,28 @@ export function cancelProcessFlow(staffId, cancelRemark, {insId, control}) {retu
 			}
 		}
 	})
+}
+
+export function uploadSignatureImg(filePath) {
+	return upload({
+    url: '/MiniAppUploadFileAction.do',
+    name: 'SignatureImg.png',
+    filePath: filePath
+  })
+}
+
+export function uploadSignatureBoardImg(userId, filePath, elementID, type) {
+	return request({
+    url: preUrl,
+    method: 'post',
+    data: {
+    	serviceId: 'bpm_2018V001Board001',
+    	params: {
+    		userId,
+				img: filePath,
+				elementID,
+				type: '2'
+    	}
+    }
+  })
 }

+ 180 - 33
pages/process/detail/index.vue

@@ -3,22 +3,36 @@
 		<uni-card>
 			<view class="main_container">
 				<uni-section titleFontSize="1.3rem" title="申请内容" type="line"></uni-section>
-				<uni-list>
-					<uni-list-item v-for="(elem, index) in formElements" :key="index">
-						<template v-slot:header>
-							<text class="element_name">{{ elem.elementName }}</text>
-						</template>
-						<template v-slot:footer>
-							<view class="element_value">
-								<view v-if="elem.canEdit == '1'" class="element_value">
+				<uni-forms label-position="left" :label-width="125" :border="true">
+					<view v-for="(elem, index) in formElements" :key="index">
+						<uni-forms-item
+							v-if="!('0' == elem.canEdit && elem.elementName.slice(-2) == '审批' && '' == elem.defaultValue)"
+							:label="elem.elementName">
+							<view class="element_value_container">
+								<view v-if="'1' == elem.canEdit" class="element_value">
+									<!-- 富文本框 -->
 									<uni-easyinput v-if="'1' == elem.type" placeholder="请输入内容"
 										v-model="elem.defaultValue" type="textarea"></uni-easyinput>
+									<!-- 文本框 -->
+									<uni-easyinput v-else-if="'0' == elem.type" placeholder="请输入内容"
+										v-model="elem.defaultValue" type="text"></uni-easyinput>
+									<!-- 审批签字板 -->
+									<view v-else-if="'13' == elem.type">
+										<button v-if="elem.defaultValue == ''" type="primary"
+											@click="handleSignature(index)">签名</button>
+										<view v-else class="signature_img">
+											<img style="width: 100%;" mode="widthFix" @click="handleSignature(index)" :src="elem.defaultValueImg" :alt="elem.elementName + '签名'" />
+										</view>
+									</view>
+								</view>
+								<view v-else-if="typeof elem.defaultValue === 'string' && elem.defaultValue.substring(0, 7) == '/shares'" class="signature_img">
+									<img style="width: 100%;" mode="widthFix" :src="config.baseUrlPre + elem.defaultValue" />
 								</view>
-								<text v-else>{{ elem.defaultValue }}</text>
+								<text class="element_value" v-else>{{ elem.defaultValue }}</text>
 							</view>
-						</template>
-					</uni-list-item>
-				</uni-list>
+						</uni-forms-item>
+					</view>
+				</uni-forms>
 			</view>
 		</uni-card>
 		<view>
@@ -126,15 +140,42 @@
 		</view>
 	</view>
 	<view style="height: 5px; margin-top: 20px;"></view>
+	<uni-popup ref="signaturePopup" @maskClick="closeSignaturePopup">
+		<view class="signature_container" :class="isLandscape ? ' signature_container_landscape' : ''">
+			<view class="signature_content">
+				<l-signature ref="signatureRef" v-if="signaturePopupShow"
+					:landscape="isLandscape" :penSize="8" :minLineWidth="4" :maxLineWidth="12" :openSmooth="true"
+					backgroundColor="#ffffff" penColor="black"></l-signature>
+			</view>
+			<view class="signature_button_container">
+				<uni-row :gutter="10">
+					<uni-col :span="6">
+						<button @click="onclickSignatureButton('undo')">撤销</button>
+					</uni-col>
+					<uni-col :span="6">
+						<button @click="onclickSignatureButton('clear')">清空</button>
+					</uni-col>
+					<uni-col :span="6">
+						<button @click="onclickSignatureButton('save')">保存</button>
+					</uni-col>
+					<uni-col :span="6">
+						<button @click="onclickSignatureButton('landscape')">全屏</button>
+					</uni-col>
+				</uni-row>
+			</view>
+		</view>
+	</uni-popup>
 </template>
 
 <script setup lang="ts">
 import { onMounted, reactive, ref } from 'vue'
 import { onLoad } from '@dcloudio/uni-app'
+import { LSignatureToTempFilePathOptions, LSignatureToFileSuccess } from '@/uni_modules/lime-signature'
 import attachmentList from '@/components/ygoa/attachmentList.vue'
+import config from '@/config.js'
 import $tab from '@/plugins/tab.js'
 import $modal from '@/plugins/modal.js'
-import { getProcessFlowInfo, getProcessFormInfo, getProcessFormInfoInFlow, getProcessFlow, submitProcessFlow, cancelProcessFlow } from '@/api/process.js'
+import { getProcessFlowInfo, getProcessFormInfo, getProcessFormInfoInFlow, getProcessFlow, submitProcessFlow, cancelProcessFlow, uploadSignatureImg, uploadSignatureBoardImg } from '@/api/process.js'
 import { useUserStore } from '@/store/user.js'
 const userStore = useUserStore()
 const processInfo = reactive({
@@ -203,7 +244,7 @@ function initProcessInfo() {
 			formElements.value = returnParams.formElements
 			repeatingForm.value = returnParams.repeatingForm
 			fileList.value = returnParams.fileList
-			if(returnParams.isCancel == 1) {
+			if (returnParams.isCancel == 1) {
 				isCancel.value = true
 			}
 			repeatingFormHasValue()
@@ -244,6 +285,60 @@ function initProcessFlow() {
 	})
 }
 
+const signaturePopup = ref(null)
+const signatureRef = ref(null)
+const signaturePopupShow = ref(false)
+const isLandscape = ref(false)
+const signatureItemIndex = ref(-1)
+function handleSignature(index) {
+	signatureItemIndex.value = index
+	signaturePopup.value.open()
+	initSignature()
+}
+function initSignature() {
+	signaturePopupShow.value = false
+	setTimeout(() => {
+		signaturePopupShow.value = true
+	}, 100)
+}
+function onclickSignatureButton(event) {
+	switch (event) {
+		case 'undo':
+			signatureRef.value.undo()
+			break;
+		case 'clear':
+			signatureRef.value.clear()
+			break;
+		case 'save':
+			signatureRef.value.canvasToTempFilePath({
+				success: (res: LSignatureToFileSuccess) => {
+					console.log('res: ', res);
+					if (res.isEmpty) {
+						$modal.msgError('签名不能为空!')
+						return
+					}
+					uploadSignatureImg(res.tempFilePath).then(res => {
+						formElements.value[signatureItemIndex.value].defaultValue = res.returnParams
+						signatureItemIndex.value = -1
+						signaturePopupShow.value = false
+						signaturePopup.value.close()
+					})
+					formElements.value[signatureItemIndex.value].defaultValueImg = res.tempFilePath
+				}
+			} as LSignatureToTempFilePathOptions)
+			break;
+		case 'landscape':
+			isLandscape.value = !isLandscape.value
+			initSignature()
+			break;
+
+	}
+}
+function closeSignaturePopup() {
+	signatureItemIndex.value = -1
+	signaturePopupShow.value = false
+}
+
 const repeatingFormPopup = ref(null)
 function handlerepeatingForm() {
 	repeatingFormPopup.value.open()
@@ -293,6 +388,10 @@ function submitProcess(result) {
 }
 
 function handleCancelProcess() {
+	if (remark.value.trim() == '') {
+		$modal.msgError('备注不能为空!')
+		return
+	}
 	$modal.confirm('确认撤销').then(() => {
 		cancelProcess()
 	}).catch(() => { })
@@ -316,18 +415,51 @@ function cancelProcess() {
 </script>
 
 <style lang="scss">
-.element_name {
-	width: 10rem;
-	font-weight: 600;
+.uni-section {
+	margin-left: -15px;
+	margin-bottom: 10px;
 }
 
-.element_value {
-	width: 60%;
+.signature_container {
+	background-color: #f5f5f5;
+	height: 40vh;
+	width: 90vw;
+
+	.signature_content {
+		height: 80%;
+		width: 100%;
+	}
+
+	.signature_button_container {
+		height: 20%;
+		width: 100%;
+
+		button {
+			height: 100%;
+		}
+	}
 }
 
-.uni-section {
-	margin-left: -15px;
-	margin-bottom: 10px;
+.signature_container_landscape {
+	height: 100vh;
+	width: 100vw;
+
+	.signature_content {
+		height: 85%;
+		width: 100%;
+	}
+
+	.signature_button_container {
+		margin-top: 10%;
+		height: 15%;
+		width: 100%;
+
+		button {
+			height: 100%;
+			width: 100%;
+			transform: rotate(90deg);
+		}
+	}
 }
 
 .process_detail_container {
@@ -335,6 +467,21 @@ function cancelProcess() {
 
 	.main_container {
 		min-height: 70vh;
+
+		.uni-forms-item__label {
+			font-size: 1rem;
+			font-weight: 600;
+		}
+
+		.element_value_container {
+			.signature_img {
+				width: 180px;
+			}
+
+			.element_value {
+				line-height: 36px;
+			}
+		}
 	}
 
 	.repeating_table_container {
@@ -406,23 +553,23 @@ function cancelProcess() {
 		}
 	}
 
-	.remark_container {
-		.remark_content {
-			margin-bottom: 10px;
-		}
-	}
-
 	.approve_button {
 		position: sticky;
-		z-index: 999;
+		z-index: 10;
 		width: 100%;
 		bottom: 10px;
 	}
+}
 
-	.reject_button {
-		::v-deep uni-card {
-			background-color: #f5f5f5;
-		}
+.reject_button {
+	.uni-card {
+		background-color: #f5f5f5;
+	}
+}
+
+.remark_container {
+	.remark_content {
+		margin-bottom: 10px;
 	}
 }
 </style>