| | |
| | | <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) |
| | |
| | | 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> |
| | | |