Files
by-crm/frontend/src/views/Report.vue
T
andy fd89c31640 feat(frontend): 为前端添加完整移动端响应式适配
- 新增响应式工具函数与全局移动端样式,统一适配≤768px屏幕
- 添加移动端底部导航组件,替代桌面端侧边栏菜单
- 为经销商、客户、报备列表页新增移动端卡片视图替换表格布局
- 调整所有页面的表单、弹窗与布局适配移动端尺寸
- 优化移动端viewport配置,适配全面屏安全区域
- 修复密码哈希工具,在非安全上下文下回退使用js-sha256库
- 更新依赖包,新增@vueuse/core与js-sha256
2026-08-03 15:35:45 +08:00

890 lines
29 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>
<div class="report-page">
<el-card>
<template #header>
<div class="card-header">
<div>
<span>报备管理</span>
<el-tag type="info" size="small" style="margin-left: 10px">
保护期:{{ protectDays }} 天
</el-tag>
</div>
<el-button type="primary" @click="handleAdd" v-if="!userStore.isAdmin">
<el-icon><Plus /></el-icon>
提交报备
</el-button>
</div>
</template>
<!-- 查询表单 -->
<el-form :inline="!isMobile" :model="queryForm" class="query-form">
<el-form-item label="学校名称">
<el-input v-model="queryForm.customerName" placeholder="请输入学校名称" clearable />
</el-form-item>
<el-form-item label="状态" style="width: 180px;">
<el-select v-model="queryForm.status" placeholder="请选择状态" clearable>
<el-option label="待审核" :value="0" />
<el-option label="已通过" :value="1" />
<el-option label="已驳回" :value="2" />
<el-option label="已失效" :value="3" />
<el-option label="已作废" :value="4" />
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery">
<el-icon><Search /></el-icon>
查询
</el-button>
<el-button @click="handleReset">重置</el-button>
</el-form-item>
</el-form>
<!-- 数据表格 -->
<el-table v-if="!isMobile" :data="tableData" border stripe v-loading="loading">
<el-table-column prop="dealerName" label="经销商" v-if="userStore.isAdmin"/>
<el-table-column prop="schoolName" label="学校名称" />
<el-table-column prop="product" label="所属产品" show-overflow-tooltip />
<el-table-column prop="projectType" label="项目类型" show-overflow-tooltip />
<el-table-column prop="contactPerson" label="负责人" show-overflow-tooltip />
<el-table-column prop="contactPhone" label="负责人电话" show-overflow-tooltip />
<el-table-column prop="description" label="报备说明" show-overflow-tooltip />
<el-table-column prop="status" label="状态">
<template #default="{ row }">
<el-tag v-if="row.status === 0" type="warning">待审核</el-tag>
<el-tag v-else-if="row.status === 1" type="success">已通过</el-tag>
<el-tag v-else-if="row.status === 2" type="danger">已驳回</el-tag>
<el-tag v-else-if="row.status === 3" type="info">已失效</el-tag>
<el-tag v-else-if="row.status === 4" type="warning">已作废</el-tag>
</template>
</el-table-column>
<el-table-column prop="protectEndDate" label="保护期截止" width="180">
<template #default="{ row }">
{{ formatDate(row.protectEndDate) }}
</template>
</el-table-column>
<el-table-column prop="createdAt" label="创建时间" width="180" />
<el-table-column label="操作" width="280" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click="handleView(row)">查看</el-button>
<el-button
v-if="row.status === 1"
link
type="info"
@click="handleShowProgress(row)"
>
进展
</el-button>
<el-button
v-if="userStore.isAdmin && row.status === 0"
link
type="success"
@click="handleAudit(row)"
>
审核
</el-button>
<el-button
v-if="userStore.isAdmin && row.status === 1"
link
type="warning"
@click="handleEdit(row)"
>
编辑
</el-button>
<el-button
v-if="!userStore.isAdmin && row.status === 0"
link
type="danger"
@click="handleWithdraw(row)"
>
撤回
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 移动端卡片视图 -->
<div v-if="isMobile" class="mobile-card-list" v-loading="loading">
<div v-for="row in tableData" :key="row.id" class="mobile-card">
<div class="card-top">
<span class="card-title">{{ row.schoolName }}</span>
<el-tag v-if="row.status === 0" type="warning" size="small">待审核</el-tag>
<el-tag v-else-if="row.status === 1" type="success" size="small">已通过</el-tag>
<el-tag v-else-if="row.status === 2" type="danger" size="small">已驳回</el-tag>
<el-tag v-else-if="row.status === 3" type="info" size="small">已失效</el-tag>
<el-tag v-else-if="row.status === 4" type="warning" size="small">已作废</el-tag>
</div>
<div v-if="userStore.isAdmin" class="card-row"><span class="label">经销商</span><span class="val">{{ row.dealerName || '-' }}</span></div>
<div class="card-row"><span class="label">所属产品</span><span class="val">{{ row.product || '-' }}</span></div>
<div class="card-row"><span class="label">项目类型</span><span class="val">{{ row.projectType || '-' }}</span></div>
<div class="card-row"><span class="label">负责人</span><span class="val">{{ row.contactPerson || '-' }}</span></div>
<div class="card-row"><span class="label">负责人电话</span><span class="val">{{ row.contactPhone || '-' }}</span></div>
<div class="card-row"><span class="label">报备说明</span><span class="val">{{ row.description || '-' }}</span></div>
<div class="card-row"><span class="label">保护期截止</span><span class="val">{{ formatDate(row.protectEndDate) }}</span></div>
<div class="card-row"><span class="label">创建时间</span><span class="val">{{ row.createdAt }}</span></div>
<div class="card-actions">
<el-button link type="primary" @click="handleView(row)">查看</el-button>
<el-button v-if="row.status === 1" link type="info" @click="handleShowProgress(row)">进展</el-button>
<el-button v-if="userStore.isAdmin && row.status === 0" link type="success" @click="handleAudit(row)">审核</el-button>
<el-button v-if="userStore.isAdmin && row.status === 1" link type="warning" @click="handleEdit(row)">编辑</el-button>
<el-button v-if="!userStore.isAdmin && row.status === 0" link type="danger" @click="handleWithdraw(row)">撤回</el-button>
</div>
</div>
<el-empty v-if="!loading && tableData.length === 0" description="暂无报备数据" />
</div>
<!-- 分页 -->
<el-config-provider :locale="zhCn">
<el-pagination
v-model:current-page="queryForm.current"
v-model:page-size="queryForm.size"
:total="total"
:page-sizes="[10, 20, 50, 100]"
:layout="isMobile ? 'prev, pager, next' : 'total, sizes, prev, pager, next, jumper'"
prev-text="上一页"
next-text="下一页"
@size-change="fetchData"
@current-change="fetchData"
:style="{ marginTop: '20px', justifyContent: isMobile ? 'center' : 'flex-end' }"
/>
</el-config-provider>
</el-card>
<!-- 提交报备对话框 -->
<el-dialog v-model="dialogVisible" title="提交报备" :width="isMobile ? '92%' : '650px'" @close="handleDialogClose">
<el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
<el-form-item label="学校" prop="schoolName">
<el-autocomplete
v-model="formData.schoolName"
:fetch-suggestions="searchSchool"
placeholder="请输入学校名称"
:trigger-on-focus="false"
style="width: 100%"
@select="handleSchoolSelect"
value-key="schoolName"
clearable
>
<template #default="{ item }">
<div>{{ item.schoolName }}</div>
<div style="font-size: 12px; color: #999;">{{ item.location || '无地址信息' }}</div>
</template>
</el-autocomplete>
</el-form-item>
<el-form-item label="所属产品" prop="product">
<el-input
v-model="formData.product"
placeholder="请输入所属产品"
clearable
/>
</el-form-item>
<el-form-item label="项目类型" prop="projectType">
<el-input
v-model="formData.projectType"
placeholder="请输入项目类型"
clearable
/>
</el-form-item>
<el-form-item label="负责人" prop="contactPerson">
<el-input
v-model="formData.contactPerson"
placeholder="请输入负责人姓名"
clearable
/>
</el-form-item>
<el-form-item label="负责人电话" prop="contactPhone">
<el-input
v-model="formData.contactPhone"
placeholder="请输入负责人电话"
clearable
/>
</el-form-item>
<el-form-item label="报备说明" prop="description">
<el-input
v-model="formData.description"
type="textarea"
:rows="4"
placeholder="请输入报备说明"
/>
</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>
<!-- 审核对话框 -->
<el-dialog v-model="auditDialogVisible" title="审核报备" :width="isMobile ? '92%' : '600px'">
<el-form :model="auditForm" label-width="100px">
<el-form-item label="审核结果">
<el-radio-group v-model="auditForm.approved">
<el-radio :label="true">通过</el-radio>
<el-radio :label="false">驳回</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="驳回原因" prop="rejectReason" v-if="!auditForm.approved">
<el-input
v-model="auditForm.rejectReason"
type="textarea"
:rows="4"
placeholder="请输入驳回原因"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="auditDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleAuditSubmit">确定</el-button>
</template>
</el-dialog>
<!-- 编辑报备对话框 -->
<el-dialog v-model="editDialogVisible" title="编辑报备" :width="isMobile ? '92%' : '600px'" @close="handleEditDialogClose">
<el-form ref="editFormRef" :model="editFormData" :rules="editRules" label-width="100px">
<el-form-item label="学校名称">
<el-input :model-value="currentReport?.schoolName" disabled />
</el-form-item>
<el-form-item label="所属产品" prop="product">
<el-input
v-model="editFormData.product"
placeholder="请输入所属产品"
clearable
/>
</el-form-item>
<el-form-item label="项目类型" prop="projectType">
<el-input
v-model="editFormData.projectType"
placeholder="请输入项目类型"
clearable
/>
</el-form-item>
<el-form-item label="负责人" prop="contactPerson">
<el-input
v-model="editFormData.contactPerson"
placeholder="请输入负责人姓名"
clearable
/>
</el-form-item>
<el-form-item label="负责人电话" prop="contactPhone">
<el-input
v-model="editFormData.contactPhone"
placeholder="请输入负责人电话"
clearable
/>
</el-form-item>
<el-form-item label="报备说明" prop="description">
<el-input
v-model="editFormData.description"
type="textarea"
:rows="4"
placeholder="请输入报备说明"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="editFormData.status" placeholder="请选择状态" style="width: 100%">
<el-option label="已通过" :value="1" />
<el-option label="已作废" :value="4" />
</el-select>
</el-form-item>
<el-form-item label="作废原因" prop="cancelReason" v-if="editFormData.status === 4">
<el-input
v-model="editFormData.cancelReason"
type="textarea"
:rows="4"
placeholder="请填写作废原因"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="editDialogVisible = false">取消</el-button>
<el-button type="primary" @click="handleEditSubmit">确定</el-button>
</template>
</el-dialog>
<!-- 报备详情对话框 -->
<el-dialog v-model="detailDialogVisible" title="报备详情" :width="isMobile ? '92%' : '700px'">
<el-descriptions :column="isMobile ? 1 : 2" border>
<el-descriptions-item label="经销商">
{{ currentReport?.dealerName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="学校名称">
{{ currentReport?.schoolName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="所属产品">
{{ currentReport?.product || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目类型">
{{ currentReport?.projectType || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目负责人">
{{ currentReport?.contactPerson || '-' }}
</el-descriptions-item>
<el-descriptions-item label="项目电话">
{{ currentReport?.contactPhone || '-' }}
</el-descriptions-item>
<el-descriptions-item label="状态" :span="2">
<el-tag v-if="currentReport?.status === 0" type="warning">待审核</el-tag>
<el-tag v-else-if="currentReport?.status === 1" type="success">已通过</el-tag>
<el-tag v-else-if="currentReport?.status === 2" type="danger">已驳回</el-tag>
<el-tag v-else-if="currentReport?.status === 3" type="info">已失效</el-tag>
<el-tag v-else-if="currentReport?.status === 4" type="warning">已作废</el-tag>
</el-descriptions-item>
<el-descriptions-item label="保护期开始" :span="1">
{{ formatDate(currentReport?.protectStartDate) }}
</el-descriptions-item>
<el-descriptions-item label="保护期结束" :span="1">
{{ formatDate(currentReport?.protectEndDate) }}
</el-descriptions-item>
<el-descriptions-item label="剩余保护天数" v-if="currentReport?.status === 1 && currentReport?.remainDays !== undefined">
<el-tag :type="currentReport.remainDays > 7 ? 'success' : currentReport.remainDays > 0 ? 'warning' : 'danger'">
{{ currentReport.remainDays }} 天
</el-tag>
</el-descriptions-item>
<el-descriptions-item label="驳回原因" v-if="currentReport?.status === 2" :span="2">
<span style="color: #f56c6c;">{{ currentReport?.rejectReason || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="作废原因" v-if="currentReport?.status === 4" :span="2">
<span style="color: #e6a23c;">{{ currentReport?.cancelReason || '-' }}</span>
</el-descriptions-item>
<el-descriptions-item label="报备说明" :span="2">
<div style="white-space: pre-wrap;">{{ currentReport?.description || '-' }}</div>
</el-descriptions-item>
<el-descriptions-item label="创建时间" :span="2">
{{ currentReport?.createdAt || '-' }}
</el-descriptions-item>
<el-descriptions-item label="更新时间" :span="2">
{{ currentReport?.updatedAt || '-' }}
</el-descriptions-item>
</el-descriptions>
<template #footer>
<el-button type="primary" @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
<!-- 进展记录对话框 -->
<el-dialog v-model="progressDialogVisible" title="报备进展记录" :width="isMobile ? '92%' : '1000px'" :fullscreen="isMobile" @close="handleProgressDialogClose">
<el-card>
<template #header>
<div class="card-header">
<span>添加进展记录</span>
</div>
</template>
<el-form ref="progressFormRef" :model="progressFormData" :rules="progressRules" label-width="100px">
<el-form-item label="进展内容" prop="progressContent">
<el-input
v-model="progressFormData.progressContent"
type="textarea"
:rows="4"
placeholder="请输入进展内容"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button v-if="editingProgressId" @click="handleCancelEdit">取消编辑</el-button>
<el-button type="primary" @click="handleSaveProgress">{{ editingProgressId ? '保存修改' : '添加' }}</el-button>
</template>
</el-card>
<el-divider content-position="left">进展记录列表</el-divider>
<el-table :data="progressList" border stripe v-loading="progressLoading">
<el-table-column prop="progressContent" label="进展内容" show-overflow-tooltip />
<el-table-column prop="createdAt" label="创建时间" width="180" />
<el-table-column prop="updatedAt" label="更新时间" width="180" />
<el-table-column label="操作" width="150" fixed="right">
<template #default="{ row }">
<el-button
v-if="!userStore.isAdmin"
link
type="primary"
@click="handleEditProgress(row)"
>
编辑
</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage, ElMessageBox, type FormInstance, type FormRules } from 'element-plus'
import { useUserStore } from '@/stores/user'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs'
import { getReportPage, createReport, auditReport, withdrawReport, updateReport } from '@/api/report'
import { getProgressByReportId, createProgress, updateProgress } from '@/api/report-progress'
import { searchSchoolByName } from '@/api/school'
import { getConfigValue } from '@/api/system'
import type { Report, ReportForm, ReportProgress, ReportProgressForm, ReportUpdateForm } from '@/types'
import { useResponsive } from '@/composables/useResponsive'
const route = useRoute()
const userStore = useUserStore()
const protectDays = ref<number>(90)
const { isMobile } = useResponsive()
const loading = ref(false)
const tableData = ref<Report[]>([])
const total = ref(0)
const dialogVisible = ref(false)
const auditDialogVisible = ref(false)
const detailDialogVisible = ref(false)
const editDialogVisible = ref(false)
const auditReportId = ref<number>()
const editingReportId = ref<number>()
const formRef = ref<FormInstance>()
const editFormRef = ref<FormInstance>()
const selectedSchool = ref<any>(null)
const currentReport = ref<Report | null>(null)
// 进展记录相关
const progressDialogVisible = ref(false)
const progressFormRef = ref<FormInstance>()
const progressFormData = reactive<ReportProgressForm>({
reportId: 0,
progressContent: ''
})
const progressList = ref<ReportProgress[]>([])
const editingProgressId = ref<number | undefined>()
const progressLoading = ref(false)
const progressRules: FormRules = {
progressContent: [{ required: true, message: '请输入进展内容', trigger: 'blur' }]
}
const queryForm = reactive({
current: 1,
size: 10,
customerName: '',
status: undefined as number | undefined
})
const formData = reactive<ReportForm>({
schoolId: undefined,
schoolName: '',
product: '',
projectType: '',
description: '',
contactPerson: '',
contactPhone: ''
})
const auditForm = reactive({
approved: true,
rejectReason: ''
})
const editFormData = reactive<ReportUpdateForm>({
product: '',
projectType: '',
description: '',
contactPerson: '',
contactPhone: '',
status: 1,
cancelReason: ''
})
const rules: FormRules = {
schoolName: [{ required: true, message: '请输入学校名称', trigger: 'blur' }],
product: [{ required: true, message: '请输入所属产品', trigger: 'blur' }],
projectType: [{ required: true, message: '请输入项目类型', trigger: 'blur' }]
}
const editRules: FormRules = {
product: [{ required: true, message: '请输入所属产品', trigger: 'blur' }],
projectType: [{ required: true, message: '请输入项目类型', trigger: 'blur' }],
status: [{ required: true, message: '请选择状态', trigger: 'change' }],
cancelReason: [{ required: true, message: '请填写作废原因', trigger: 'blur' }]
}
// 格式化日期,去掉时分秒
const formatDate = (dateStr: string | null | undefined) => {
if (!dateStr) return '-'
return dateStr.split(' ')[0] // 只保留日期部分,去掉时间
}
// 显示进展记录对话框
const handleShowProgress = async (row: Report) => {
progressFormData.reportId = row.id
progressFormData.progressContent = ''
editingProgressId.value = undefined
await fetchProgressList(row.id)
progressDialogVisible.value = true
}
// 获取进展记录列表
const fetchProgressList = async (reportId: number) => {
progressLoading.value = true
try {
const res = await getProgressByReportId(reportId)
progressList.value = res
} catch (error) {
console.error('获取进展记录失败', error)
progressList.value = []
} finally {
progressLoading.value = false
}
}
// 保存进展记录
const handleSaveProgress = async () => {
if (!progressFormRef.value) return
await progressFormRef.value.validate(async (valid) => {
if (valid) {
try {
if (editingProgressId.value) {
// 编辑模式
await updateProgress(editingProgressId.value, progressFormData)
ElMessage.success('更新成功')
} else {
// 新增模式
await createProgress(progressFormData)
ElMessage.success('添加成功')
}
// 重新获取进展记录列表
await fetchProgressList(progressFormData.reportId)
// 重置表单
progressFormData.progressContent = ''
editingProgressId.value = undefined
} catch (error) {
console.error('保存进展记录失败', error)
}
}
})
}
// 编辑进展记录
const handleEditProgress = (row: ReportProgress) => {
editingProgressId.value = row.id
progressFormData.progressContent = row.progressContent
}
// 取消编辑
const handleCancelEdit = () => {
editingProgressId.value = undefined
progressFormData.progressContent = ''
}
// 关闭进展记录对话框
const handleProgressDialogClose = () => {
progressDialogVisible.value = false
progressFormRef.value?.resetFields()
progressFormData.progressContent = ''
editingProgressId.value = undefined
progressList.value = []
}
// 查询数据
const fetchData = async () => {
loading.value = true
try {
const res = await getReportPage(queryForm)
tableData.value = res.records
total.value = res.total
} catch (error) {
console.error('查询失败', error)
} finally {
loading.value = false
}
}
// 搜索学校
const searchSchool = async (queryString: string, cb: any) => {
if (!queryString || queryString.trim().length < 1) {
cb([])
return
}
try {
const schools = await searchSchoolByName(queryString)
const suggestions = schools.map((school: any) => ({
...school,
value: school.schoolName
}))
cb(suggestions)
} catch (error) {
console.error('搜索学校失败', error)
cb([])
}
}
// 学校选择回调
const handleSchoolSelect = (item: any) => {
selectedSchool.value = item
formData.schoolId = item.id
}
// 查询按钮
const handleQuery = () => {
queryForm.current = 1
fetchData()
}
// 重置按钮
const handleReset = () => {
queryForm.customerName = ''
queryForm.status = undefined
queryForm.current = 1
fetchData()
}
// 新增按钮
const handleAdd = () => {
// 自动填充经销商的联系人和电话
if (userStore.userInfo?.dealerContactPerson) {
formData.contactPerson = userStore.userInfo.dealerContactPerson
}
if (userStore.userInfo?.dealerContactPhone) {
formData.contactPhone = userStore.userInfo.dealerContactPhone
}
dialogVisible.value = true
}
// 查看详情
const handleView = (row: Report) => {
currentReport.value = row
detailDialogVisible.value = true
}
// 审核按钮
const handleAudit = (row: Report) => {
auditReportId.value = row.id
auditForm.approved = true
auditForm.rejectReason = ''
auditDialogVisible.value = true
}
// 编辑按钮
const handleEdit = (row: Report) => {
editingReportId.value = row.id
currentReport.value = row
editFormData.product = row.product || ''
editFormData.projectType = row.projectType || ''
editFormData.description = row.description || ''
editFormData.contactPerson = row.contactPerson || ''
editFormData.contactPhone = row.contactPhone || ''
editFormData.status = row.status
editFormData.cancelReason = row.cancelReason || ''
editDialogVisible.value = true
}
// 编辑对话框关闭
const handleEditDialogClose = () => {
editFormRef.value?.resetFields()
Object.assign(editFormData, {
product: '',
projectType: '',
description: '',
contactPerson: '',
contactPhone: '',
status: 1,
cancelReason: ''
})
editingReportId.value = undefined
}
// 编辑提交
const handleEditSubmit = async () => {
if (!editingReportId.value) return
// 验证表单
if (editFormData.status === 4 && !editFormData.cancelReason) {
ElMessage.warning('请填写作废原因')
return
}
try {
await updateReport(editingReportId.value, editFormData)
ElMessage.success('编辑成功')
editDialogVisible.value = false
fetchData()
} catch (error) {
console.error('编辑失败', error)
}
}
// 撤回按钮
const handleWithdraw = async (row: Report) => {
try {
await ElMessageBox.confirm(
'确定要撤回该报备吗?',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}
)
await withdrawReport(row.id)
ElMessage.success('撤回成功')
fetchData()
} catch (error) {
// 取消撤回
}
}
// 提交报备
const handleSubmit = async () => {
if (!formRef.value) return
await formRef.value.validate(async (valid) => {
if (valid) {
try {
await createReport(formData)
ElMessage.success('提交成功')
dialogVisible.value = false
fetchData()
} catch (error) {
console.error('提交失败', error)
}
}
})
}
// 审核提交
const handleAuditSubmit = async () => {
if (!auditReportId.value) return
if (!auditForm.approved && !auditForm.rejectReason) {
ElMessage.warning('请输入驳回原因')
return
}
try {
await auditReport(auditReportId.value, auditForm)
ElMessage.success('审核成功')
auditDialogVisible.value = false
fetchData()
} catch (error) {
console.error('审核失败', error)
}
}
// 对话框关闭
const handleDialogClose = () => {
formRef.value?.resetFields()
Object.assign(formData, {
schoolId: undefined,
schoolName: '',
product: '',
projectType: '',
description: '',
contactPerson: '',
contactPhone: ''
})
selectedSchool.value = null
}
// 获取保护期配置
const fetchProtectDays = async () => {
try {
const res = await getConfigValue('report.protect.days')
protectDays.value = parseInt(res) || 90
} catch (error) {
console.error('获取配置失败', error)
}
}
onMounted(() => {
fetchProtectDays()
// 从路由查询参数中读取初始查询条件
const { status } = route.query
if (status !== undefined) {
queryForm.status = status === '' ? undefined : parseInt(status as string)
}
fetchData()
})
</script>
<style scoped>
.report-page {
width: 100%;
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
}
.query-form {
margin-bottom: 20px;
}
/* 详情对话框样式优化 */
:deep(.el-descriptions) {
margin-top: 10px;
}
:deep(.el-descriptions__label) {
font-weight: 600;
background-color: #fafafa;
}
:deep(.el-descriptions__content) {
color: #333;
}
/* ===== 移动端卡片视图 ===== */
.mobile-card-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.mobile-card {
background: #fff;
border: 1px solid #ebeef5;
border-radius: 8px;
padding: 12px;
}
.card-top {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 8px;
}
.card-title {
font-size: 15px;
font-weight: 600;
color: #303133;
}
.card-row {
display: flex;
align-items: flex-start;
font-size: 13px;
color: #606266;
line-height: 1.8;
}
.card-row .label {
width: 80px;
flex-shrink: 0;
color: #909399;
}
.card-row .val {
flex: 1;
word-break: break-all;
}
.card-actions {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 8px;
padding-top: 8px;
border-top: 1px solid #f0f0f0;
}
@media (max-width: 768px) {
.card-header {
flex-wrap: wrap;
gap: 10px;
}
}
</style>