✨ feat: 财务单据完善
This commit is contained in:
@@ -38,6 +38,7 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getFinancialAccounts() {
|
getFinancialAccounts() {
|
||||||
|
console.log(this.financialAccounts, 'financialAccounts');
|
||||||
this.options = this.financialAccounts.map(item => ({
|
this.options = this.financialAccounts.map(item => ({
|
||||||
label: item.accountName,
|
label: item.accountName,
|
||||||
value: item.accountId
|
value: item.accountId
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ const mutations = {
|
|||||||
const actions = {
|
const actions = {
|
||||||
getFinancialAccounts({ commit }) {
|
getFinancialAccounts({ commit }) {
|
||||||
listAccount({ pageSize: 1000 }).then(response => {
|
listAccount({ pageSize: 1000 }).then(response => {
|
||||||
commit('SET_FINANCIAL_ACCOUNTS', response.rows);
|
console.log(response.data, 'finance.response.rows');
|
||||||
|
commit('SET_FINANCIAL_ACCOUNTS', response.data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,124 @@
|
|||||||
|
<template>
|
||||||
|
<div class="finance-voucher-component">
|
||||||
|
<div
|
||||||
|
v-for="(voucher, index) in voucherData"
|
||||||
|
:key="index"
|
||||||
|
class="voucher-item"
|
||||||
|
>
|
||||||
|
<!-- 主单据信息行 -->
|
||||||
|
<div class="voucher-header">
|
||||||
|
<div class="header-cell">
|
||||||
|
<el-checkbox v-model="voucher.checked"></el-checkbox>
|
||||||
|
</div>
|
||||||
|
<div class="header-cell">日期: {{ formatDate(voucher.docDate) }}</div>
|
||||||
|
<div class="header-cell">单据编号: {{ voucher.docNo }}</div>
|
||||||
|
<div class="header-cell">单据类型: {{ voucher.docType }}</div>
|
||||||
|
<div class="header-cell operation-group">
|
||||||
|
<el-button type="text" size="mini" @click.stop="handleView(voucher)">查看</el-button>
|
||||||
|
<el-button type="text" size="mini" @click.stop="handleDelete(voucher)">删除</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 凭证明细表格 -->
|
||||||
|
<el-table :data="voucher.detailList || []" border style="width: 100%;">
|
||||||
|
<el-table-column label="摘要" prop="voucherNo" />
|
||||||
|
<el-table-column label="科目" prop="accountId" />
|
||||||
|
<el-table-column label="借方金额" prop="debitAmount" align="right" />
|
||||||
|
<el-table-column label="贷方金额" prop="creditAmount" align="right" />
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<!-- 总计行 -->
|
||||||
|
<div class="total-row">
|
||||||
|
<div class="total-cell" :colspan="3">总计</div>
|
||||||
|
<div class="total-cell" align="right">{{ calculateTotal(voucher.detailList, 'debitAmount') }}</div>
|
||||||
|
<div class="total-cell" align="right">{{ calculateTotal(voucher.detailList, 'creditAmount') }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "FinanceVoucherComponent",
|
||||||
|
props: {
|
||||||
|
voucherData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 用于存储选中状态,若父组件需控制,可改为 prop 或 sync 修饰符
|
||||||
|
internalVoucherData: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
voucherData: {
|
||||||
|
handler(val) {
|
||||||
|
this.internalVoucherData = val.map((v) => ({
|
||||||
|
...v,
|
||||||
|
checked: false,
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
immediate: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleView(voucher) {
|
||||||
|
this.$emit("view-voucher", voucher);
|
||||||
|
},
|
||||||
|
handleDelete(voucher) {
|
||||||
|
this.$emit("delete-voucher", voucher);
|
||||||
|
},
|
||||||
|
formatDate(dateStr) {
|
||||||
|
if (!dateStr) return "";
|
||||||
|
return new Date(dateStr).toLocaleDateString();
|
||||||
|
},
|
||||||
|
calculateTotal(detailList, field) {
|
||||||
|
if (!detailList || detailList.length === 0) return "0.00";
|
||||||
|
return detailList.reduce(
|
||||||
|
(sum, item) => sum + parseFloat(item[field] || 0),
|
||||||
|
0
|
||||||
|
).toFixed(2);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.finance-voucher-component {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.voucher-item {
|
||||||
|
border: 1px solid #e6e6e6;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
.voucher-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
padding: 8px 16px;
|
||||||
|
}
|
||||||
|
.header-cell {
|
||||||
|
flex: 1;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.operation-group {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
}
|
||||||
|
.total-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f0f9ff;
|
||||||
|
padding: 8px 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.total-cell {
|
||||||
|
flex: 1;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -13,6 +13,11 @@
|
|||||||
<el-form-item label="关联订单" prop="relatedOrderId">
|
<el-form-item label="关联订单" prop="relatedOrderId">
|
||||||
<el-input v-model="form.relatedOrderId" placeholder="请输入关联订单" />
|
<el-input v-model="form.relatedOrderId" placeholder="请输入关联订单" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item label="单据类型" prop="docType">
|
||||||
|
<el-select v-model="form.docType" placeholder="请选择单据类型">
|
||||||
|
<el-option v-for="item in dict.type.finance_voucher_type" :key="item.value" :label="item.label" :value="item.value" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
@@ -94,18 +99,20 @@
|
|||||||
<script>
|
<script>
|
||||||
import AmountSelect from '@/components/KLPService/AmountSelect/index.vue';
|
import AmountSelect from '@/components/KLPService/AmountSelect/index.vue';
|
||||||
import { addFinancialDocumentWithDetail, updateFinancialDocument } from "@/api/finance/financialDocument";
|
import { addFinancialDocumentWithDetail, updateFinancialDocument } from "@/api/finance/financialDocument";
|
||||||
import { updateJournalEntry } from "@/api/finance/jouneryEntry";
|
import { updateJournalEntry, addJournalEntry } from "@/api/finance/jouneryEntry";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
AmountSelect
|
AmountSelect
|
||||||
},
|
},
|
||||||
|
dicts: ['finance_voucher_type'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
docNo: undefined,
|
docNo: undefined,
|
||||||
docDate: undefined,
|
docDate: undefined,
|
||||||
relatedOrderId: undefined
|
relatedOrderId: undefined,
|
||||||
|
docType: undefined
|
||||||
},
|
},
|
||||||
tableData: [{
|
tableData: [{
|
||||||
voucherNo: '',
|
voucherNo: '',
|
||||||
@@ -167,24 +174,26 @@ export default {
|
|||||||
initData: {
|
initData: {
|
||||||
handler(newVal) {
|
handler(newVal) {
|
||||||
console.log(newVal, 'watchData');
|
console.log(newVal, 'watchData');
|
||||||
if (newVal) {
|
if (newVal && newVal.detailList) {
|
||||||
if (newVal.detailList) {
|
this.tableData = newVal.detailList;
|
||||||
this.tableData = newVal.detailList;
|
|
||||||
} else {
|
|
||||||
this.tableData = [{
|
|
||||||
voucherNo: '',
|
|
||||||
accountId: undefined,
|
|
||||||
debitAmount: 0,
|
|
||||||
creditAmount: 0,
|
|
||||||
remark: '',
|
|
||||||
voucherNo: ''
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
this.form.docNo = newVal.docNo;
|
this.form.docNo = newVal.docNo;
|
||||||
this.form.docDate = newVal.docDate;
|
this.form.docDate = newVal.docDate;
|
||||||
this.form.relatedOrderId = newVal.relatedOrderId;
|
this.form.relatedOrderId = newVal.relatedOrderId;
|
||||||
|
this.form.docType = newVal.docType;
|
||||||
this.isCreate = false;
|
this.isCreate = false;
|
||||||
} else {
|
} else {
|
||||||
|
this.form.docNo = undefined;
|
||||||
|
this.form.docDate = undefined;
|
||||||
|
this.form.relatedOrderId = undefined;
|
||||||
|
this.form.docType = undefined;
|
||||||
|
this.tableData = [{
|
||||||
|
voucherNo: '',
|
||||||
|
accountId: undefined,
|
||||||
|
debitAmount: 0,
|
||||||
|
creditAmount: 0,
|
||||||
|
remark: '',
|
||||||
|
voucherNo: ''
|
||||||
|
}]
|
||||||
this.isCreate = true;
|
this.isCreate = true;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -312,6 +321,38 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
handleCreate() {
|
handleCreate() {
|
||||||
|
if (!this.validateTableData()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. 提交数据
|
||||||
|
addFinancialDocumentWithDetail({
|
||||||
|
docNo: form.docNo,
|
||||||
|
docDate: form.docDate,
|
||||||
|
// 保持变量名一致
|
||||||
|
relatedOrderId: form.relatedOrderId,
|
||||||
|
amount: this.debitAmount,
|
||||||
|
details: validData.map((row, idx) => ({
|
||||||
|
// voucherNo: row.voucherNo,
|
||||||
|
voucherNo: row.voucherNo,
|
||||||
|
// 保持变量名一致
|
||||||
|
accountId: row.accountId,
|
||||||
|
debitAmount: row.debitAmount,
|
||||||
|
creditAmount: row.creditAmount,
|
||||||
|
remark: row.remark,
|
||||||
|
lineNo: idx + 1,
|
||||||
|
entryDate: form.docDate
|
||||||
|
}))
|
||||||
|
}).then(response => {
|
||||||
|
this.$message.success('凭证创建成功');
|
||||||
|
this.$emit('success');
|
||||||
|
}).catch(error => {
|
||||||
|
this.$message.error('凭证创建失败:' + (error.message || '未知错误'));
|
||||||
|
this.$emit('error', error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
validateTableData() {
|
||||||
// 收集所有错误信息
|
// 收集所有错误信息
|
||||||
const errors = [];
|
const errors = [];
|
||||||
const { form, tableData } = this;
|
const { form, tableData } = this;
|
||||||
@@ -321,6 +362,7 @@ export default {
|
|||||||
if (!form.docDate) errors.push('单据日期必填');
|
if (!form.docDate) errors.push('单据日期必填');
|
||||||
// 注意:原模板中是relatedOrderId,保持变量名一致
|
// 注意:原模板中是relatedOrderId,保持变量名一致
|
||||||
if (!form.relatedOrderId) errors.push('关联订单必填');
|
if (!form.relatedOrderId) errors.push('关联订单必填');
|
||||||
|
if (!form.docType) errors.push('单据类型必填');
|
||||||
|
|
||||||
// 2. 过滤有效行并检查基本存在性
|
// 2. 过滤有效行并检查基本存在性
|
||||||
const validData = tableData.filter(row => this.isRowNotEmpty(row));
|
const validData = tableData.filter(row => this.isRowNotEmpty(row));
|
||||||
@@ -365,47 +407,37 @@ export default {
|
|||||||
message: errors.map(error => `<p>${error}</p>`).join(''),
|
message: errors.map(error => `<p>${error}</p>`).join(''),
|
||||||
type: 'error'
|
type: 'error'
|
||||||
})
|
})
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
// 6. 提交数据
|
|
||||||
addFinancialDocumentWithDetail({
|
|
||||||
docNo: form.docNo,
|
|
||||||
docDate: form.docDate,
|
|
||||||
// 保持变量名一致
|
|
||||||
relatedOrderId: form.relatedOrderId,
|
|
||||||
amount: this.debitAmount,
|
|
||||||
details: validData.map((row, idx) => ({
|
|
||||||
// voucherNo: row.voucherNo,
|
|
||||||
voucherNo: row.voucherNo,
|
|
||||||
// 保持变量名一致
|
|
||||||
accountId: row.accountId,
|
|
||||||
debitAmount: row.debitAmount,
|
|
||||||
creditAmount: row.creditAmount,
|
|
||||||
remark: row.remark,
|
|
||||||
lineNo: idx + 1,
|
|
||||||
entryDate: form.docDate
|
|
||||||
}))
|
|
||||||
}).then(response => {
|
|
||||||
this.$message.success('凭证创建成功');
|
|
||||||
this.$emit('success');
|
|
||||||
}).catch(error => {
|
|
||||||
this.$message.error('凭证创建失败:' + (error.message || '未知错误'));
|
|
||||||
this.$emit('error', error);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleEdit(index) {
|
handleEdit(index) {
|
||||||
// 找到对应的列变更
|
// 找到对应的列变更
|
||||||
const row = this.tableData[index];
|
const row = this.tableData[index];
|
||||||
updateJournalEntry(row).then(response => {
|
if (row.entryId) {
|
||||||
this.$message.success('明细变更成功');
|
updateJournalEntry(row).then(response => {
|
||||||
}).catch(error => {
|
this.$message.success('明细变更成功');
|
||||||
this.$message.error('明细变更失败:' + (error.message || '未知错误'));
|
}).catch(error => {
|
||||||
});
|
this.$message.error('明细变更失败:' + (error.message || '未知错误'));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
addJournalEntry({
|
||||||
|
...row,
|
||||||
|
documentId: this.initData.documentId,
|
||||||
|
}).then(response => {
|
||||||
|
this.$message.success('明细变更成功');
|
||||||
|
}).catch(error => {
|
||||||
|
this.$message.error('明细变更失败:' + (error.message || '未知错误'));
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
handleChange() {
|
handleChange() {
|
||||||
|
if (!this.validateTableData()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
updateFinancialDocument({
|
updateFinancialDocument({
|
||||||
documentId: this.initData.documentId,
|
documentId: this.initData.documentId,
|
||||||
docNo: this.form.docNo,
|
docNo: this.form.docNo,
|
||||||
|
|||||||
@@ -73,37 +73,11 @@
|
|||||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||||
</el-row>
|
</el-row>
|
||||||
|
|
||||||
<el-table v-loading="loading" :data="financialDocumentList" @selection-change="handleSelectionChange">
|
<FinanceVoucherTable
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
:voucher-data="financialDocumentList"
|
||||||
<el-table-column label="单据ID" align="center" prop="documentId" v-if="true"/>
|
@view-voucher="handleUpdate"
|
||||||
<el-table-column label="单据编号" align="center" prop="docNo" />
|
@delete-voucher="handleDelete"
|
||||||
<el-table-column label="单据类型" align="center" prop="docType" />
|
/>
|
||||||
<el-table-column label="单据日期" align="center" prop="docDate" width="180">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<span>{{ parseTime(scope.row.docDate, '{y}-{m}-{d}') }}</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column label="单据金额" align="center" prop="amount" />
|
|
||||||
<el-table-column label="关联订单ID" align="center" prop="relatedOrderId" />
|
|
||||||
<el-table-column label="单据状态" align="center" prop="status" />
|
|
||||||
<el-table-column label="备注" align="center" prop="remark" />
|
|
||||||
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-edit"
|
|
||||||
@click="handleUpdate(scope.row)"
|
|
||||||
>修改</el-button>
|
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="text"
|
|
||||||
icon="el-icon-delete"
|
|
||||||
@click="handleDelete(scope.row)"
|
|
||||||
>删除</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
|
|
||||||
<pagination
|
<pagination
|
||||||
v-show="total > 0"
|
v-show="total > 0"
|
||||||
@@ -123,11 +97,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { listFinancialDocumentWithDetail, getFinancialDocument, delFinancialDocument, addFinancialDocument, updateFinancialDocument } from "@/api/finance/financialDocument";
|
import { listFinancialDocumentWithDetail, getFinancialDocument, delFinancialDocument, addFinancialDocument, updateFinancialDocument } from "@/api/finance/financialDocument";
|
||||||
import CreateDocument from "./components/Voucher.vue";
|
import CreateDocument from "./components/Voucher.vue";
|
||||||
|
import FinanceVoucherTable from "./components/FinanceVoucherTable.vue"; // 引入定制表格
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "FinancialDocument",
|
name: "FinancialDocument",
|
||||||
components: {
|
components: {
|
||||||
CreateDocument
|
CreateDocument,
|
||||||
|
FinanceVoucherTable
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
@@ -227,6 +203,8 @@ export default {
|
|||||||
handleAdd() {
|
handleAdd() {
|
||||||
this.reset();
|
this.reset();
|
||||||
this.open = true;
|
this.open = true;
|
||||||
|
this.currentRow = {}
|
||||||
|
// this.isCreate = true;
|
||||||
this.title = "添加财务单据";
|
this.title = "添加财务单据";
|
||||||
},
|
},
|
||||||
/** 修改按钮操作 */
|
/** 修改按钮操作 */
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div style="position: relative; padding-top: 60px;">
|
<div style="position: relative;">
|
||||||
<div style="position: absolute; top: 10px; left: 10px;">
|
<div style="position: absolute; top: 10px; left: 10px;">
|
||||||
<!-- 策略切换单选框 -->
|
<!-- 策略切换单选框 -->
|
||||||
<el-radio-group
|
<el-radio-group
|
||||||
v-model="currentStrategy"
|
v-model="currentStrategy"
|
||||||
size="small"
|
size="mini"
|
||||||
>
|
>
|
||||||
<el-radio label="stockIo">盘点单</el-radio>
|
<el-radio label="stockIo">盘点单</el-radio>
|
||||||
<el-radio label="order">订单</el-radio>
|
<el-radio label="order">订单</el-radio>
|
||||||
@@ -16,6 +16,7 @@
|
|||||||
v-model="currentId"
|
v-model="currentId"
|
||||||
:placeholder="`请选择${strategyLabels[currentStrategy]}`"
|
:placeholder="`请选择${strategyLabels[currentStrategy]}`"
|
||||||
style="width: 200px;"
|
style="width: 200px;"
|
||||||
|
size="mini"
|
||||||
>
|
>
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in currentList"
|
v-for="item in currentList"
|
||||||
@@ -26,7 +27,6 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="print-container" v-loading="loading">
|
<div class="print-container" v-loading="loading">
|
||||||
<BarCode :barcodes="drawerBarcodeData" />
|
<BarCode :barcodes="drawerBarcodeData" />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user