231 lines
8.3 KiB
Vue
231 lines
8.3 KiB
Vue
<template>
|
|
<div class="subject-page">
|
|
<div class="subject-header">
|
|
<h3 class="page-title">📋 会计科目管理 — 新30号准则打标</h3>
|
|
<div class="header-right">
|
|
<el-button size="small" @click="goBack">← 返回报表</el-button>
|
|
<el-button type="primary" size="small" :loading="loading" @click="loadSubjects">刷新</el-button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 过滤 -->
|
|
<div class="filter-row">
|
|
<el-input v-model="keyword" placeholder="搜索科目名称/编码" size="small" style="width:200px;" clearable @change="loadSubjects" />
|
|
<el-select v-model="filterCategory" placeholder="新准则分类" clearable size="small" style="width:160px;" @change="loadSubjects">
|
|
<el-option label="经营类" value="operating" />
|
|
<el-option label="研发费用" value="operating_rd" />
|
|
<el-option label="经营汇兑" value="operating_fx" />
|
|
<el-option label="投资类" value="investing" />
|
|
<el-option label="筹资类" value="financing" />
|
|
<el-option label="筹资汇兑" value="financing_fx" />
|
|
<el-option label="所得税" value="tax" />
|
|
<el-option label="终止经营" value="discontinued" />
|
|
</el-select>
|
|
<span class="filter-info">共 {{ totalSubjects }} 个科目</span>
|
|
<span style="margin-left:auto;">
|
|
<el-button size="small" type="success" :disabled="selectedIds.length === 0" @click="showBatchDialog">
|
|
批量打标 ({{ selectedIds.length }})
|
|
</el-button>
|
|
</span>
|
|
</div>
|
|
|
|
<!-- 科目表格 -->
|
|
<el-table
|
|
:data="subjects"
|
|
border stripe size="small"
|
|
style="width:100%;margin-top:8px;"
|
|
@selection-change="onSelectionChange"
|
|
>
|
|
<el-table-column type="selection" width="40" />
|
|
<el-table-column prop="subject_code" label="科目编码" width="100" />
|
|
<el-table-column prop="subject_name" label="科目名称" min-width="160" />
|
|
<el-table-column prop="parent_code" label="上级编码" width="80" />
|
|
<el-table-column prop="level" label="级别" width="50" />
|
|
<el-table-column label="新30号准则分类" width="180">
|
|
<template #default="{ row }">
|
|
<el-select
|
|
v-model="row.new_standard_category"
|
|
size="small"
|
|
placeholder="选择分类"
|
|
style="width:150px;"
|
|
@change="val => updateCategory(row, val)"
|
|
>
|
|
<el-option label="未分类" value="" />
|
|
<el-option label="经营类" value="operating" />
|
|
<el-option label="研发费用(经营类)" value="operating_rd" />
|
|
<el-option label="经营汇兑损益" value="operating_fx" />
|
|
<el-option label="投资类" value="investing" />
|
|
<el-option label="筹资类" value="financing" />
|
|
<el-option label="筹资汇兑损益" value="financing_fx" />
|
|
<el-option label="所得税" value="tax" />
|
|
<el-option label="终止经营" value="discontinued" />
|
|
</el-select>
|
|
</template>
|
|
</el-table-column>
|
|
<el-table-column prop="category" label="科目类别" width="80" />
|
|
<el-table-column label="分类标签" width="100">
|
|
<template #default="{ row }">
|
|
<el-tag v-if="row.new_standard_category" :type="tagType(row.new_standard_category)" size="small">
|
|
{{ catLabel(row.new_standard_category) }}
|
|
</el-tag>
|
|
<span v-else style="color:#ccc;">未分类</span>
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
|
|
<!-- 批量打标对话框 -->
|
|
<el-dialog v-model="batchDialogVisible" title="批量设置新30号准则分类" width="400px">
|
|
<div class="batch-dialog-body">
|
|
<p>已选 <strong>{{ selectedIds.length }}</strong> 个科目</p>
|
|
<el-select v-model="batchCategory" placeholder="选择分类" size="small" style="width:100%;">
|
|
<el-option label="经营类" value="operating" />
|
|
<el-option label="研发费用(经营类)" value="operating_rd" />
|
|
<el-option label="经营汇兑损益" value="operating_fx" />
|
|
<el-option label="投资类" value="investing" />
|
|
<el-option label="筹资类" value="financing" />
|
|
<el-option label="筹资汇兑损益" value="financing_fx" />
|
|
<el-option label="所得税" value="tax" />
|
|
<el-option label="终止经营" value="discontinued" />
|
|
</el-select>
|
|
</div>
|
|
<template #footer>
|
|
<el-button size="small" @click="batchDialogVisible = false">取消</el-button>
|
|
<el-button type="primary" size="small" :loading="batchLoading" @click="doBatchUpdate">确认打标</el-button>
|
|
</template>
|
|
</el-dialog>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { ref, onMounted } from 'vue'
|
|
import { ElMessage, ElMessageBox } from 'element-plus'
|
|
import axios from 'axios'
|
|
|
|
const api = axios.create({ baseURL: '/api/cma', timeout: 30000 })
|
|
api.interceptors.request.use((config: any) => {
|
|
const token = localStorage.getItem('cma_token')
|
|
if (token) config.headers.Authorization = `'Bearer ' + token`
|
|
return config
|
|
})
|
|
|
|
const loading = ref(false)
|
|
const subjects = ref<any[]>([])
|
|
const totalSubjects = ref(0)
|
|
const keyword = ref('')
|
|
const filterCategory = ref('')
|
|
const selectedIds = ref<number[]>([])
|
|
|
|
// 批量打标
|
|
const batchDialogVisible = ref(false)
|
|
const batchCategory = ref('')
|
|
const batchLoading = ref(false)
|
|
|
|
async function loadSubjects() {
|
|
loading.value = true
|
|
try {
|
|
const params: any = {}
|
|
if (filterCategory.value) params.category = filterCategory.value
|
|
if (keyword.value) params.keyword = keyword.value
|
|
const r = await api.get('/subjects', { params })
|
|
const d = (r as any).data || {}
|
|
subjects.value = d.data || []
|
|
totalSubjects.value = d.total || 0
|
|
} catch (e) {
|
|
ElMessage.error('加载科目列表失败')
|
|
subjects.value = []
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
async function updateCategory(row: any, val: string) {
|
|
if (!val) {
|
|
// 清空分类
|
|
row.new_standard_category = ''
|
|
return
|
|
}
|
|
try {
|
|
await api.put(`/subjects/${row.id}`, null, {
|
|
params: { new_standard_category: val }
|
|
})
|
|
ElMessage.success(`${row.subject_name} 分类更新成功`)
|
|
} catch (e) {
|
|
ElMessage.error('更新失败')
|
|
// 回滚
|
|
row.new_standard_category = row._old_category || ''
|
|
}
|
|
}
|
|
|
|
function onSelectionChange(rows: any[]) {
|
|
selectedIds.value = rows.map((r: any) => r.id)
|
|
}
|
|
|
|
function showBatchDialog() {
|
|
if (selectedIds.value.length === 0) {
|
|
ElMessage.warning('请先选择科目')
|
|
return
|
|
}
|
|
batchCategory.value = ''
|
|
batchDialogVisible.value = true
|
|
}
|
|
|
|
async function doBatchUpdate() {
|
|
if (!batchCategory.value) {
|
|
ElMessage.warning('请选择分类')
|
|
return
|
|
}
|
|
batchLoading.value = true
|
|
try {
|
|
await api.put('/subjects/batch/category', null, {
|
|
params: {
|
|
ids: selectedIds.value,
|
|
new_standard_category: batchCategory.value,
|
|
}
|
|
})
|
|
ElMessage.success(`批量更新 ${selectedIds.value.length} 个科目成功`)
|
|
batchDialogVisible.value = false
|
|
await loadSubjects()
|
|
} catch (e) {
|
|
ElMessage.error('批量更新失败')
|
|
} finally {
|
|
batchLoading.value = false
|
|
}
|
|
}
|
|
|
|
function catLabel(cat: string): string {
|
|
const map: Record<string, string> = {
|
|
operating: '经营类', operating_rd: '研发费用', operating_fx: '经营汇兑',
|
|
investing: '投资类', financing: '筹资类', financing_fx: '筹资汇兑',
|
|
tax: '所得税', discontinued: '终止经营',
|
|
}
|
|
return map[cat] || cat
|
|
}
|
|
|
|
function tagType(cat: string): string {
|
|
const map: Record<string, string> = {
|
|
operating: '', operating_rd: 'warning', operating_fx: 'info',
|
|
investing: 'success', financing: 'danger', financing_fx: 'danger',
|
|
tax: 'info', discontinued: 'warning',
|
|
}
|
|
return map[cat] || ''
|
|
}
|
|
|
|
function goBack() {
|
|
window.history.back()
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadSubjects()
|
|
})
|
|
</script>
|
|
|
|
<style scoped>
|
|
.subject-page { max-width: 1200px; margin: 0 auto; padding: 16px; }
|
|
.subject-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 16px; }
|
|
.header-right { display: flex; gap: 8px; align-items: center; }
|
|
.page-title { font-size: 18px; font-weight: 600; color: #1a1a2e; margin: 0; }
|
|
.filter-row { display: flex; align-items: center; gap: 12px; margin-bottom: 12px; }
|
|
.filter-info { font-size: 12px; color: #999; }
|
|
.batch-dialog-body { display: flex; flex-direction: column; gap: 12px; }
|
|
</style>
|