智慧教务系统
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.
 
 
 
 
 
 

239 lines
7.1 KiB

<!--合同列表页面-->
<template>
<view class="contract-list" style="background-color: #181A20; min-height: 100vh;">
<!-- 顶部统计 -->
<view class="stats-section" style="background-color: #181A20; padding: 20rpx;">
<view class="stats-card" style="background-color: #2A2A2A; border-radius: 12rpx; padding: 30rpx;">
<view class="stats-row">
<view class="stats-item">
<text class="stats-number" style="color: rgb(41, 211, 180); font-size: 36rpx; font-weight: bold;">{{ stats.total }}</text>
<text class="stats-label" style="color: #fff; font-size: 24rpx;">总合同</text>
</view>
<view class="stats-item">
<text class="stats-number" style="color: rgb(41, 211, 180); font-size: 36rpx; font-weight: bold;">{{ stats.pending }}</text>
<text class="stats-label" style="color: #fff; font-size: 24rpx;">待签署</text>
</view>
<view class="stats-item">
<text class="stats-number" style="color: rgb(41, 211, 180); font-size: 36rpx; font-weight: bold;">{{ stats.completed }}</text>
<text class="stats-label" style="color: #fff; font-size: 24rpx;">已完成</text>
</view>
</view>
</view>
</view>
<!-- 合同列表 -->
<view class="contract-section" style="padding: 20rpx;">
<view class="section-title" style="color: #fff; font-size: 32rpx; margin-bottom: 20rpx;">
我的合同
</view>
<view
v-for="contract in contractList"
:key="contract.id"
class="contract-item"
style="background-color: #2A2A2A; border-radius: 12rpx; margin-bottom: 20rpx; padding: 30rpx;"
@click="goToDetail(contract)"
>
<view class="contract-header">
<text class="contract-name" style="color: #fff; font-size: 30rpx; font-weight: bold;">
{{ contract.contract_name }}
</text>
<view
class="contract-status"
:style="{
backgroundColor: getStatusColor(contract.status),
color: '#fff',
padding: '8rpx 16rpx',
borderRadius: '20rpx',
fontSize: '22rpx'
}"
>
{{ getStatusText(contract.status) }}
</view>
</view>
<view class="contract-info" style="margin-top: 20rpx;">
<view class="info-row">
<text class="info-label" style="color: #999; font-size: 24rpx;">合同类型:</text>
<text class="info-value" style="color: #fff; font-size: 24rpx;">{{ contract.contract_type_text }}</text>
</view>
<view class="info-row" style="margin-top: 10rpx;">
<text class="info-label" style="color: #999; font-size: 24rpx;">分发时间:</text>
<text class="info-value" style="color: #fff; font-size: 24rpx;">{{ formatTime(contract.created_at) }}</text>
</view>
<view v-if="contract.sign_time" class="info-row" style="margin-top: 10rpx;">
<text class="info-label" style="color: #999; font-size: 24rpx;">签署时间:</text>
<text class="info-value" style="color: #fff; font-size: 24rpx;">{{ formatTime(contract.sign_time) }}</text>
</view>
</view>
<view class="contract-actions" style="margin-top: 30rpx; text-align: right;">
<button
v-if="contract.status === 'pending'"
class="action-btn primary"
style="background-color: rgb(41, 211, 180); color: #fff; border: none; border-radius: 20rpx; padding: 12rpx 30rpx; font-size: 24rpx;"
>
立即签署
</button>
<button
v-else-if="contract.status === 'completed'"
class="action-btn secondary"
style="background-color: transparent; color: rgb(41, 211, 180); border: 2rpx solid rgb(41, 211, 180); border-radius: 20rpx; padding: 12rpx 30rpx; font-size: 24rpx;"
>
查看详情
</button>
</view>
</view>
</view>
<!-- 加载更多 -->
<view v-if="hasMore" class="load-more" style="text-align: center; padding: 40rpx; color: #999;">
<text @click="loadMore">加载更多</text>
</view>
<!-- 空状态 -->
<view v-if="contractList.length === 0 && !loading" class="empty-state" style="text-align: center; padding: 100rpx; color: #999;">
<text>暂无合同</text>
</view>
</view>
</template>
<script>
import apiRoute from '@/api/apiRoute.js'
export default {
data() {
return {
loading: false,
hasMore: true,
page: 1,
stats: {
total: 0,
pending: 0,
completed: 0
},
contractList: []
}
},
onLoad() {
this.getContractList()
this.getStats()
},
onPullDownRefresh() {
this.page = 1
this.contractList = []
this.getContractList()
this.getStats()
},
onReachBottom() {
if (this.hasMore) {
this.loadMore()
}
},
methods: {
async getContractList() {
if (this.loading) return
this.loading = true
try {
const res = await apiRoute.getMyContracts({
page: this.page,
limit: 10
})
if (this.page === 1) {
this.contractList = res.data.data
} else {
this.contractList.push(...res.data.data)
}
this.hasMore = res.data.data.length >= 10
uni.stopPullDownRefresh()
} catch (error) {
uni.showToast({
title: '获取数据失败',
icon: 'none'
})
} finally {
this.loading = false
}
},
async getStats() {
try {
const res = await apiRoute.getContractStats()
this.stats = res.data
} catch (error) {
console.error('获取统计数据失败', error)
}
},
loadMore() {
this.page++
this.getContractList()
},
goToDetail(contract) {
uni.navigateTo({
url: `/pages-common/contract/detail?id=${contract.id}`
})
},
getStatusColor(status) {
const colorMap = {
'pending': '#f39c12',
'completed': 'rgb(41, 211, 180)',
'rejected': '#e74c3c'
}
return colorMap[status] || '#999'
},
getStatusText(status) {
const textMap = {
'pending': '待签署',
'completed': '已完成',
'rejected': '已拒绝'
}
return textMap[status] || '未知'
},
formatTime(timestamp) {
if (!timestamp) return ''
const date = new Date(timestamp * 1000)
return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
}
}
}
</script>
<style scoped>
.stats-row {
display: flex;
justify-content: space-around;
}
.stats-item {
display: flex;
flex-direction: column;
align-items: center;
}
.contract-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.info-row {
display: flex;
}
.contract-actions {
display: flex;
justify-content: flex-end;
}
</style>