whx 2 ماه پیش
والد
کامیت
3f4c352bb9
51فایلهای تغییر یافته به همراه1979 افزوده شده و 335 حذف شده
  1. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/index.html
  2. 15 19
      virgo.wzfrontend/src/main/resources/static/workark/pdf/web/viewer.html
  3. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/2693.234eea0b.css
  4. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/6530.7391b4b6.css
  5. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/css/7449.9c8ce381.css
  6. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/css/3166.759e3c99.css
  7. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/1083.2fc06206.js
  8. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/1411.8883eaec.js
  9. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/1654.7281dafb.js
  10. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/1736.945aeda9.js
  11. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2156.f84b5e88.js
  12. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2288.8a917230.js
  13. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2477.dbeeee0e.js
  14. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/2693.63ae194a.js
  15. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/3166.e3fb0bc7.js
  16. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/3249.878dcb29.js
  17. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/3713.2e483bef.js
  18. 0 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/3792.9886082b.js
  19. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/4028.b6ce9491.js
  20. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/4028.bfe952fb.js
  21. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/4849.08b62d05.js
  22. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/4858.44764f06.js
  23. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/4978.f041a2bb.js
  24. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/5895.5c450dfa.js
  25. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/5957.c136ba0a.js
  26. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/6103.48f3b899.js
  27. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/6604.40ea4d65.js
  28. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/6653.7b58c9fb.js
  29. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/6991.da5327dd.js
  30. 1 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/7230.b1be6194.js
  31. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/7444.14414622.js
  32. 67 0
      virgo.wzfrontend/src/main/resources/static/workark/static/js/7449.9397aa74.js
  33. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/7788.e79f236c.js
  34. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/8083.def76eee.js
  35. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/8099.faf529ff.js
  36. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/8484.1e867047.js
  37. 0 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/9372.e0286144.js
  38. 1 1
      virgo.wzfrontend/src/main/resources/static/workark/static/js/app.ccd7977c.js
  39. 1306 160
      virgo.wzfrontend/workark/package-lock.json
  40. 2 2
      virgo.wzfrontend/workark/package.json
  41. 15 19
      virgo.wzfrontend/workark/public/pdf/web/viewer.html
  42. 25 2
      virgo.wzfrontend/workark/src/api/finace.js
  43. 241 11
      virgo.wzfrontend/workark/src/components/common/pdfViewer.vue
  44. 4 5
      virgo.wzfrontend/workark/src/components/work/finace/contract/contractUpload.vue
  45. 110 0
      virgo.wzfrontend/workark/src/components/work/finace/contract/selectContract.vue
  46. 3 3
      virgo.wzfrontend/workark/src/components/work/finace/invoice/apply/edit.vue
  47. 0 0
      virgo.wzfrontend/workark/src/components/work/finace/invoice/selectInvoice.vue
  48. 2 1
      virgo.wzfrontend/workark/src/components/work/serve/content/edit.vue
  49. 159 6
      virgo.wzfrontend/workark/src/components/work/serve/list/detail.vue
  50. 3 3
      virgo.wzfrontend/workark/src/views/work/finance/invoiceHeader.vue
  51. 6 86
      virgo.wzfrontend/workark/src/views/work/finance/organizationContract.vue

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/index.html


+ 15 - 19
virgo.wzfrontend/src/main/resources/static/workark/pdf/web/viewer.html

@@ -221,14 +221,16 @@
 					return rs
 				})
 				return obj
-			}
-			
+			}
+
 			var query = getQueryObject();
 			if (query.type == 'look') {
 				positionList = window.parent['getPositionList']();
-			} else if (query.type == 'update') {
+			} else if (query.type == 'edit') {
 				document.getElementsByClassName('operation')[0].style.display = 'block';
-				positionList = window.parent['getPositionList']();
+				if (window.parent.getPositionList) {
+					positionList = window.parent['getPositionList']();
+				}
 			}
 
 			function renderPage(page) {
@@ -300,24 +302,23 @@
 
 			function btn(_self) {
 				_self.parentNode.style.display = 'none'
-				window.parent['signSeal'](_self.id, 'page' + nowIndex);
+				// window.parent['signSeal'](_self.id, 'page' + nowIndex);
+				createImage('https://fc1tn.baidu.com/it/u=3484410304,3029921230&fm=202&mola=new&crop=v1',1)
 			}
 
-			function createImage(type, imageUrl, elemId, recipient, sealId) {
-				var div = document.createElement('div');
-				div.className = type + ' move'
-				div.setAttribute('recipient', recipient);
+			function createImage(imageUrl, sealId) {
+				var div = document.createElement('div');
+				div.className = 'seal move'
 				div.setAttribute('sealId', sealId);
 				div.innerHTML = '<img src="' + imageUrl + '">'
-				document.getElementById(elemId).appendChild(div);
-				moveType = type;
-				url = imageUrl;
+				document.getElementById('page0').appendChild(div);
 				move();
 			}
 
 			function move() {
 				var oBox = document.getElementsByClassName("move")[0];
-				oBox.onmousedown = function(ev) {
+				oBox.onmousedown = function(ev) {
+					console.log('-----');
 					var disX = ev.clientX - oBox.offsetLeft;
 					var disY = ev.clientY - oBox.offsetTop;
 					document.onmousemove = function(ev) {
@@ -341,12 +342,7 @@
 			}
 
 			function sure() {
-				return {
-					url: query.fileUrl,
-					fileId: query.fileId,
-					fileName: query.fileName,
-					positionList: positionList
-				}
+				return {}
 			}
 		</script>
 	</body>

virgo.wzfrontend/src/main/resources/static/workark/static/css/5957.234eea0b.css → virgo.wzfrontend/src/main/resources/static/workark/static/css/2693.234eea0b.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/css/6530.7391b4b6.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/css/7449.9c8ce381.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/css/3166.759e3c99.css


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/1083.2fc06206.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/1411.8883eaec.js


virgo.wzfrontend/src/main/resources/static/workark/static/js/1654.883ff169.js → virgo.wzfrontend/src/main/resources/static/workark/static/js/1654.7281dafb.js


virgo.wzfrontend/src/main/resources/static/workark/static/js/1736.60f72f49.js → virgo.wzfrontend/src/main/resources/static/workark/static/js/1736.945aeda9.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/2156.f84b5e88.js


virgo.wzfrontend/src/main/resources/static/workark/static/js/2288.efef54ac.js → virgo.wzfrontend/src/main/resources/static/workark/static/js/2288.8a917230.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/2477.dbeeee0e.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/2693.63ae194a.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/3166.e3fb0bc7.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/3249.878dcb29.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/3713.2e483bef.js


virgo.wzfrontend/src/main/resources/static/workark/static/js/3792.e0853fb5.js → virgo.wzfrontend/src/main/resources/static/workark/static/js/3792.9886082b.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/4028.b6ce9491.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/4028.bfe952fb.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/4849.08b62d05.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/4858.44764f06.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/4978.f041a2bb.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/5895.5c450dfa.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/5957.c136ba0a.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/6103.48f3b899.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/6604.40ea4d65.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/6653.7b58c9fb.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/6991.da5327dd.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/7230.b1be6194.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/7444.14414622.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 67 - 0
virgo.wzfrontend/src/main/resources/static/workark/static/js/7449.9397aa74.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/7788.e79f236c.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/8083.def76eee.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/8099.faf529ff.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/8484.1e867047.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/9372.e0286144.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1 - 1
virgo.wzfrontend/src/main/resources/static/workark/static/js/app.ccd7977c.js


تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1306 - 160
virgo.wzfrontend/workark/package-lock.json


+ 2 - 2
virgo.wzfrontend/workark/package.json

@@ -11,10 +11,10 @@
 		"axios": "^0.19.0",
 		"core-js": "^3.8.3",
 		"element-ui": "^2.15.14",
-		"pdfjs-dist": "^2.6.347",
+		"fabric": "^6.6.1",
+		"pdfvuer": "^1.10.0",
 		"sortablejs": "^1.15.6",
 		"vue": "^2.6.14",
-		"vue-quill-editor": "^3.0.6",
 		"vue-router": "^3.1.3",
 		"vuex": "^3.0.1"
 	},

+ 15 - 19
virgo.wzfrontend/workark/public/pdf/web/viewer.html

@@ -221,14 +221,16 @@
 					return rs
 				})
 				return obj
-			}
-			
+			}
+
 			var query = getQueryObject();
 			if (query.type == 'look') {
 				positionList = window.parent['getPositionList']();
-			} else if (query.type == 'update') {
+			} else if (query.type == 'edit') {
 				document.getElementsByClassName('operation')[0].style.display = 'block';
-				positionList = window.parent['getPositionList']();
+				if (window.parent.getPositionList) {
+					positionList = window.parent['getPositionList']();
+				}
 			}
 
 			function renderPage(page) {
@@ -300,24 +302,23 @@
 
 			function btn(_self) {
 				_self.parentNode.style.display = 'none'
-				window.parent['signSeal'](_self.id, 'page' + nowIndex);
+				// window.parent['signSeal'](_self.id, 'page' + nowIndex);
+				createImage('https://fc1tn.baidu.com/it/u=3484410304,3029921230&fm=202&mola=new&crop=v1',1)
 			}
 
-			function createImage(type, imageUrl, elemId, recipient, sealId) {
-				var div = document.createElement('div');
-				div.className = type + ' move'
-				div.setAttribute('recipient', recipient);
+			function createImage(imageUrl, sealId) {
+				var div = document.createElement('div');
+				div.className = 'seal move'
 				div.setAttribute('sealId', sealId);
 				div.innerHTML = '<img src="' + imageUrl + '">'
-				document.getElementById(elemId).appendChild(div);
-				moveType = type;
-				url = imageUrl;
+				document.getElementById('page0').appendChild(div);
 				move();
 			}
 
 			function move() {
 				var oBox = document.getElementsByClassName("move")[0];
-				oBox.onmousedown = function(ev) {
+				oBox.onmousedown = function(ev) {
+					console.log('-----');
 					var disX = ev.clientX - oBox.offsetLeft;
 					var disY = ev.clientY - oBox.offsetTop;
 					document.onmousemove = function(ev) {
@@ -341,12 +342,7 @@
 			}
 
 			function sure() {
-				return {
-					url: query.fileUrl,
-					fileId: query.fileId,
-					fileName: query.fileName,
-					positionList: positionList
-				}
+				return {}
 			}
 		</script>
 	</body>

+ 25 - 2
virgo.wzfrontend/workark/src/api/finace.js

@@ -114,7 +114,7 @@ export function deleteInvoiceById(id) {
 		url: `/api/workarkInvoice/delete/${id}`,
 		method: 'delete'
 	})
-}
+}
 /* 
  * 获取企业合同
  * 
@@ -125,7 +125,7 @@ export function getOrganizationContract(organizationId) {
 		url: `/file/workarkContract/${organizationId}`,
 		method: 'get'
 	})
-}
+}
 /* 
  * 删除企业合同
  * 
@@ -136,4 +136,27 @@ export function deleteOrganizationContract(id) {
 		url: `/file/workarkContract/${id}`,
 		method: 'delete'
 	})
+}
+/* 
+ * 绑定企业合同
+ * 
+ * 
+ */
+export function bindContract(data) {
+	return request({
+		url: `/file/workarkContract/pdf`,
+		method: 'post',
+		data: data
+	})
+}
+/* 
+ * 获取绑定企业合同详情
+ * 
+ * 
+ */
+export function getBindContract(pdfId) {
+	return request({
+		url: `/file/workarkContract/show/${pdfId}`,
+		method: 'get'
+	})
 }

+ 241 - 11
virgo.wzfrontend/workark/src/components/common/pdfViewer.vue

@@ -1,27 +1,186 @@
 <template>
 	<div class="pdf-viewer">
-		<iframe v-if="pdfUrl" :src="pdfUrl" ref="iframe" class="iframe-pdf"></iframe>
+		<div class="pdf-viewer-box">
+			<div class="preview-box">
+				<div class="thumbnail-item" v-for="(thumb, index) in thumbnails" :key="index"
+					:class="{ active: currentPage === index + 1 }" @click="changePage(index + 1)">
+					<img class="image" :src="thumb" alt="thumbnail" />
+					<div class="text">{{index+1}}</div>
+				</div>
+			</div>
+			<div class="operation-box">
+				<canvas ref="mainCanvas"></canvas>
+				<div ref="fabricCanvas" class="fabric-canvas">
+					<canvas id="fabricCanvas"></canvas>
+				</div>
+			</div>
+			<div class="operation-button" v-if="type === 'edit'">
+				<div class="button-item">
+					<el-button type="primary" size="mini">签字</el-button>
+				</div>
+				<div class="button-item">
+					<el-button type="primary" size="mini" @click="insertSeal">盖章</el-button>
+				</div>
+			</div>
+		</div>
+		<div class="hui-dialog-submit" v-if="type === 'edit'">
+			<el-button size="small" @click="$emit('callback')">取 消</el-button>
+			<el-button size="small" type="primary" @click="submit" :loading="loading">提 交</el-button>
+		</div>
+		
 	</div>
 </template>
 
 <script>
+	import pdf from 'pdfvuer';
+	import * as fabric from 'fabric';
 	export default {
 		props: ['list', 'type'],
 		data() {
 			return {
-				pdfUrl: ''
+				pdfDoc: null,
+				currentPage: 1,
+				totalPages: 0,
+				thumbnails: [], // 存储缩略图 Base64
+				renderTask: null,
+				fabricCanvas: null,
+				sealObj: null,
+				loading: false
 			}
 		},
-		mounted() {
+		beforeDestroy() {
+			if (this.fabricCanvas) {
+				document.removeEventListener('keydown', this.initDelete);
+			}
+		},
+		async mounted() {
 			if (this.list.length > 0) {
-				this.selectPdf();
+				await this.loadPdf(this.list[0].url);
+				await this.generateThumbnails();
+				await this.changePage(1);
+			}
+			if (this.type === 'edit') {
+				document.addEventListener('keydown', this.initDelete);
 			}
 		},
 		methods: {
-			selectPdf() {
-				this.pdfUrl = '';
-				this.pdfUrl = '/pdf/web/viewer.html?file=' + this.list[0].url + '&type=' + this.type;
+			//加载pdf
+			async loadPdf(url) {
+				const loadingTask = pdf.createLoadingTask({
+					url
+				});
+				this.pdfDoc = await loadingTask;
+				this.totalPages = this.pdfDoc._pdfInfo.numPages;
+			},
+			// 生成所有缩略图
+			async generateThumbnails() {
+				for (let pageNum = 1; pageNum <= this.totalPages; pageNum++) {
+					const page = await this.pdfDoc.getPage(pageNum);
+					const thumbnail = await this.renderPageToImage(page); // 缩略图缩放比例
+					this.thumbnails.push(thumbnail);
+				}
+			},
+			// 将单页渲染为图片(Base64)
+			async renderPageToImage(page) {
+				const viewport = page.getViewport({
+					scale: 1
+				});
+				const canvas = document.createElement('canvas');
+				const context = canvas.getContext('2d');
+				const outputScale = window.devicePixelRatio || 1;
+				this.setCanvasSize(canvas, viewport, outputScale);
+				const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null;
+				await page.render({
+					canvasContext: context,
+					viewport,
+					transform
+				}).promise;
+				// 转换为 Base64
+				return canvas.toDataURL('image/jpeg', 1);
+			},
+			// 切换页面
+			async changePage(pageNum) {
+				this.currentPage = pageNum;
+				const page = await this.pdfDoc.getPage(pageNum);
+				await this.renderMainPage(page);
+			},
+			// 渲染主视图(高清大图)
+			async renderMainPage(page) {
+				const viewport = page.getViewport({
+					scale: 1
+				});
+				const canvas = this.$refs.mainCanvas;
+				const context = canvas.getContext('2d');
+				const outputScale = window.devicePixelRatio || 1;
+				this.setCanvasSize(canvas, viewport, outputScale);
+				const transform = outputScale !== 1 ? [outputScale, 0, 0, outputScale, 0, 0] : null;
+				// 取消之前的渲染任务(避免冲突)
+				if (this.renderTask) this.renderTask.cancel();
+				// 渲染高清大图
+				this.renderTask = page.render({
+					canvasContext: context,
+					viewport,
+					transform
+				});
+				await this.renderTask.promise;
+			},
+			setCanvasSize(canvas, viewport, outputScale) {
+				canvas.width = Math.floor(viewport.width * outputScale);
+				canvas.height = Math.floor(viewport.height * outputScale);
+				canvas.style.width = Math.floor(viewport.width) + "px";
+				canvas.style.height = Math.floor(viewport.height) + "px";
+				if (this.fabricCanvas) this.fabricCanvas.dispose();
+				if (this.type === 'edit') {
+					this.$refs.fabricCanvas.style.width = Math.floor(viewport.width) + "px";
+					this.$refs.fabricCanvas.style.height = Math.floor(viewport.height) + "px";
+					this.fabricCanvas = new fabric.Canvas('fabricCanvas', {
+						width: Math.floor(viewport.width), // 设置画布宽度
+						height: Math.floor(viewport.height), // 设置画布高度
+					});
+				}
 			},
+			insertSeal() {
+				if (!this.fabricCanvas) return;
+				fabric.Image.fromURL('./assets/wechat_code.jpg').then(img => {
+					let scale = 100 / img.width;
+					img.scale(scale);
+					img.set({
+						top: 0,
+						left: 0
+					})
+					this.sealObj = img;
+					// 将文字添加到画布
+					this.fabricCanvas.add(img);
+					this.fabricCanvas.renderAll();
+				});
+			},
+			sureSeal() {
+				this.fabricCanvas.discardActiveObject();
+				this.sealObj.set({
+					selectable: false
+				});
+			},
+			initDelete(event) {
+				if (!this.fabricCanvas) return;
+				if (event.key === 'Delete' || event.key === 'Backspace') {
+					var activeObject = this.fabricCanvas.getActiveObject(); // 获取当前激活的对象
+					if (activeObject) {
+						this.fabricCanvas.remove(activeObject); // 删除选中的对象
+					}
+				}
+			},
+			submit() {
+				const allObjects = this.fabricCanvas.getObjects();
+				for (let i = 0; i < allObjects.length; i++) {
+					let item = allObjects[i];
+					console.log({
+						left: item.left,
+						top: item.top,
+						width: item.width * item.scaleX,
+						height: item.height * item.scaleY
+					});
+				}
+			}
 		},
 	}
 </script>
@@ -30,11 +189,82 @@
 		height: 100%;
 		width: 100%;
 		overflow: hidden;
+		display: flex;
+		flex-direction: column;
+
+		.hui-dialog-submit {
+			border-top: 1px solid $--border-color-light;
+			text-align: right;
+			padding: 10px;
+		}
+
+		.pdf-viewer-box {
+			flex: 1;
+			height: 0;
+			display: flex;
+			position: relative;
+		}
 
-		.iframe-pdf {
-			border: none;
-			height: 100%;
-			width: 100%;
+		.operation-button {
+			position: absolute;
+			bottom: 20px;
+			right: 20px;
+
+			.button-item {
+				margin-top: 10px;
+			}
+		}
+
+		.preview-box {
+			overflow-y: auto;
+
+			.thumbnail-item {
+				width: 100px;
+				padding: 10px 10px 0 10px;
+				cursor: pointer;
+
+				.image {
+					border: 1px solid $--border-color-light;
+					width: 100%;
+				}
+
+				.text {
+					text-align: center;
+					padding-top: 5px;
+				}
+
+				&:last-child {
+					padding-bottom: 10px;
+				}
+
+				&.active {
+					.image {
+						border-color: $--color-primary;
+					}
+
+					.text {
+						color: $--color-primary;
+					}
+				}
+			}
+		}
+
+		.operation-box {
+			flex: 1;
+			width: 0;
+			overflow-y: auto;
+			background: $--background-color-base;
+			text-align: center;
+			position: relative;
+
+			.fabric-canvas {
+				position: absolute;
+				top: 0;
+				left: 0;
+				right: 0;
+				margin: auto;
+				z-index: 9;
+			}
 		}
 	}
 </style>

+ 4 - 5
virgo.wzfrontend/workark/src/components/work/finace/contract/contractUpload.vue

@@ -1,7 +1,8 @@
 <template>
 	<div class="datacenter-upload">
 		<el-upload :action="action" name="uploadFile" ref="upload" :headers="headers" :on-success="successFile"
-			:before-upload="beforeUpload" :on-error="errorUpload" :show-file-list="false" :on-progress="progress" accept=".docx">
+			:before-upload="beforeUpload" :on-error="errorUpload" :show-file-list="false" :on-progress="progress"
+			accept=".docx">
 			<div class="bim-update-button">
 				<i class="el-icon-plus"></i>
 			</div>
@@ -27,8 +28,7 @@
 				this.action = config.baseURL + '/file/workarkContract/' + this.$store.getters.organization.id;
 			} else {
 				this.action = config.baseURL + '/file/workarkContract/update/' + this.contractId;
-			}
-			console.log(this.contractId);
+			}
 			this.headers.token = getToken();
 		},
 		methods: {
@@ -55,8 +55,7 @@
 			},
 		},
 		watch: {
-			contractId() {
-				console.log(this.contractId);
+			contractId() {
 				if (!this.contractId) {
 					this.action = config.baseURL + '/file/workarkContract/' + this.$store.getters.organization.id;
 				} else {

+ 110 - 0
virgo.wzfrontend/workark/src/components/work/finace/contract/selectContract.vue

@@ -0,0 +1,110 @@
+<template>
+	<div class="hui-flex-box hui-flex hui-table">
+		<div class="hui-content-insert">
+			<el-button type="primary" size="small" @click="upload()">上传合同</el-button>
+			<contract-upload ref="upload" v-show="false" :contractId="contractId" type="project" @reload="init">
+			</contract-upload>
+		</div>
+		<div class="hui-flex-box">
+			<el-table ref="elTable" :data="tableData" height="100%" v-loading="loading"@current-change="handleCurrentChange">
+				<el-table-column width="35" v-if="type === 'filter'">
+					<template slot-scope="scope">
+						<el-radio class="radio" :label="scope.row" v-model="currentRow">{{""}}</el-radio>
+					</template>
+				</el-table-column>
+				<el-table-column prop="name" label="合同名称">
+				</el-table-column>
+				<el-table-column prop="createDate" label="创建时间">
+				</el-table-column>
+				<el-table-column prop="updateDate" label="更新时间">
+				</el-table-column>
+				<el-table-column label="操作" width="180" align="center">
+					<template slot-scope="scope">
+						<div class="hui-table-operation">
+							<span class="table-operation" @click="previewItem(scope.row)">预览</span>
+							<span class="table-operation" @click="upload(scope.row.id)">更新</span>
+							<span class="table-operation" @click="deleteItem(scope.row.id)">删除</span>
+						</div>
+					</template>
+				</el-table-column>
+				<template slot="empty">
+					<el-empty description="暂无数据"></el-empty>
+				</template>
+			</el-table>
+		</div>
+		<el-dialog :close-on-click-modal="false" title="预览合同" :visible.sync="dialogVisible" width="900px"
+			:append-to-body="true">
+			<pdf-viewer v-if="dialogVisible" :list="contractList" type="preview">
+			</pdf-viewer>
+		</el-dialog>
+	</div>
+</template>
+
+<script>
+	import {
+		getOrganizationContract,
+		deleteOrganizationContract
+	} from '@/api/finace'
+	const contractUpload = () => import('@/components/work/finace/contract/contractUpload');
+	const pdfViewer = () => import('@/components/common/pdfViewer');
+	import config from '@/config';
+	export default {
+		props: ['type'],
+		data() {
+			return {
+				tableData: [],
+				loading: false,
+				contractList: [],
+				contractId: '',
+				dialogVisible: false,
+				currentRow: null
+			}
+		},
+		mounted() {
+			this.init();
+		},
+		methods: {
+			init(type) {
+				this.loading = true;
+				getOrganizationContract(this.$store.getters.organization.id).then(res => {
+					this.loading = false;
+					if (res.state) {
+						this.tableData = res.data;
+						if (this.type === 'filter') this.currentRow = this.tableData[0];
+					}
+				})
+			},
+			handleCurrentChange(row) {
+				this.currentRow = row;
+			},
+			upload(id) {
+				this.contractId = id;
+				this.$nextTick(() => {
+					this.$refs.upload.reloadUpload();
+				})
+			},
+			previewItem(item) {
+				this.contractList = [{
+					url: window.location.origin + '/' + config.baseURL + '/file/workarkContract/pdf/' + item.id
+				}]
+				this.dialogVisible = true;
+			},
+			deleteItem(id) {
+				this.$confirm('确定要删除合同?', () => {
+					deleteOrganizationContract(id).then(res => {
+						if (res.state) {
+							this.$message.success('操作成功');
+							this.init();
+						}
+					})
+				});
+			}
+		},
+		components: {
+			contractUpload,
+			pdfViewer
+		}
+	}
+</script>
+
+<style lang="scss"></style>

+ 3 - 3
virgo.wzfrontend/workark/src/components/work/finace/invoice/apply/edit.vue

@@ -43,7 +43,7 @@
 		<el-dialog :close-on-click-modal="false" title="选择发票抬头" :visible.sync="visible" width="1100px"
 			:append-to-body="true">
 			<div class="hui-flex hui-content hui-dialog">
-				<invoice-header ref="selectInvoiceHeader" v-if="visible" type="filter"></invoice-header>
+				<select-invoice ref="selectInvoiceHeader" v-if="visible" type="filter"></select-invoice>
 				<div class="hui-dialog-submit">
 					<el-button size="small" @click="visible = false">取 消</el-button>
 					<el-button size="small" type="primary" @click="selectInvoiceHeader">确定</el-button>
@@ -57,7 +57,7 @@
 	import {
 		insertInvoice
 	} from '@/api/finace'
-	const invoiceHeader = () => import('@/components/work/finace/invoice/invoiceHeader');
+	const selectInvoice = () => import('@/components/work/finace/invoice/selectInvoice');
 	export default {
 		props: ['orderNo'],
 		data() {
@@ -112,7 +112,7 @@
 			}
 		},
 		components: {
-			invoiceHeader
+			selectInvoice
 		}
 	}
 </script>

virgo.wzfrontend/workark/src/components/work/finace/invoice/invoiceHeader.vue → virgo.wzfrontend/workark/src/components/work/finace/invoice/selectInvoice.vue


+ 2 - 1
virgo.wzfrontend/workark/src/components/work/serve/content/edit.vue

@@ -22,7 +22,8 @@
 					<upload ref="detailedImage" :list="detailedImage" type="insert" :maxLen="15"></upload>
 				</el-form-item>
 				<el-form-item label="合同样本" class="hui-textarea">
-					<upload ref="contract" :list="contract" type="insert" accept=".pdf" text="上传合同"></upload>
+					<upload ref="contract" :list="contract" type="insert" accept=".pdf" text="上传合同" :maxLen="1">
+					</upload>
 				</el-form-item>
 			</el-form>
 		</div>

+ 159 - 6
virgo.wzfrontend/workark/src/components/work/serve/list/detail.vue

@@ -1,5 +1,5 @@
 <template>
-	<div class="hui-flex">
+	<div class="hui-flex serve-detail">
 		<div class="hui-flex-box">
 			<div class="hui-detail">
 				<div class="hui-detail-box">
@@ -48,6 +48,45 @@
 						</div>
 					</div>
 				</div>
+				<div class="hui-detail-box">
+					<div class="hui-detail-title">订单合同</div>
+					<div class="hui-detail-content">
+						<div class="hui-detail-item" v-if="part.contractId">
+							<div class="hui-detail-label">合同编号</div>
+							<div class="hui-detail-value">HT20250416778822</div>
+						</div>
+						<div class="hui-detail-item" v-if="part.contractId">
+							<div class="hui-detail-label">合同内容</div>
+							<div class="hui-detail-value">
+								<span class="color-primary" @click="action({
+									id:7,
+									name:'查看合同'
+								})">
+									查看合同
+								</span>
+							</div>
+						</div>
+						<div class="hui-detail-item">
+							<div class="hui-detail-label">合同状态</div>
+							<div class="hui-detail-value">
+								<el-timeline>
+									<el-timeline-item :class="timelineClass(1)" :hide-timestamp="true">
+										服务商上传合同
+									</el-timeline-item>
+									<el-timeline-item :class="timelineClass(2)" :hide-timestamp="true">
+										服务商盖章
+									</el-timeline-item>
+									<el-timeline-item :class="timelineClass(3)" :hide-timestamp="true">
+										客户盖章
+									</el-timeline-item>
+									<el-timeline-item :class="timelineClass(4)" :hide-timestamp="true">
+										签约成功
+									</el-timeline-item>
+								</el-timeline>
+							</div>
+						</div>
+					</div>
+				</div>
 				<div class="hui-detail-box">
 					<div class="hui-detail-title">订单过程</div>
 					<div class="hui-detail-content" style="padding:0;">
@@ -63,10 +102,19 @@
 				{{item.name}}
 			</el-button>
 		</div>
-		<el-dialog :close-on-click-modal="false" title="过程修改" :visible.sync="visible" width="900px"
+		<el-dialog :close-on-click-modal="false" :title="visibleTitle" :visible.sync="visible" width="900px"
 			:append-to-body="true">
-			<process-set v-if="visible" @callback="callback" :part="part" type="product" operationType="edit">
+			<process-set v-if="visible && actionType === 2" @callback="callback" :part="part" type="product"
+				operationType="edit">
 			</process-set>
+			<div v-if="visible && actionType === 5 || actionType === 6" class="hui-flex hui-content hui-dialog">
+				<select-contract ref="selectContract" v-if="visible" type="filter"></select-contract>
+				<div class="hui-dialog-submit">
+					<el-button size="small" @click="visible = false">取 消</el-button>
+					<el-button size="small" type="primary" @click="selectContract">确定</el-button>
+				</div>
+			</div>
+			<pdf-viewer v-if="visible && actionType === 7" :list="contractList" type="preview"></pdf-viewer>
 		</el-dialog>
 		<el-dialog :close-on-click-modal="false" title="支付订单" :visible.sync="dialogVisible" width="600px"
 			:append-to-body="true">
@@ -82,8 +130,16 @@
 		changeOrderStatus,
 		getOrederDetailByOrderNo
 	} from '@/api/serve'
+	import {
+		bindContract,
+		getBindContract
+	} from '@/api/finace'
+
 	const processSet = () => import('@/components/work/system/serveSet/processSet');
 	const payOrder = () => import('@/components/website/payOrder');
+	const selectContract = () => import('@/components/work/finace/contract/selectContract');
+	const pdfViewer = () => import('@/components/common/pdfViewer');
+	import config from '@/config';
 	export default {
 		props: ['detailId', 'type', 'detailType'],
 		data() {
@@ -93,7 +149,10 @@
 				visible: false,
 				reloadKey: false,
 				dialogVisible: false,
-				timeOut: null
+				timeOut: null,
+				actionType: '',
+				visibleTitle: '',
+				contractList: []
 			}
 		},
 		mounted() {
@@ -116,6 +175,7 @@
 			initSuccessFunc(res) {
 				if (res.state) {
 					this.part = res.data;
+					if (this.part.contractId) this.initBindContract();
 					if (this.detailType === 'orderNo') return;
 					this.type === 1 ? this.initCustomerRole() : this.initFacilitatorRole();
 				}
@@ -138,6 +198,16 @@
 					type: 'primary',
 					name: '确认订单'
 				});
+				if (!this.part.contractId) this.activeList.push({
+					id: 5,
+					type: 'primary',
+					name: '绑定合同'
+				});
+				// if (this.part.contractId) this.activeList.push({
+				// 	id: 6,
+				// 	type: 'warning',
+				// 	name: '修改合同'
+				// });
 			},
 			initCustomerRole() {
 				//客户
@@ -146,8 +216,36 @@
 					type: 'primary',
 					name: '立即支付'
 				})
+				if (this.part.contract) this.activeList.push({
+					id: 8,
+					type: 'warning',
+					name: '签订合同'
+				});
+			},
+			initBindContract() {
+				getBindContract(this.part.contractId).then(res => {});
+			},
+			timelineClass(type) {
+				let str = ''
+				if (!this.part.id) return str;
+				switch (type) {
+					case 1:
+						str = this.part.contractId ? 'success' : 'warning'
+						break;
+					case 2:
+						if (this.part.contractId && this.part.contractStatus === 0) str = 'warning';
+						break;
+					case 4:
+						str = 'last-timeline-item'
+						break;
+					default:
+						break;
+				}
+				return str;
 			},
 			action(item) {
+				this.actionType = item.id;
+				this.visibleTitle = item.name;
 				switch (item.id) {
 					case 1:
 						this.changePrice();
@@ -167,6 +265,16 @@
 					case 4:
 						this.dialogVisible = true;
 						break;
+					case 5:
+					case 6:
+						this.visible = true;
+						break;
+					case 7:
+						this.contractList = [{
+							url: `${window.location.origin}/${config.baseURL}/file/workarkContract/show/${this.part.contractId}`
+						}]
+						this.visible = true;
+						break;
 					default:
 						break;
 				}
@@ -201,6 +309,18 @@
 				}
 				if (done) done();
 			},
+			selectContract() {
+				if (!this.$refs.selectContract) return;
+				let data = this.$refs.selectContract.currentRow;
+				if (!data) return;
+				bindContract({
+					orderNo: this.part.orderNo,
+					contractId: data.id
+				}).then(res => {
+					this.updateOrderSuccessFunc(res);
+					this.visible = false;
+				});
+			},
 			callback(type) {
 				if (type === 'reloadKey') return this.reloadKey = !this.reloadKey;
 				this.visible = false;
@@ -224,10 +344,43 @@
 		},
 		components: {
 			processSet,
-			payOrder
+			payOrder,
+			selectContract,
+			pdfViewer
 		}
 	}
 </script>
 
-<style>
+<style lang="scss">
+	.serve-detail {
+		.el-timeline {
+			padding-top: 10px;
+			padding-left: 10px;
+
+			.success {
+				.el-timeline-item__tail {
+					border-color: $--color-success;
+				}
+
+				.el-timeline-item__node {
+					background-color: $--color-success;
+				}
+			}
+
+			.warning {
+				.el-timeline-item__tail {
+					border-color: $--color-warning;
+				}
+
+				.el-timeline-item__node {
+					background-color: $--color-warning;
+				}
+			}
+		}
+
+		.last-timeline-item {
+			padding-bottom: 0;
+		}
+
+	}
 </style>

+ 3 - 3
virgo.wzfrontend/workark/src/views/work/finance/invoiceHeader.vue

@@ -3,12 +3,12 @@
 		<div class="hui-content-title">
 			<div class="hui-title-item active">发票管理</div>
 		</div>
-		<invoice-header type="list"></invoice-header>
+		<select-invoice type="list"></select-invoice>
 	</div>
 </template>
 
 <script>
-	const invoiceHeader = () => import('@/components/work/finace/invoice/invoiceHeader');
+	const selectInvoice = () => import('@/components/work/finace/invoice/selectInvoice');
 	export default {
 		data() {
 			return {}
@@ -16,7 +16,7 @@
 		mounted() {},
 		methods: {},
 		components: {
-			invoiceHeader
+			selectInvoice
 		}
 	}
 </script>

+ 6 - 86
virgo.wzfrontend/workark/src/views/work/finance/organizationContract.vue

@@ -3,100 +3,20 @@
 		<div class="hui-content-title">
 			<div class="hui-title-item active">企业合同</div>
 		</div>
-		<div class="hui-flex-box hui-flex hui-table">
-			<div class="hui-content-insert">
-				<el-button type="primary" size="small" @click="upload()">上传合同</el-button>
-				<contract-upload ref="upload" v-show="false" :contractId="contractId" type="project" @reload="init">
-				</contract-upload>
-			</div>
-			<div class="hui-flex-box">
-				<el-table ref="elTable" :data="tableData" height="100%" v-loading="loading">
-					<el-table-column prop="name" label="合同名称">
-					</el-table-column>
-					<el-table-column prop="createDate" label="创建时间">
-					</el-table-column>
-					<el-table-column prop="updateDate" label="更新时间">
-					</el-table-column>
-					<el-table-column label="操作" width="180" align="center">
-						<template slot-scope="scope">
-							<div class="hui-table-operation">
-								<span class="table-operation" @click="previewItem(scope.row)">预览</span>
-								<span class="table-operation" @click="upload(scope.row.id)">更新</span>
-								<span class="table-operation" @click="deleteItem(scope.row.id)">删除</span>
-							</div>
-						</template>
-					</el-table-column>
-					<template slot="empty">
-						<el-empty description="暂无数据"></el-empty>
-					</template>
-				</el-table>
-			</div>
-		</div>
-		<el-dialog :close-on-click-modal="false" title="预览合同" :visible.sync="dialogVisible" width="900px"
-			:append-to-body="true">
-			<pdf-viewer v-if="dialogVisible" :list="contractList" type="preview">
-			</pdf-viewer>
-		</el-dialog>
+		<select-contract type="list"></select-contract>
 	</div>
 </template>
 
 <script>
-	import {
-		getOrganizationContract,
-		deleteOrganizationContract
-	} from '@/api/finace'
-	const contractUpload = () => import('@/components/work/finace/contract/contractUpload');
-	const pdfViewer = () => import('@/components/common/pdfViewer');
-	import config from '@/config';
+	const selectContract = () => import('@/components/work/finace/contract/selectContract');
 	export default {
 		data() {
-			return {
-				tableData: [],
-				loading: false,
-				contractList: [],
-				contractId: '',
-				dialogVisible: false
-			}
-		},
-		mounted() {
-			this.init();
-		},
-		methods: {
-			init(type) {
-				this.loading = true;
-				getOrganizationContract(this.$store.getters.organization.id).then(res => {
-					this.loading = false;
-					if (res.state) {
-						this.tableData = res.data;
-					}
-				})
-			},
-			upload(id) {
-				this.contractId = id;
-				this.$nextTick(() => {
-					this.$refs.upload.reloadUpload();
-				})
-			},
-			previewItem(item) {
-				this.contractList = [{
-					url: window.location.origin + '/' + config.baseURL + '/file/workarkContract/pdf/' + item.id
-				}]
-				this.dialogVisible = true;
-			},
-			deleteItem(id) {
-				this.$confirm('确定要删除合同?', () => {
-					deleteOrganizationContract(id).then(res => {
-						if (res.state) {
-							this.$message.success('操作成功');
-							this.init();
-						}
-					})
-				});
-			}
+			return {}
 		},
+		mounted() {},
+		methods: {},
 		components: {
-			contractUpload,
-			pdfViewer
+			selectContract
 		}
 	}
 </script>