Browse Source

feat(contract): 添加合同webview页面并优化PDF查看功能

- 新增合同webview页面用于展示合同内容
- 优化PDF查看功能,支持直接打开PDF文件
- 添加无合同模板时的提示信息
- 调整合同上传的文件类型检查逻辑
master
前端-胡立永 2 months ago
parent
commit
8913445660
5 changed files with 307 additions and 213 deletions
  1. +3
    -0
      pages.json
  2. +6
    -0
      pages/index/consult.vue
  3. +243
    -210
      pages_order/contract/contract.vue
  4. +38
    -3
      pages_order/contract/contractManageEdit.vue
  5. +17
    -0
      pages_order/contract/webview.vue

+ 3
- 0
pages.json View File

@ -187,6 +187,9 @@
{
"path": "contract/contractDetail"
},
{
"path": "contract/webview"
},
{
"path": "contract/contract",
"style": {


+ 6
- 0
pages/index/consult.vue View File

@ -83,6 +83,12 @@
flex-shrink: 0;
}
.info{
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
.title{
font-weight: 900;
}


+ 243
- 210
pages_order/contract/contract.vue View File

@ -1,221 +1,254 @@
<template>
<!-- 电子合同 -->
<view>
<navbar title="电子合同"
leftClick
@leftClick="$utils.navigateBack"/>
<view class="">
<uv-tabs :list="tabs"
lineColor="#3796F8"
lineHeight="8rpx"
lineWidth="50rpx"
:scrollable="false"
@click="clickTabs"></uv-tabs>
</view>
<view class="content">
<view class="projectContent" v-for="(item, index) in list" :key="index">
<view class="item">
<image src="/static/image/contract/contract.png" mode="aspectFill"/>
<view class="itemList">
<view class="projectName">
{{ item.title }}
<text class="status" :class="{
'status-pending': role ? item.bossStatus === 0 : item.employeeStatus === 0,
'status-signed': role ? item.bossStatus === 1 : item.employeeStatus === 1,
'status-completed': role ? item.bossStatus === 2 : item.employeeStatus === 2
}">
{{ role ?
(item.bossStatus === 0 ? '待签署' : item.bossStatus === 1 ? '已签署' : '已完成') :
(item.employeeStatus === 0 ? '待签署' : item.employeeStatus === 1 ? '已签署' : '已完成')
}}
</text>
</view>
<view class="buyer">甲方{{ item.companyName }}</view>
<view class="seller">乙方{{ item.employeeName }}</view>
</view>
<view class="actions">
<view class="view-btn" @click="showPDF(item)">
<uv-icon name="eye" color="#2979ff" size="30rpx"></uv-icon>
<text>查看</text>
</view>
<view class="sign-btn"
v-if="(role && item.bossStatus === 0) || (!role && item.employeeStatus === 0)"
@click.stop="$utils.navigateTo('/pages_order/contract/electronicSignature?id=' + item.id)">
<uv-icon name="edit-pen" color="#fff" size="30rpx"></uv-icon>
<text>签署</text>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 电子合同 -->
<view>
<navbar title="电子合同" leftClick @leftClick="$utils.navigateBack" />
<view class="">
<uv-tabs :list="tabs" lineColor="#3796F8" lineHeight="8rpx" lineWidth="50rpx" :scrollable="false"
@click="clickTabs"></uv-tabs>
</view>
<view class="content">
<view class="projectContent" v-for="(item, index) in list" :key="index">
<view class="item">
<image src="/static/image/contract/contract.png" mode="aspectFill" />
<view class="itemList">
<view class="projectName">
{{ item.title }}
<text class="status" :class="{
'status-pending': role ? item.bossStatus === 0 : item.employeeStatus === 0,
'status-signed': role ? item.bossStatus === 1 : item.employeeStatus === 1,
'status-completed': role ? item.bossStatus === 2 : item.employeeStatus === 2
}">
{{ role ?
(item.bossStatus === 0 ? '待签署' : item.bossStatus === 1 ? '已签署' : '已完成') :
(item.employeeStatus === 0 ? '待签署' : item.employeeStatus === 1 ? '已签署' : '已完成')
}}
</text>
</view>
<view class="buyer">甲方{{ item.companyName }}</view>
<view class="seller">乙方{{ item.employeeName }}</view>
</view>
<view class="actions">
<view class="view-btn" @click="showPDF(item)">
<uv-icon name="eye" color="#2979ff" size="30rpx"></uv-icon>
<text>查看</text>
</view>
<view class="sign-btn"
v-if="(role && item.bossStatus === 0) || (!role && item.employeeStatus === 0)"
@click.stop="$utils.navigateTo('/pages_order/contract/electronicSignature?id=' + item.id)">
<uv-icon name="edit-pen" color="#fff" size="30rpx"></uv-icon>
<text>签署</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import mixinList from '@/mixins/list.js'
import { mapState } from 'vuex'
export default {
mixins : [mixinList],
data() {
return {
tabs: [
{
name: '全部合同'
},
{
name: '待我签署'
},
{
name: '他人签署'
},
{
name: '签约完成'
},
],
type : 0,
mixinsListApi : 'queryContractList',
}
},
computed : {
},
onLoad() {
this.queryParams.role = this.role ? 1 : 0
},
methods: {
clickTabs({index}) {
this.type = index
if(index == 0){
delete this.queryParams.status
}
this.queryParams.status = index
this.getData()
},
showPDF(item){
// this.$utils.
// navigateTo('/pages_order/contract/contractDetail?id='
// + item.id)
//
if(this.role && item.bossStatus != 0 ||
item.employeeStatus != 0 && !this.role
){
uni.downloadFile({
url : item.contract,
success : res => {
uni.openDocument({
filePath: res.tempFilePath,
})
}
})
return
import mixinList from '@/mixins/list.js'
import { mapState } from 'vuex'
export default {
mixins: [mixinList],
data() {
return {
tabs: [
{
name: '全部合同'
},
{
name: '待我签署'
},
{
name: '他人签署'
},
{
name: '签约完成'
},
],
type: 0,
mixinsListApi: 'queryContractList',
contractUrl : '',
}
},
computed: {
},
onLoad() {
this.queryParams.role = this.role ? 1 : 0
},
methods: {
clickTabs({ index }) {
this.type = index
if (index == 0) {
delete this.queryParams.status
}
this.queryParams.status = index
this.getData()
},
openPDF() {
console.log(uni.getSystemInfoSync().platform);
switch (uni.getSystemInfoSync().platform) {
// case "android":
// console.log("");
// this.androidOpenPdf(this.contractUrl);
// break;
// case "ios":
// console.log("IOS");
// uni.navigateTo({
// url: "/pages_order/contract/webview?contractUrl=" + this.contractUrl,
// });
// break;
default:
this.androidOpenPdf(this.contractUrl);
break;
}
},
androidOpenPdf(filePath){
uni.downloadFile({
url: filePath,
success: res => {
console.log('下载PDF成功');
uni.openDocument({
filePath : res.filePath || res.tempFilePath,
showMenu: true,
})
},
fail(err) {
console.log(err);
}
uni.showModal({
title: '您希望的操作是?!',
cancelText: '签署合同',
confirmText: '查看内容',
success : e => {
if(e.confirm){
uni.downloadFile({
url : item.contract,
success : res => {
uni.openDocument({
filePath: res.tempFilePath,
})
}
})
}else{
this.$utils.
navigateTo('/pages_order/contract/electronicSignature?id='
+ item.id)
}
}
})
},
}
}
})
},
showPDF(item) {
// this.$utils.
// navigateTo('/pages_order/contract/contractDetail?id='
// + item.id)
this.contractUrl = item.contract
//
if (this.role && item.bossStatus != 0 ||
item.employeeStatus != 0 && !this.role
) {
this.openPDF()
return
}
uni.showModal({
title: '您希望的操作是?!',
cancelText: '签署合同',
confirmText: '查看内容',
success: e => {
if (e.confirm) {
this.openPDF()
} else {
this.$utils.
navigateTo('/pages_order/contract/electronicSignature?id='
+ item.id)
}
}
})
},
}
}
</script>
<style scoped lang="scss">
.content {
width: 100%;
height: 100%;
.projectContent {
background-color: #fff;
display: flex;
margin: 30rpx;
border-radius: 20rpx;
.item{
display: flex;
width: 100%;
padding: 20rpx;
image {
width: 140rpx;
height: 120rpx;
margin-right: 20rpx;
}
.itemList {
flex: 1;
.projectName {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 16rpx;
display: flex;
align-items: center;
.status {
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
margin-left: 16rpx;
&.status-pending {
background-color: #E6F7FF;
color: #1890FF;
}
&.status-signed {
background-color: #F6FFED;
color: #52C41A;
}
&.status-completed {
background-color: #F5F5F5;
color: #666666;
}
}
}
.buyer, .seller {
font-size: 24rpx;
color: #666;
margin-top: 8rpx;
}
}
.actions {
display: flex;
flex-direction: column;
justify-content: center;
gap: 16rpx;
.view-btn, .sign-btn {
display: flex;
align-items: center;
padding: 12rpx 24rpx;
border-radius: 30rpx;
background-color: #F0F7FF;
text {
color: #2979ff;
font-size: 24rpx;
margin-left: 8rpx;
}
}
.sign-btn {
background-color: #2979ff;
text, uv-icon {
color: #fff;
}
}
}
}
}
width: 100%;
height: 100%;
.projectContent {
background-color: #fff;
display: flex;
margin: 30rpx;
border-radius: 20rpx;
.item {
display: flex;
width: 100%;
padding: 20rpx;
image {
width: 140rpx;
height: 120rpx;
margin-right: 20rpx;
}
.itemList {
flex: 1;
.projectName {
font-size: 32rpx;
font-weight: bold;
margin-bottom: 16rpx;
display: flex;
align-items: center;
.status {
font-size: 24rpx;
padding: 4rpx 16rpx;
border-radius: 20rpx;
margin-left: 16rpx;
&.status-pending {
background-color: #E6F7FF;
color: #1890FF;
}
&.status-signed {
background-color: #F6FFED;
color: #52C41A;
}
&.status-completed {
background-color: #F5F5F5;
color: #666666;
}
}
}
.buyer,
.seller {
font-size: 24rpx;
color: #666;
margin-top: 8rpx;
}
}
.actions {
display: flex;
flex-direction: column;
justify-content: center;
gap: 16rpx;
.view-btn,
.sign-btn {
display: flex;
align-items: center;
padding: 12rpx 24rpx;
border-radius: 30rpx;
background-color: #F0F7FF;
text {
color: #2979ff;
font-size: 24rpx;
margin-left: 8rpx;
}
}
.sign-btn {
background-color: #2979ff;
text,
uv-icon {
color: #fff;
}
}
}
}
}
}
</style>

+ 38
- 3
pages_order/contract/contractManageEdit.vue View File

@ -7,6 +7,11 @@
</view>
<view style="padding: 25rpx;background-color: #fff;">
<!-- 没有模板时的提示 -->
<view v-if="!form.template || imageArr.length === 0" class="no-template-tip">
<text>请先点击"导入合同"按钮上传PDF合同模板</text>
</view>
<canvas-drag ref="canvasRef"
id="canvas-drag" :graph="graph"
:width="width" :height="height"
@ -310,10 +315,25 @@
uni.chooseMessageFile({
count: 1, //
type: 'file',
extension: ['.pdf'], //
// extension
success(res) {
// that.$Oss.ossUpload(res.tempFiles[0].path)
success(that.$Oss.ossUpload(res.tempFiles[0].path))
const file = res.tempFiles[0]
const fileName = file.name || ''
const fileExtension = fileName.toLowerCase().split('.').pop()
//
if (fileExtension !== 'pdf') {
uni.showToast({
title: '只能上传PDF文件,请重新选择',
icon: 'none',
duration: 3000
})
error(new Error('文件类型不正确'))
return
}
//
success(that.$Oss.ossUpload(file.path))
},
fail: (err) => {
error(err)
@ -453,6 +473,21 @@
border-radius: 10rpx;
}
}
.no-template-tip {
display: flex;
align-items: center;
justify-content: center;
height: 300rpx;
background-color: #f8f9fa;
border: 2rpx dashed #ddd;
border-radius: 10rpx;
margin-bottom: 20rpx;
text {
color: #999;
font-size: 28rpx;
text-align: center;
}
}
.btn-list {
display: flex;
flex-wrap: wrap;


+ 17
- 0
pages_order/contract/webview.vue View File

@ -0,0 +1,17 @@
<template>
<view id="web-info">
<web-view :src="src"></web-view>
</view>
</template>
<script>
export default {
data() {
return {
src: '',
}
},
onLoad(option) {
this.src = option.contractUrl
}
}
</script>

Loading…
Cancel
Save