Files
jjx-wap/pages/public/contract.vue
T
b2894lxlx c8e651b7a6 fix: 支付去掉货到付款,样式穿透改为 ::v-deep
支付单改为上传凭证和附件,尾款或全款时提示交易已完结。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-19 14:20:52 +08:00

681 lines
25 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template> <!-- 合同管理 -->
<view class="wrap">
<!-- 吸顶 -->
<u-sticky offset-top="0" customNavHeight="0">
<!-- 顶部 -->
<uititle title="合同管理"></uititle>
<!-- 选项卡 -->
<view class="layout layout-tab flex justify-between align-center">
<view :class="['tab', {active: tabIndex == 0}]" @click="handTab(0)">待创建</view>
<view :class="['tab', {active: tabIndex == 1}]" @click="handTab(1)">待签署</view>
<view :class="['tab', {active: tabIndex == 2}]" @click="handTab(2)">已完成</view>
<!-- <view :class="['tab', {active: tabIndex == 3}]" @click="handTab(3)">已作废</view>-->
</view>
<u-subsection :list="signTypeList" :current="subsection" keyName="label" active-color="#A92924"
@change="changeSubsection"/>
</u-sticky>
<view>
<u-subsection :list="signTypeFilterList" :current="signTypeFilter" keyName="label" active-color="#A92924"
@change="changeSignTypeFilter" v-if="tabIndex == 2"/>
<u-search bg-color="#FFFFFF" v-model="keyword" placeholder="输入签约方关键字搜索" @blur="query(1)" @custom="query(1)"></u-search>
</view>
<view class="layout layout-contract">
<view class="item" v-for="(item, index) in tableData.rows" :key="index">
<view class="title text-single m-right-20">
<text v-if="item.contract.status > 0">{{ item.contract.docTitle }}</text>
<text v-else-if="item.contract.status === 0 && item.sheet">{{ item.sheet.title }}</text>
</view>
<view class="flex justify-start align-center mt-15">
<template v-if="item.sheet">
<view class="mr-10">
<u-tag plain text="自主交易" size="mini" v-if="item.sheet.tradeMethod === 0" type="primary"
>
</u-tag>
<u-tag plain text="金久信公证" size="mini"
v-if="item.sheet.tradeMethod === 1 && item.contract.type !== 'sign'"
type="success">
</u-tag>
</view>
<view class="mr-10">
<u-tag plain text="标准合同" size="mini" effect="plain" v-if="item.sheet.signMethod === 0"
type="success">
</u-tag>
<u-tag plain text="双方协商合同" size="mini" effect="plain"
v-if="item.sheet.signMethod === 2"
type="primary">
</u-tag>
<u-tag plain text="线下合同" size="mini" effect="plain" v-if="item.sheet.signMethod === 1"
type="warning">
</u-tag>
</view>
</template>
<u-tag plain text="金久信公证" size="mini"
v-if="item.contract.tradeMethod === 1 && item.contract.type === 'sign'" class="mr-10"
type="success">
</u-tag>
<u-tag type="primary" v-if="item.contract.type === 'enquiry'" text="询价单" size="mini"
class="mr-10"/>
<u-tag type="success" v-else-if="item.contract.type === 'process'" text="加工单" size="mini"
class="mr-10"/>
<u-tag type="success" v-else-if="item.contract.type === 'sign'" text="金久信签约宝" size="mini"
class="mr-10"/>
<u-tag type="primary" v-else-if="item.contract.type === 'old'" text="旧货交易" size="mini"
class="mr-10"/>
<u-tag type="errpr" v-else-if="item.contract.type === 'self-support'" text="自营询价" size="mini"
class="mr-10"/>
<view v-if="item.contract.status === 1" class="flex justify-start items-center flex-wrap">
<view class="justify-start items-center flex-wrap"
v-for="(party, pIndex) in item.contract.partyList" :key="pIndex">
<u-tag size="mini" class="mr-10 ml-10"
v-if="party.userId !== userInfo._id && !party.sign && party.role !== 'third'" plain
type="error" text="待交易方签署"/>
<u-tag size="mini" class="mr-10 ml-10"
v-if="party.userId !== userInfo._id && !party.sign && party.role === 'third'" plain
type="error" text="待第三方签署"/>
<u-tag size="mini" class="mr-10 ml-10" v-if="party.userId === userInfo._id && !party.sign"
plain
type="primary" text="待我签署"/>
</view>
</view>
<view v-if="item.order" class="text-main text-25">
(订单状态:{{
item.order.orderStatus === 4 ? '已完成' : ([5, 6].includes(item.order.orderStatus) ? '订单终止' : '执行中')
}})
</view>
<!-- <view class="flex-1"></view>-->
<!-- <view class="date">2023-04-27到期,过期将无法签署</view>-->
</view>
<view class="sm m-top-20 flex flex-col justify-start items-start">
<text class="m-right-20">合同编码:{{ item.contract.transactionId }}</text>
<text class="m-right-20" v-if="item.sheet && item.contract.type !== 'old'">交易编码:{{
item.contract.type === 'enquiry' ? item.sheet.enquiryNo : item.sheet.orderNo
}}
</text>
<text class="m-right-20">创建时间:{{ item.contract._add_time_str }}</text>
<template v-if="parseInt(item.contract.status) > 0">
<text v-for="(party, partyIndex) in item.contract.partyList " :key="partyIndex">
<template v-if="party.role !== 'third'">
<template v-if="party.userId === item.contract.userId">
发起方签订完成时间:{{
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
}}
</template>
<template v-if="party.userId !== item.contract.userId">
接收方签订完成时间:{{
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
}}
</template>
</template>
<template v-if="party.role === 'third'">
第三方签订完成时间:{{
party.signedAt ? dayjs(party.signedAt).format('YYYY-MM-DD HH:mm:ss') : ''
}}
</template>
</text>
</template>
<view v-if="item.contract.signEndDate">
<text>签订截止时间:{{
dayjs(item.contract.signEndDate).format('YYYY-MM-DD HH:mm:ss')
}}</text>
<text class="text-red ml-20" v-if="item.contract.signCount === 0">{{ dayjs(item.contract.signEndDate).isBefore(dayjs()) ? '已超时限' : '' }}</text>
</view>
<view v-if="item.contract.type === 'sign' && item.contract.payUser && item.contract.payUser.user">
费用承担方:{{
item.contract.payUser.user.accountType === 2 ?
item.contract.payUser.user.company.companyName : item.contract.payUser.user.person.personName
}}
</view>
</view>
<view class="flex justify-start align-center m-top-20">
<view class="op flex justify-start align-center m-right-30" @click="showParty(item)">
<u-icon name="chat" color="#A92924" size="18"></u-icon>
<text class="op-text m-left-10">查看交易方</text>
</view>
</view>
<view class="mt-20 flex justify-start align-center">
<view class="op flex justify-start align-center"
v-if="item.contract.status === 0 && item.contract.userId === userInfo._id"
@click="createContract(item.contract)">
<u-icon name="plus-circle" color="#A92924" size="18"></u-icon>
<text class="op-text m-left-10">创建合同</text>
</view>
<view class="mr-10">
<u-button @click.native="changeContract(item.contract)" custom-style="padding: 0"
v-if="((item.sheet && item.sheet.signMethod === 2) || item.contract.type === 'sign' || item.contract.type === 'self-support')
&& item.contract.status === 1
&& item.contract.userId === userInfo._id && item.contract.signCount === 0"
size="mini" type="primary">修改合同内容
</u-button>
</view>
<view class="ml-10">
<u-button custom-style="padding: 0" v-if="item.contract.userId === userInfo._id"
@click="delContract(item.contract)" size="mini" type="text">
删除合同
</u-button>
</view>
<template v-if="parseInt(item.contract.status) === 1 && dayjs(item.contract.signEndDate).isAfter(dayjs())">
<view class="ml-10">
<u-button @click="extSign(item.sign, item.contract)" size="mini" type="primary"
:disabled="item.sign">
{{ item.sign ? '已签署' : '签署文件' }}
</u-button>
</view>
</template>
<template v-if="parseInt(item.contract.status) === 2">
<view class="ml-10">
<u-button custom-style="padding: 0"
@click="viewContract(item.contract)"
size="mini" plain>
{{ parseInt(item.contract.signType) === 1 ? '查看单据' : '查看合同' }}
</u-button>
</view>
<view class="ml-10">
<u-button custom-style="padding: 0" @click="downloadContract(item.contract.transactionId)" type="success"
size="mini" plain>
{{ parseInt(item.contract.signType) === 1 ? '下载单据' : '下载合同' }}
</u-button>
</view>
<view class="ml-10">
<u-button @click="payDownloadContract(item.contract)" type="primary" custom-style="padding: 0"
size="mini" plain>
{{
parseInt(item.contract.signType) === 1 ? '下载单据(付费司法调证)' : '下载合同(付费司法调证)'
}}
</u-button>
</view>
</template>
<view class="ml-10">
<u-button custom-style="padding: 0"
v-if="item.order && parseInt(item.contract.status) === 2 && ((item.sheet && item.sheet.tradeMethod === 1) || item.contract.tradeMethod === 1)"
@click="$jump(`/pages/shop/order?menuIndex=${item.role === 'buyer' ? 1 : 0}&keyword=${item.order.orderNo}`)"
size="mini"
:type="(item.order && item.order.orderStatus > 4) ? 'info' :'success'">
{{
(item.order && item.order.orderStatus === 4) ? '订单已结束' : ([5, 6].includes(item.order.orderStatus) ? '订单已终止' : (item.role === 'buyer' ? '去付款' : '去请款'))
}}
</u-button>
</view>
<view class="ml-10">
<u-button custom-style="padding: 0"
v-if="item.contract.otherFile && item.contract.otherFile.length > 0"
@click="openDownload(item.contract.otherFile)" plain
size="mini"
type="info">查看附件
</u-button>
</view>
</view>
</view>
</view>
<!-- 没有数据 u-empty是框架组件 cmempty是自己封装组件 -->
<u-empty mode="list" text="暂无更多内容~"></u-empty>
<!-- <cmempty></cmempty> -->
<u-popup :show="show" mode="center" @close="show = false" closeable close-on-click-overlay
:custom-style="{width: '90%'}">
<view class="p-30">
<view class="mb-10">名称:{{ title }}</view>
<view class="mb-10">联系人:{{ name }}</view>
<view class="mb-10">联系方式:{{ companyMobile }}</view>
</view>
</u-popup>
<contact-modal ref="contactModal"/>
<u-modal :show="showPartyModal" title="交易方" @confirm="showPartyModal = false">
<u-parse :content="partyContent"></u-parse>
</u-modal>
</view>
</template>
<script>
import uititle from '@/components/common/title'
import cmsearch from '@/components/common/search'
import cmempty from '@/components/common/empty'
import dayjs from "dayjs";
import ContactModal from "@/components/ContactModal.vue";
import {Loading} from "element-ui";
const SIGN_CONFIRM_CONTENT = `1、您确认,若全体各签约方未完成全部签约流程,本签约文件不发生法律效力,系统无法对该签约文件予以保存及提供司法调证服务;
2、您确认,当前签约的实名主体名称、手机号码与注册认证阶段提交的信息未发生变更;若发生变更,必须及时进行重新认证后方可继续签约,避免产生严重法律风险与经济损失;
3、您确认,本次签约为本系统实名认证主体操作,如若不是实名认证主体操作,授权委托人需本系统进行授权认证后签约;
4、您确认,您与其他签约方均系在平等、自愿的基础上完成本次签约;
5、你确认,此次签约内容符合《中华人民共和国电子签名法》《民法典》生效保护范畴;
6、如因法律法规、监管部门政策更新等原因,系统提示您重新进行实名认证、证书续期等重要提示时,请您必须在签约前完成,否则造成任何损失,平台不承担任何责任;以上签约条件您均已经知悉并确认,否则您有权拒绝本次签约。`
export default {
components: {
ContactModal,
uititle,
cmsearch,
cmempty,
},
data() {
return {
tabIndex: 0,
tableData: {},
userInfo: null,
show: false,
title: '',
name: '',
companyMobile: '',
signTypeList: [
{
tradeMethod: null,
type: null,
label: '全部'
},
{
tradeMethod: 0,
type: null,
label: '自主交易'
},
{
tradeMethod: 1,
type: null,
label: '金久信公正'
},
{
tradeMethod: null,
type: 'sign',
label: '金久信签约宝'
},
],
subsection: 0,
signTypeFilterList: [
{
value: '2',
label: '合同签约'
},
{
value: '1',
label: '单据签约'
},
],
signTypeFilter: 0,
keyword: '',
numToChForThird: ['三', '四', '五', '六', '七', '八', '九', '十'],
showPartyModal: false,
partyContent: ''
}
},
methods: {
dayjs,
handTab(index) {
this.tabIndex = index
this.query(1)
},
detailLink(val) {
vk.navigateTo('/pages/public/create')
},
menuSelect(e) {
this.menuIndex = String(e)
this.formData.status = Number(e)
this.isSign = false
this.query(1)
},
selectSign() {
this.isSign = true
this.menuIndex = ''
},
changeSubsection(index) {
this.subsection = index
this.query(1)
},
changeSignTypeFilter(index) {
this.signTypeFilter = index
this.query(1)
},
async query(pageIndex) {
this.tableData = await vk.callFunction({
url: 'client/contract/kh/getList',
title: '请求中...',
data: {
pageIndex,
pageSize: 500,
status: this.tabIndex,
tradeMethod: this.signTypeList[this.subsection].tradeMethod,
type: this.signTypeList[this.subsection].type,
keyword: this.keyword,
signType: this.signTypeFilter === 1 ? '1' : '2',
},
});
this.$forceUpdate()
},
/**
* 创建合同
* @param contract
*/
createContract(contract) {
// this.form1.contractId = contract._id
this.$jump(`/pages/public/create?contractId=${contract._id}`)
},
async changeContract(contract) {
this.$jump(`/pages/public/create?contractId=${contract._id}`)
},
onFormSuccess() {
this.form1.props.show = false
// this.form1.data.contractId = null
// this.formData.status = 1
// this.menuIndex = '1'
// this.isSign = false
// this.$refs.form2.resetForm()
// this.$refs.form1.resetForm()
// this.query(1)
vk.redirectTo({url: '/pages/contract/index?tab=1'})
},
/**
* 签署合同
* @param sign
* @param contract
*/
extSign(sign, contract) {
if (sign) return
uni.showModal({
title: '提示',
content: SIGN_CONFIRM_CONTENT,
showCancel: false,
confirmText: '知悉同意',
success: (confirmRes) => {
if (confirmRes.confirm) {
vk.callFunction({
url: 'client/contract/kh/extSign',
title: '请求中...',
data: {
contractId: contract._id,
isWap: true
},
success: (res) => {
window.location.href = res.data
// window.open(res.data)
}
});
}
}
});
},
showStopSign(contract) {
vk.callFunction({
url: 'client/contract/kh/extSign',
title: '请求中...',
data: {
contractId: contract._id
},
success: (res) => {
// window.open(res.data)
window.location.href = res.data
}
});
},
viewContract(contract) {
vk.callFunction({
url: 'client/contract/kh/viewContract',
title: '请求中...',
data: {
contractId: contract._id
},
success: (res) => {
window.location.href = res.data
// window.open(res.data)
this.query(1)
}
});
},
navTo(url) {
vk.navigateTo({
url: url
})
},
showParty(userContract) {
// let content = ''
// userContract.contract.partyList.forEach(party => {
// // if (party.userId !== userContract.userId) partyUser = party.user
// const partyUser = party.user
// if (partyUser) {
// const name = partyUser.nickname
// let role = party.role === 'buyer' ? '购买方' : '销售方'
// if (party.role === 'third') role = '第三方'
// content += `<view class="flex flex-col justify-start items-start py-10 border-bottom">
// <view>身份:${role}</view>
// <view>联系人:${name}</view>
// <view>联系方式:${partyUser.mobile}</view></view>`
// }
// })
let content = ''
const buyer = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract.userId === item.userId)
const seller = userContract.contract.partyList.find(item => item.role !== 'third' && userContract.contract.userId !== item.userId)
const thirdList = userContract.contract.partyList.filter(item => item.role === 'third')
content += `<div class="flex flex-col justify-start items-start py-10 border-bottom">
<div>身份:发起方</div>
<div>联系人:${buyer.user.nickname}</div>
<div>联系方式:${buyer.user.mobile}</div></div>`
content += `<div class="flex flex-col justify-start items-start py-10 border-bottom">
<div>身份:接收方</div>
<div>联系人:${seller.user.nickname}</div>
<div>联系方式:${seller.user.mobile}</div></div>`
thirdList.forEach((item, index) => {
console.log(item)
content += `<div class="flex flex-col justify-start items-start py-10 border-bottom">
<div>身份:第${this.numToChForThird[index]}方</div>
<div>联系人:${item.user.nickname}</div>
<div>联系方式:${item.user.mobile}</div></div>`
})
// this.$confirm(content, '', {
// cancelButtonText: '关闭',
// showConfirmButton: false,
// dangerouslyUseHTMLString: true
// })
this.partyContent = content
this.showPartyModal = true
},
changeTradeMethod(tradeMethod) {
this.formData.tradeMethod = tradeMethod
this.formData.type = null
this.query(1)
},
changeType(type) {
this.formData.tradeMethod = null
this.formData.type = type
this.query(1)
},
openDownload(otherFile) {
for (let file in otherFile) {
// window.open(otherFile)
window.location.href = otherFile
}
},
async getCommonContractUrl() {
const res = await vk.callFunction({
url: 'client/dict/pub/getDetail',
data: {
id: '657d36befe975f63af1f24e7'
},
})
this.contractTemplate = res.content
},
downloadContractTemplate() {
// window.open(this.contractTemplate)
window.location.href = this.contractTemplate
},
async delContract(contract) {
uni.showModal({
title: '温馨提示',
content: '请您确认文件无用或已经完成履约后再删除文件,删除后平台将无法为您提供相关数据,您将无法查询已经删除文件。请您谨慎操作。',
success: async res => {
if (res.confirm) {
await vk.callFunction({
url: 'client/contract/kh/del',
data: {
id: contract._id
},
success: (res) => {
this.query(1)
}
})
}
}
})
},
async payDownloadContract(contract) {
const amountRes = await vk.callFunction({
url: 'client/dict/pub/getDetail',
data: {
id: 'ded3e568662e5817000026633aad1e69'
},
})
if (!contract.canDownloadUidList || !contract.canDownloadUidList.includes(this.userInfo.uid)) {
if (contract.certificate && !contract.certificate.paidConfirm) {
if (contract.certificate.paymentMethod === 'online') {
return vk.navigateTo({
url: `/pages/shop/pay?id=${contract.certificate.orderId}`
})
}else return vk.toast('请先等待后台确认支付')
}
vk.navigateTo({
url: `/pages/public/certificate?contractId=${contract._id}&transactionId=${contract.transactionId}&amount=${amountRes.content}`
})
} else {
uni.showModal({
title: '温馨提示',
content: '您提交申请后,平台将在两个工作日内向您提供合法生效文件,客服电话:400-686-5559',
success: async res => {
if (res.confirm) {
if (contract.certificate) {
if (contract.certificate.deliveryMethods.paper) {
vk.toast('您的司法调证文件已发货,请注意查收')
} else {
if (contract.certificate.downloadUrl) window.open(contract.certificate.downloadUrl)
else vk.toast('文件生成中,请耐心等待')
}
} else vk.toast('操作失败,请联系客服')
}
}
})
}
},
async downloadContract(contract_id) {
let loadingInstance1 = Loading.service({fullscreen: true, text: '加载中...'});
const res = await vk.callFunction({
url: 'client/contract/pub/getDownload',
data: {
contract_id
}
});
loadingInstance1.close()
if (res) {
// window.open(`https://textapi.fadada.com/api2/downLoadContract.api?app_id=502704&timestamp=${res.data.timestamp}&v=2.0&msg_digest=${res.data.msg_digest}&contract_id=${contract_id}`)
window.location.href = `https://textapi.fadada.com/api2/downLoadContract.api?app_id=502704&timestamp=${res.data.timestamp}&v=2.0&msg_digest=${res.data.msg_digest}&contract_id=${contract_id}`
}
},
},
onLoad(option) {
if (option.tab) this.tabIndex = parseInt(option.tab)
this.userInfo = vk.getStorageSync('uni_id_user_info')
this.query(1)
},
}
</script>
<style lang="scss">
page {
background: #ffffff;
}
::v-deep .u-tag--mini {
padding: 0 1px !important;
}
.layout-tab {
height: 100rpx;
padding: 0 30rpx;
background: #f1f1f1;
.tab {
margin: 0 20rpx;
padding: 10rpx 0rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #666666;
}
.active {
position: relative;
color: #A92924;
&::after {
position: absolute;
left: 0;
bottom: 0;
z-index: 9;
content: '';
width: 100%;
height: 1px;
background: #A92924;
}
}
}
.layout-contract {
padding: 10rpx 30rpx;
.item {
padding: 30rpx 0rpx;
border-bottom: 1px solid #f2f2f2;
&:last-child {
border-bottom: none;
}
.sm {
font-size: 24rpx;
line-height: 40rpx;
color: #999999;
}
.title {
//max-width: 300rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #101010;
}
}
.tag {
display: inline-block;
padding: 0 10rpx;
height: 36rpx;
font-size: 22rpx;
line-height: 36rpx;
color: #A92924;
text-align: center;
background-color: rgba(169, 41, 36, 0.13);
}
.date, .op-text {
font-size: 24rpx;
line-height: 40rpx;
color: #A92924;
}
.xiugai {
width: 130rpx;
height: 44rpx;
font-size: 24rpx;
line-height: 44rpx;
color: #ffffff;
text-align: center;
background: #A92924;
}
}
.trade-method-item {
cursor: pointer;
font-size: 25rpx;
margin-right: 15rpx;
line-height: 40rpx;
}
</style>