feat(frontend): 绩效台账与月度结算两页接入(新组绩效工资)
- 绩效台账页(order17):月/版本筛选 + 行展开计算快照 + 重算(原因 对话框,管理员/财务);核算入口在回款管理页(每笔回款行内触发) - 月结页(order18):生成快照(月份输入)+ 状态筛选 + 提交审批 + 详情抽屉(按人明细三口径/试用期说明/审批单号关联) - 均复用 usePagedList/AppPagination/--ys-* 惯例;金额 str 直出 - type-check 零错误;build 通过 Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
e7e47d88bc
commit
a1217f4482
5 files changed
+609
No files matched your search
@@ -0,0 +1,175 @@
|
||||
<script setup lang="ts">
|
||||
import { reactive, ref } from 'vue'
|
||||
import { ElMessage } from 'element-plus'
|
||||
|
||||
import * as calcApi from '@/api/calc'
|
||||
import type { LedgerRow } from '@/api/calc'
|
||||
import AppPagination from '@/components/table/AppPagination.vue'
|
||||
import { usePagedList } from '@/composables/usePagedList'
|
||||
import { handledError } from '@/utils/error'
|
||||
|
||||
/**
|
||||
* 绩效核算台账(M3 ④):核算事实的固化点。
|
||||
*
|
||||
* - 核算=把回款固化为台账行(每笔回款仅一次;同业务重复回款仅登记进度)
|
||||
* - 重算=作废旧版本、按当前参数落新版本(管理员/财务授权,原因留痕)
|
||||
* - 行展开看计算快照(所用参数版本与行级折算明细)
|
||||
*/
|
||||
|
||||
const filters = reactive({
|
||||
settlement_month: '',
|
||||
is_active: 1 as number | undefined,
|
||||
})
|
||||
|
||||
const { records, total, pageNum, pageSize, loading, load, search } = usePagedList<
|
||||
LedgerRow,
|
||||
{ settlement_month?: string; is_active?: number }
|
||||
>(calcApi.listLedger, () => ({
|
||||
settlement_month: filters.settlement_month.trim() || undefined,
|
||||
is_active: filters.is_active,
|
||||
}))
|
||||
|
||||
function resetFilters(): void {
|
||||
filters.settlement_month = ''
|
||||
filters.is_active = 1
|
||||
search()
|
||||
}
|
||||
|
||||
const recalcVisible = ref(false)
|
||||
const recalcTarget = ref<LedgerRow | null>(null)
|
||||
const recalcReason = ref('')
|
||||
|
||||
function openRecalc(row: LedgerRow): void {
|
||||
recalcTarget.value = row
|
||||
recalcReason.value = ''
|
||||
recalcVisible.value = true
|
||||
}
|
||||
|
||||
async function submitRecalc(): Promise<void> {
|
||||
if (!recalcTarget.value) return
|
||||
if (!recalcReason.value.trim()) {
|
||||
ElMessage.warning('重算必须填写原因')
|
||||
return
|
||||
}
|
||||
try {
|
||||
await calcApi.recalcReceipt(recalcTarget.value.id, recalcReason.value.trim())
|
||||
ElMessage.success('重算完成(新版本已生效)')
|
||||
recalcVisible.value = false
|
||||
await load()
|
||||
} catch (error) {
|
||||
handledError(error)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="page">
|
||||
<el-form inline class="filters" @submit.prevent>
|
||||
<el-form-item label="归属月">
|
||||
<el-input
|
||||
v-model="filters.settlement_month"
|
||||
placeholder="YYYY-MM"
|
||||
clearable
|
||||
style="width: 140px"
|
||||
@keyup.enter="search"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="版本">
|
||||
<el-select v-model="filters.is_active" style="width: 130px">
|
||||
<el-option label="仅当前生效" :value="1" />
|
||||
<el-option label="含历史版本" :value="0" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="search">查询</el-button>
|
||||
<el-button @click="resetFilters">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
<el-table v-loading="loading" :data="records" stripe>
|
||||
<el-table-column type="expand">
|
||||
<template #default="{ row }">
|
||||
<pre class="snapshot">{{ JSON.stringify(row.snapshot_json ?? {}, null, 2) }}</pre>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="settlement_month" label="归属月" width="90" />
|
||||
<el-table-column prop="business_no" label="业务编号" min-width="150" />
|
||||
<el-table-column prop="personnel_name" label="归属人员" width="100" />
|
||||
<el-table-column prop="role_code" label="岗位" width="110" />
|
||||
<el-table-column prop="receipt_date" label="回款日" width="100" />
|
||||
<el-table-column prop="payment_days" label="天数" width="70" />
|
||||
<el-table-column prop="rate_text" label="计提比例" min-width="90" />
|
||||
<el-table-column prop="converted_profit" label="折算毛利" min-width="100" />
|
||||
<el-table-column prop="performance_amount" label="绩效金额" min-width="100" />
|
||||
<el-table-column prop="payable_amount" label="应付绩效" min-width="100" />
|
||||
<el-table-column label="版本" width="80">
|
||||
<template #default="{ row }">
|
||||
v{{ row.calc_version }}
|
||||
<el-tag v-if="row.is_active === 0" size="small" type="info" disable-transitions>
|
||||
已替代
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" width="90" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button
|
||||
v-if="row.is_active === 1 && row.calc_type === 1"
|
||||
link
|
||||
type="primary"
|
||||
@click="openRecalc(row)"
|
||||
>
|
||||
重算
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<AppPagination
|
||||
v-model:page-num="pageNum"
|
||||
v-model:page-size="pageSize"
|
||||
:total="total"
|
||||
@change="load"
|
||||
/>
|
||||
|
||||
<el-dialog v-model="recalcVisible" title="重算确认" width="460px">
|
||||
<p class="recalc-warn">
|
||||
重算会作废当前版本(v{{ recalcTarget?.calc_version }})并按当前参数落新版本,
|
||||
历史版本可追溯。请填写重算原因。
|
||||
</p>
|
||||
<el-input
|
||||
v-model="recalcReason"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
maxlength="255"
|
||||
placeholder="重算原因(必填,留痕)"
|
||||
/>
|
||||
<template #footer>
|
||||
<el-button @click="recalcVisible = false">取消</el-button>
|
||||
<el-button type="primary" @click="submitRecalc">确认重算</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.filters {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.snapshot {
|
||||
margin: 0;
|
||||
padding: 10px;
|
||||
font-size: 12px;
|
||||
line-height: 1.6;
|
||||
background: #f4f5f8;
|
||||
border-radius: 6px;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.recalc-warn {
|
||||
margin: 0 0 10px;
|
||||
font-size: 12px;
|
||||
color: var(--ys-ink-3);
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user