yeg
2026-09-09 528d52f2c7c6f911c54cae6e3f25500eab4384fe
src/views/FormationReport.vue
@@ -1,35 +1,13 @@
<script setup lang="ts">
import { computed, onMounted, reactive, ref } from 'vue'
import { computed, reactive, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useRouter } from 'vue-router'
import { useFormationReports } from '@/stores/formationReports'
import type { FormationSummary } from '@/api/formationReports'
import { getUserInfo } from '@/api/auth'
import { useFormationReports, type FormationReportRecord } from '@/stores/formationReports'
import { createFormationReportPrintData, openFormationReportPrint } from '@/utils/formationReportPrint'
interface FilterState { reportName: string; creator: string; dateRange: [string, string] | null }
const router = useRouter()
const { records, refreshReports, removeReport } = useFormationReports()
const loading = ref(false)
const loadError = ref('')
const canCreate = ref(false)
const canEdit = ref(false)
const canQuery = ref(false)
const canDelete = ref(false)
const deletingId = ref<number | null>(null)
const dateText = (time: number) => new Date(time).toLocaleString()
const dateKey = (time: number) => new Date(time).toLocaleDateString('sv-SE')
onMounted(async () => {
  loading.value = true
  records.value = []
  try {
    const permissions = (await getUserInfo()).permissions || []
    const has = (action: string) => permissions.includes('*:*:*') || permissions.includes(`system:formation-report:${action}`)
    canCreate.value = has('add'); canEdit.value = has('edit'); canQuery.value = has('query'); canDelete.value = has('remove')
    if (canQuery.value) await refreshReports()
    else loadError.value = '无查看化成报表权限'
  } catch (error) { loadError.value = error instanceof Error ? error.message : '化成报表列表加载失败' }
  finally { loading.value = false }
})
const { records, removeReport } = useFormationReports()
const filters = reactive<FilterState>({ reportName: '', creator: '', dateRange: null })
const appliedFilters = ref<FilterState>({ reportName: '', creator: '', dateRange: null })
const currentPage = ref(1)
@@ -40,32 +18,29 @@
  const keyword = query.reportName.trim().toLowerCase()
  return records.value.filter(item => !keyword || item.name.toLowerCase().includes(keyword) || String(item.id).includes(keyword))
    .filter(item => !query.creator || query.creator === '全部' || item.creator === query.creator)
    .filter(item => !query.dateRange || (dateKey(item.createdAt) >= query.dateRange[0] && dateKey(item.createdAt) <= query.dateRange[1]))
    .sort((a, b) => b.createdAt - a.createdAt)
    .filter(item => !query.dateRange || (item.createdAt.slice(0, 10) >= query.dateRange[0] && item.createdAt.slice(0, 10) <= query.dateRange[1]))
    .sort((a, b) => b.createdAt.localeCompare(a.createdAt))
})
const pagedRecords = computed(() => filteredRecords.value.slice((currentPage.value - 1) * pageSize.value, currentPage.value * pageSize.value))
function applySearch() { appliedFilters.value = { reportName: filters.reportName, creator: filters.creator, dateRange: filters.dateRange ? [...filters.dateRange] as [string, string] : null }; currentPage.value = 1; ElMessage.success(`已找到 ${filteredRecords.value.length} 份化成报表`) }
function resetSearch() { Object.assign(filters, { reportName: '', creator: '', dateRange: null }); appliedFilters.value = { reportName: '', creator: '', dateRange: null }; currentPage.value = 1 }
function openCreate() { router.push('/report-formation/new') }
function openEdit(item: FormationSummary) { router.push({ path: `/report-formation/${item.id}/edit`, query: { mode: 'edit' } }) }
function openView(item: FormationSummary) { router.push({ path: `/report-formation/${item.id}/edit`, query: { mode: 'view' } }) }
async function deleteReport(item: FormationSummary) {
  try {
    await ElMessageBox.confirm(`删除“${item.name}”及全部历史版本后无法恢复,是否继续?`, '确认删除化成报表', { confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning' })
    deletingId.value = item.id
    await removeReport(item.id)
    currentPage.value = Math.min(currentPage.value, Math.max(1, Math.ceil(filteredRecords.value.length / pageSize.value)))
    ElMessage.success('化成报表已删除')
  } catch (error) { if (error !== 'cancel' && error !== 'close') ElMessage.error(error instanceof Error ? error.message : '删除失败') }
  finally { deletingId.value = null }
function openEdit(item: FormationReportRecord) { router.push(`/report-formation/${item.id}/edit`) }
function openView(item: FormationReportRecord) { router.push({ path: `/report-formation/${item.id}/edit`, query: { mode: 'view' } }) }
function downloadPdf(item: FormationReportRecord) {
  const opened = openFormationReportPrint(createFormationReportPrintData(item))
  if (!opened) { ElMessage.warning('浏览器阻止了报表窗口,请允许弹出窗口后重试'); return }
  ElMessage.info('已打开打印版报表,请在打印窗口选择“另存为 PDF”')
}
async function deleteReport(item: FormationReportRecord) {
  try { await ElMessageBox.confirm(`删除“${item.name}”后无法恢复,是否继续?`, '确认删除化成报表', { confirmButtonText: '删除', cancelButtonText: '取消', type: 'warning' }); removeReport(item.id); ElMessage.success('化成报表已删除') } catch { /* 用户取消 */ }
}
</script>
<template>
  <div class="formation-page" v-loading="loading">
    <el-alert v-if="loadError" :title="loadError" type="error" :closable="false" />
  <div class="formation-page">
    <section class="filter-panel"><header class="section-heading"><div><i></i><strong>查询报表</strong><span>FORMATION REPORT QUERY</span></div><small>共 {{ records.length }} 份报表</small></header><div class="filter-grid"><label><span>报表名称</span><el-input v-model="filters.reportName" clearable placeholder="输入报表名称或ID" @keyup.enter="applySearch" /></label><label><span>创建人</span><el-select v-model="filters.creator" clearable placeholder="全部"><el-option label="全部" value="全部" /><el-option v-for="item in creatorOptions" :key="item" :label="item" :value="item" /></el-select></label><label><span>创建时间</span><el-date-picker v-model="filters.dateRange" type="daterange" value-format="YYYY-MM-DD" start-placeholder="开始日期" end-placeholder="结束日期" range-separator="至" unlink-panels /></label><div class="filter-actions"><button class="primary-button" type="button" @click="applySearch"><el-icon><Search /></el-icon>查询</button><button class="secondary-button" type="button" @click="resetSearch"><el-icon><RefreshLeft /></el-icon>重置</button></div></div></section>
    <section class="result-panel"><div class="result-toolbar"><div><i></i><strong>化成报表列表</strong><span>{{ filteredRecords.length }} RESULTS · 按创建时间倒序</span></div><div class="toolbar-actions"><button v-if="canCreate" class="primary-button create-button" type="button" @click="openCreate"><el-icon><Plus /></el-icon>新建报表</button></div></div><div class="table-wrap"><table><thead><tr><th>报表ID</th><th>报表名称</th><th>测试名称</th><th>电池组</th><th>创建时间</th><th>创建人</th><th class="action-column">操作</th></tr></thead><tbody><tr v-for="item in pagedRecords" :key="item.id"><td class="id-cell">#{{ item.id }}</td><td><strong>{{ item.name }}</strong></td><td>{{ item.testName }}</td><td>{{ item.batteryGroup }}</td><td>{{ dateText(item.createdAt) }}</td><td>{{ item.creator }}</td><td class="action-column"><div class="row-actions"><button v-if="canQuery" type="button" @click="openView(item)">查看报表</button><button v-if="canEdit" type="button" @click="openEdit(item)">编辑</button><button v-if="canDelete" :disabled="deletingId !== null" class="delete-action" type="button" @click="deleteReport(item)">删除</button></div></td></tr><tr v-if="!pagedRecords.length && !loading && !loadError"><td colspan="7" class="empty-cell">暂无符合条件的化成报表</td></tr></tbody></table></div><footer class="pagination-bar"><span>显示 {{ pagedRecords.length }} 条,共 {{ filteredRecords.length }} 条</span><el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 50]" :total="filteredRecords.length" layout="sizes, prev, pager, next" background /></footer></section>
    <section class="result-panel"><div class="result-toolbar"><div><i></i><strong>化成报表列表</strong><span>{{ filteredRecords.length }} RESULTS · 按创建时间倒序</span></div><div class="toolbar-actions"><button class="primary-button create-button" type="button" @click="openCreate"><el-icon><Plus /></el-icon>新建报表</button></div></div><div class="table-wrap"><table><thead><tr><th>报表ID</th><th>报表名称</th><th>测试名称</th><th>电池组</th><th>创建时间</th><th>创建人</th><th class="action-column">操作</th></tr></thead><tbody><tr v-for="item in pagedRecords" :key="item.id"><td class="id-cell">#{{ item.id }}</td><td><strong>{{ item.name }}</strong></td><td>{{ item.testName }}</td><td>{{ item.batteryGroup }}</td><td>{{ item.createdAt }}</td><td>{{ item.creator }}</td><td class="action-column"><div class="row-actions"><button type="button" @click="openView(item)">查看报表</button><button type="button" @click="openEdit(item)">编辑</button><button type="button" @click="downloadPdf(item)">下载PDF</button><button class="delete-action" type="button" @click="deleteReport(item)">删除</button></div></td></tr><tr v-if="!pagedRecords.length"><td colspan="7" class="empty-cell">暂无符合条件的化成报表</td></tr></tbody></table></div><footer class="pagination-bar"><span>显示 {{ pagedRecords.length }} 条,共 {{ filteredRecords.length }} 条</span><el-pagination v-model:current-page="currentPage" v-model:page-size="pageSize" :page-sizes="[10, 20, 50]" :total="filteredRecords.length" layout="sizes, prev, pager, next" background /></footer></section>
  </div>
</template>