Files
backmanagerweb/src/components/contract.vue
T

444 lines
12 KiB
Vue
Raw Normal View History

2026-06-15 23:20:21 +08:00
<script setup>
2026-06-22 22:18:08 +08:00
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search } from '@element-plus/icons-vue'
import {
getContractList,
createContract,
updateContract,
deleteContractAPI
} from '../api/contract'
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
const search = ref('')
const select = ref('1')
2026-06-15 23:20:21 +08:00
const dateRange = ref([])
2026-06-22 22:18:08 +08:00
const filterType = ref('')
const loading = ref(false)
const searchResults = ref([])
const showSearchResults = ref(false)
const showAddForm = ref(false)
const isEditMode = ref(false)
const currentContractId = ref(null)
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
const form = reactive({
contract_no: '',
contract_name: '',
type: '',
party_a: '蜜雪冰城股份有限公司',
party_b: '',
sign_date: '',
start_date: '',
end_date: '',
amount: 0,
status: '待审批',
remark: ''
2026-06-15 23:20:21 +08:00
})
2026-06-22 22:18:08 +08:00
onMounted(() => {
fetchData()
})
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
// 获取合同列表
const fetchData = async () => {
loading.value = true
const res = await getContractList()
searchResults.value = res.data
showSearchResults.value = true
loading.value = false
2026-06-15 23:20:21 +08:00
}
2026-06-22 22:18:08 +08:00
// 处理搜索
const handleSearch = async () => {
loading.value = true
let keyword = search.value
if (select.value === '1' && keyword && !keyword.startsWith('HT')) {
keyword = 'HT' + keyword
}
const params = {
keyword,
searchField: select.value,
type: filterType.value,
startDate: dateRange.value?.[0],
endDate: dateRange.value?.[1]
}
const res = await getContractList(params)
searchResults.value = res.data
showSearchResults.value = true
loading.value = false
}
// 日期变更处理
const handleDateChange = () => {
handleSearch()
2026-06-15 23:20:21 +08:00
}
// 重置搜索
const resetSearch = () => {
2026-06-22 22:18:08 +08:00
search.value = ''
select.value = '1'
filterType.value = ''
2026-06-15 23:20:21 +08:00
dateRange.value = []
2026-06-22 22:18:08 +08:00
fetchData()
}
// 新增合同
const addContract = () => {
resetForm()
showAddForm.value = true
showSearchResults.value = false
}
// 编辑合同
const editContract = (row) => {
isEditMode.value = true
currentContractId.value = row.id
Object.assign(form, {
contract_no: row.contract_no,
contract_name: row.contract_name,
type: row.type,
party_a: row.party_a,
party_b: row.party_b,
sign_date: row.sign_date,
start_date: row.start_date,
end_date: row.end_date,
amount: row.amount,
status: row.status,
remark: row.remark
})
showAddForm.value = true
showSearchResults.value = false
}
// 保存合同
const saveContract = async () => {
if (isEditMode.value) {
await updateContract(currentContractId.value, { ...form })
ElMessage.success('更新成功')
} else {
await createContract({ ...form })
ElMessage.success('新增成功')
}
cancelAdd()
fetchData()
}
// 删除合同
const deleteContract = (id) => {
ElMessageBox.confirm('确定删除该合同吗?', '提示', {
type: 'warning'
}).then(async () => {
await deleteContractAPI(id)
ElMessage.success('删除成功')
fetchData()
})
}
// 取消
const cancelAdd = () => {
resetForm()
showAddForm.value = false
showSearchResults.value = true
}
// 重置表单
const resetForm = () => {
Object.assign(form, {
contract_no: '',
contract_name: '',
type: '',
party_a: '蜜雪冰城股份有限公司',
party_b: '',
sign_date: '',
start_date: '',
end_date: '',
amount: 0,
status: '待审批',
remark: ''
})
isEditMode.value = false
currentContractId.value = null
}
// 状态样式
const getStatusType = (status) => {
const map = {
'生效中': 'success',
'已到期': 'danger',
'待审批': 'warning',
'已终止': 'info'
}
return map[status] || 'info'
2026-06-15 23:20:21 +08:00
}
// 日期快捷选项
const dateShortcuts = [
{
text: '最近一周',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 7 * 24 * 3600 * 1000)
return [start, end]
}
},
{
text: '最近一个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 30 * 24 * 3600 * 1000)
return [start, end]
}
},
{
text: '最近三个月',
value: () => {
const end = new Date()
const start = new Date()
start.setTime(start.getTime() - 90 * 24 * 3600 * 1000)
return [start, end]
}
}
]
// 格式化日期
const formatDate = (date) => {
if (!date) return ''
return date
}
</script>
<template>
2026-06-22 22:18:08 +08:00
<div class="contract-container">
<!-- 搜索栏区域 -->
<div class="contract-search">
<!-- 第一行搜索框 + 按钮 -->
<div class="search-row">
<el-input v-model="search" style="max-width: 500px" placeholder="请输入搜索关键词"
class="contract-search-with-select" @keyup.enter="handleSearch">
<template #prepend>
<el-select v-model="select" placeholder="请选择" style="width: 115px">
<el-option label="编号" value="1" />
<el-option label="名称" value="2" />
</el-select>
</template>
<template #append>
<el-button :icon="Search" @click="handleSearch" />
</template>
</el-input>
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
<div class="search-buttons">
<el-button type="success" @click="addContract">新增合同</el-button>
<el-button type="default" @click="resetSearch">重置</el-button>
2026-06-15 23:20:21 +08:00
</div>
2026-06-22 22:18:08 +08:00
</div>
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
<!-- 第二行筛选条件 -->
<div class="filter-row">
<span class="filter-label">筛选条件</span>
<el-select v-model="filterType" placeholder="合同类型" clearable style="width: 150px;" @change="handleSearch">
<el-option label="全部类型" value="" />
<el-option label="加盟合同" value="加盟合同" />
<el-option label="供货合同" value="供货合同" />
<el-option label="租赁合同" value="租赁合同" />
<el-option label="服务合同" value="服务合同" />
</el-select>
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
<el-date-picker
v-model="dateRange"
type="daterange"
range-separator=""
start-placeholder="开始日期"
end-placeholder="结束日期"
style="margin-left: 10px;"
@change="handleDateChange"
/>
</div>
2026-06-15 23:20:21 +08:00
</div>
2026-06-22 22:18:08 +08:00
<!-- 合同列表 -->
<div v-if="showSearchResults" class="contract-list">
<div v-if="loading" class="loading-container">
<el-skeleton :rows="5" animated />
</div>
<div v-else-if="searchResults.length === 0" class="empty-container">
<el-empty description="暂无合同数据" />
</div>
<div v-else>
<div class="list-header">
<span class="total-count">共找到 {{ searchResults.length }} 条合同</span>
</div>
<el-table :data="searchResults" border style="width: 100%">
<el-table-column prop="id" label="ID" width="60" />
<el-table-column prop="contract_no" label="合同编号" width="130" />
<el-table-column prop="contract_name" label="合同名称" min-width="180" />
<el-table-column prop="type" label="合同类型" width="110" />
<el-table-column prop="party_b" label="乙方" width="100" />
<el-table-column prop="amount" label="金额" width="110">
<template #default="{ row }">
¥{{ row.amount?.toLocaleString() }}
</template>
</el-table-column>
<el-table-column prop="status" label="状态" width="90">
<template #default="{ row }">
<el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="sign_date" label="签订日期" width="110" />
<el-table-column label="操作" width="140" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="editContract(row)">编辑</el-button>
<el-button link type="danger" @click="deleteContract(row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
</div>
<!-- 新增/编辑表单 -->
<div v-if="showAddForm" class="contract-form" style="margin-top: 20px;">
<el-divider content-position="left">{{ isEditMode ? '编辑合同' : '新增合同' }}</el-divider>
<el-form :model="form" label-width="auto" style="max-width: 700px;" label-position="top">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="合同编号">
<el-input v-model="form.contract_no" placeholder="如: HT-001" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="合同类型">
<el-select v-model="form.type" placeholder="请选择" style="width: 100%;">
<el-option label="加盟合同" value="加盟合同" />
<el-option label="供货合同" value="供货合同" />
<el-option label="租赁合同" value="租赁合同" />
<el-option label="服务合同" value="服务合同" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="合同名称">
<el-input v-model="form.contract_name" placeholder="请输入合同名称" />
</el-form-item>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="甲方">
<el-input v-model="form.party_a" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="乙方">
<el-input v-model="form.party_b" placeholder="请输入乙方名称" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="签订日期">
<el-date-picker v-model="form.sign_date" type="date" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="生效日期">
<el-date-picker v-model="form.start_date" type="date" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="到期日期">
<el-date-picker v-model="form.end_date" type="date" style="width: 100%;" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="合同金额">
<el-input-number v-model="form.amount" :min="0" :step="1000" style="width: 100%;" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">
<el-select v-model="form.status" style="width: 100%;">
<el-option label="待审批" value="待审批" />
<el-option label="生效中" value="生效中" />
<el-option label="已到期" value="已到期" />
<el-option label="已终止" value="已终止" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" :rows="3" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="saveContract">保存</el-button>
<el-button @click="cancelAdd">取消</el-button>
</el-form-item>
</el-form>
</div>
</div>
2026-06-15 23:20:21 +08:00
</template>
<style scoped>
2026-06-22 22:18:08 +08:00
.contract-container {
padding: 20px;
}
2026-06-15 23:20:21 +08:00
2026-06-22 22:18:08 +08:00
.contract-search {
margin-bottom: 20px;
padding: 15px;
background: #fff;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
.search-row {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
gap: 10px;
}
.search-buttons {
display: flex;
gap: 10px;
}
.filter-row {
display: flex;
align-items: center;
margin-top: 15px;
padding-top: 15px;
border-top: 1px solid #eee;
}
.filter-label {
color: #606266;
font-size: 14px;
margin-right: 10px;
}
.list-header {
margin-bottom: 15px;
}
.total-count {
color: #909399;
font-size: 14px;
}
.loading-container, .empty-container {
padding: 40px 0;
}
2026-06-15 23:20:21 +08:00
</style>