179 lines
7.4 KiB
Vue
179 lines
7.4 KiB
Vue
<template>
|
|
<div class="page">
|
|
<el-card class="search-card">
|
|
<el-form :inline="true" :model="searchForm">
|
|
<el-form-item label="审批类型">
|
|
<select v-model="searchForm.type" style="width: 150px; height: 36px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 10px;">
|
|
<option value="">全部</option>
|
|
<option value="订单退款">订单退款</option>
|
|
<option value="车辆报废">车辆报废</option>
|
|
<option value="押金退还">押金退还</option>
|
|
<option value="价格修改">价格修改</option>
|
|
<option value="其他">其他</option>
|
|
</select>
|
|
</el-form-item>
|
|
<el-form-item label="状态">
|
|
<select v-model="searchForm.status" style="width: 150px; height: 36px; border: 1px solid #dcdfe6; border-radius: 4px; padding: 0 10px;">
|
|
<option value="">全部</option>
|
|
<option value="待审批">待审批</option>
|
|
<option value="已通过">已通过</option>
|
|
<option value="已拒绝">已拒绝</option>
|
|
</select>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" @click="handleSearch">搜索</el-button>
|
|
<el-button @click="handleReset">重置</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</el-card>
|
|
|
|
<div class="toolbar">
|
|
<el-button type="primary" @click="handleAdd">+ 创建审批</el-button>
|
|
</div>
|
|
|
|
<el-card>
|
|
<el-table :data="tableData" border stripe>
|
|
<el-table-column prop="approvalId" label="审批编号" width="140" />
|
|
<el-table-column prop="type" label="类型" width="100" />
|
|
<el-table-column prop="title" label="标题" />
|
|
<el-table-column prop="applicant" label="申请人" width="100" />
|
|
<el-table-column prop="status" label="状态" width="100">
|
|
<template #default="{ row }">
|
|
<el-tag :type="getStatusType(row.status)">{{ row.status }}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="approver" label="审批人" width="100" />
|
|
<el-table-column prop="createdAt" label="创建时间" width="120">
|
|
<template #default="{ row }">{{ formatDate(row.createdAt) }}</template>
|
|
</el-table-column>
|
|
<el-table-column label="操作" width="180">
|
|
<template #default="{ row }">
|
|
<el-button v-if="row.status === '待审批'" size="small" type="success" @click="handleApprove(row)">通过</el-button>
|
|
<el-button v-if="row.status === '待审批'" size="small" type="danger" @click="handleReject(row)">拒绝</el-button>
|
|
<el-button size="small" @click="handleEdit(row)">查看</el-button>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
</el-card>
|
|
|
|
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="500px">
|
|
<el-form :model="form" :rules="rules" ref="formRef" label-width="80px">
|
|
<el-form-item label="类型" prop="type">
|
|
<el-select v-model="form.type">
|
|
<el-option label="订单退款" value="订单退款" />
|
|
<el-option label="车辆报废" value="车辆报废" />
|
|
<el-option label="押金退还" value="押金退还" />
|
|
<el-option label="价格修改" value="价格修改" />
|
|
<el-option label="其他" value="其他" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<el-form-item label="标题" prop="title">
|
|
<el-input v-model="form.title" />
|
|
</el-form-item>
|
|
<el-form-item label="内容">
|
|
<el-input v-model="form.content" type="textarea" rows="3" />
|
|
</el-form-item>
|
|
<el-form-item label="申请人">
|
|
<el-input v-model="form.applicant" />
|
|
</el-form-item>
|
|
<el-form-item label="审批人">
|
|
<el-input v-model="form.approver" />
|
|
</el-form-item>
|
|
<el-form-item label="备注">
|
|
<el-input v-model="form.remark" type="textarea" rows="2" />
|
|
</el-form-item>
|
|
</el-form>
|
|
<template #footer>
|
|
<el-button @click="dialogVisible = false">取消</el-button>
|
|
<el-button type="primary" @click="handleSubmit">确定</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, onMounted } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import axios from 'axios'
|
|
|
|
const searchForm = ref({ type: '', status: '' })
|
|
const tableData = ref([])
|
|
const dialogVisible = ref(false)
|
|
const dialogTitle = ref('创建审批')
|
|
const formRef = ref(null)
|
|
const form = ref({ _id: '', type: '', title: '', content: '', applicant: '', approver: '', remark: '', status: '待审批' })
|
|
const rules = { type: [{ required: true, message: '请选择类型', trigger: 'change' }], title: [{ required: true, message: '请输入标题', trigger: 'blur' }] }
|
|
|
|
const fetchData = async () => {
|
|
const res = await axios.get('http://localhost:3000/api/approvals')
|
|
if (res.data.success) tableData.value = res.data.data
|
|
}
|
|
const handleSearch = () => {
|
|
let data = [...tableData.value]
|
|
if (searchForm.value.type) data = data.filter(a => a.type === searchForm.value.type)
|
|
if (searchForm.value.status) data = data.filter(a => a.status === searchForm.value.status)
|
|
tableData.value = data
|
|
}
|
|
const handleReset = () => { searchForm.value = { type: '', status: '' }; fetchData() }
|
|
const handleAdd = () => { dialogTitle.value = '创建审批'; form.value = { _id: '', type: '', title: '', content: '', applicant: '', approver: '', remark: '', status: '待审批' }; dialogVisible.value = true }
|
|
const handleEdit = (row) => { dialogTitle.value = '查看审批'; form.value = { ...row }; dialogVisible.value = true }
|
|
const handleApprove = async (row) => {
|
|
await axios.put(`http://localhost:3000/api/approvals/${row._id}`, { status: '已通过', approver: '管理员' })
|
|
ElMessage.success('审批通过'); fetchData()
|
|
}
|
|
const handleReject = async (row) => {
|
|
await axios.put(`http://localhost:3000/api/approvals/${row._id}`, { status: '已拒绝', approver: '管理员' })
|
|
ElMessage.info('已拒绝'); fetchData()
|
|
}
|
|
const handleSubmit = async () => {
|
|
await formRef.value.validate()
|
|
if (form.value._id) {
|
|
await axios.put(`http://localhost:3000/api/approvals/${form.value._id}`, form.value)
|
|
ElMessage.success('修改成功')
|
|
} else {
|
|
await axios.post('http://localhost:3000/api/approvals', form.value)
|
|
ElMessage.success('创建成功')
|
|
}
|
|
dialogVisible.value = false; fetchData()
|
|
}
|
|
const getStatusType = (status) => ({ '待审批': 'warning', '已通过': 'success', '已拒绝': 'danger' }[status] || 'info')
|
|
const formatDate = (d) => d ? new Date(d).toLocaleDateString('zh-CN') : '-'
|
|
onMounted(() => { fetchData() })
|
|
</script>
|
|
|
|
<style scoped>
|
|
.search-card {
|
|
margin-bottom: 20px;
|
|
}
|
|
.search-card :deep(.el-select) {
|
|
min-width: 200px;
|
|
}
|
|
.search-card :deep(.el-select .el-input) {
|
|
width: 200px;
|
|
}
|
|
.search-card :deep(.el-select-dropdown__item) {
|
|
padding: 8px 16px;
|
|
}
|
|
.search-card :deep(.el-select__wrapper) {
|
|
background-color: #fff !important;
|
|
min-height: 40px !important;
|
|
width: 200px !important;
|
|
}
|
|
.search-card :deep(.el-select__placeholder) {
|
|
color: #999 !important;
|
|
display: block !important;
|
|
}
|
|
.search-card :deep(.el-select__selected-item) {
|
|
color: #333 !important;
|
|
display: block !important;
|
|
line-height: 24px !important;
|
|
}
|
|
.search-card :deep(.el-tag) {
|
|
background-color: #f0f0f0 !important;
|
|
color: #333 !important;
|
|
height: 28px !important;
|
|
line-height: 28px !important;
|
|
}
|
|
.toolbar { margin-bottom: 20px; }
|
|
</style>
|