20260803173356

This commit is contained in:
oneao committed 2026-08-03 17:33:57 +08:00
1 parent 5f67172892
commit efd5a2bc93
21 files changed
+14314

No files matched your search

@@ -0,0 +1,204 @@
<script setup>
import { defineEmits, defineProps, ref, watch } from "vue";
import { morePermission } from "@/utils/auth";
const props = defineProps({
visible: { type: Boolean, default: false },
title: { type: String, default: "选择数据" },
params: {
type: Object,
default: () => ({
moneyId: "",
feeMoneyIds: [],
}),
},
});
const emit = defineEmits(["update:visible", "confirm"]);
const tableData = ref([]);
const localVisible = ref(props.visible);
(watch(
() => props.visible,
(val) => {
localVisible.value = val;
if (val) {
tableData.value = props.params.feeMoneyIds.map((item, index) => ({
id: index + 1,
feeMoneyId: item, // 费用币种
moneyId: props.params.moneyId, // 收款币种
exrate: item === props.params.moneyId ? 1 : "", // 汇率默认值
}));
}
},
),
{ immediate: true });
// 关闭弹窗
function handleClose() {
emit("update:visible", false);
}
// 点击确认
function handleConfirm() {
emit("confirm", tableData.value);
emit("update:visible", false);
}
const columns = [
{
prop: "feeMoneyId",
label: "费用币种",
edit_width: "90",
readOnly: "1",
},
{
prop: "moneyId",
label: "收款币种",
edit_width: "90",
readOnly: "1",
},
{
prop: "exrate",
label: "汇率",
edit_width: "110",
},
];
</script>
<template>
<el-dialog
v-model="localVisible"
:title="title"
width="400px"
:before-close="handleClose"
align-center
class="g3dialogfooter"
draggable
>
<div class="g3pagecontainer">
<div class="g3container">
<vxe-table
ref="tableRef"
border
stripe
header-align="center"
:data="tableData"
:filter-config="{
showIcon: false,
}"
:column-drag-config="{
showIcon: false,
trigger: 'cell',
}"
:row-config="{
useKey: true,
keyField: 'id',
}"
:cell-config="{
height: 26,
}"
:column-config="{
resizable: true,
drag: true,
}"
:edit-config="{
trigger: 'click',
mode: 'row',
autoClear: false,
showStatus: false,
showIcon: false,
}"
show-overflow
show-header-overflow
show-footer-overflow
height="100%"
>
<vxe-column
v-for="column in columns"
:key="column.prop"
:field="column.prop"
:title="column.label"
:width="column.edit_width || column.width"
align="center"
:edit-render="{ autoFocus: true, enabled: true }"
>
<template #edit="{ row }">
<el-input
v-model="row[column.prop]"
size="small"
:disabled="column.readOnly === '1'"
/>
</template>
</vxe-column>
</vxe-table>
</div>
</div>
<template #footer>
<div class="dialogfooter">
<el-button @click="handleClose" class="g3button"> 取消 </el-button>
<el-button
type="primary"
@click="handleConfirm"
class="g3button"
:disabled="morePermission(3)"
>
确认
</el-button>
</div>
</template>
</el-dialog>
</template>
<style lang="scss" scoped>
.g3pagecontainer {
box-sizing: border-box;
display: flex;
width: 100%;
height: 180px;
padding: 2px 2px;
}
.g3container {
display: flex;
flex: 1;
flex-direction: column;
height: 100%;
padding: 10px 10px 0px 10px;
background-color: #ffffff;
}
.dialogfooter {
margin: 8px 0px 16px 0px;
padding-right: 10px;
}
.g3button {
border-radius: 8px;
}
:deep(.vxe-cell) {
padding: 0px !important;
}
</style>
<style>
.el-dialog.g3dialogfooter {
--el-dialog-padding-primary: 4px;
}
.el-dialog.g3dialogfooter .el-dialog__header {
padding: 3px 20px 5px 0px;
}
.el-dialog.g3dialogfooter .el-dialog__title {
color: #1f2225;
margin-left: 11px;
font-size: 14px;
font-weight: 600;
font-family:
v-sans,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol";
}
.el-dialog.g3dialogfooter .el-dialog__headerbtn {
width: 38px;
height: 42px;
}
</style>
+999
View File
@@ -0,0 +1,999 @@
import { app } from "@/main";
import { createVNode, render, ref } from "vue";
import { ElMessage } from "element-plus";
import { handleMappingConfig } from "@/utils/dodata.js";
import { getDefaultValue, getFieldString, getMoneyExRate } from "@/utils/g3Funlib.js";
import { useUserStore } from "@/store/user.js";
import { getDate, getDateAfter, getDateTime } from "@/utils/time.js";
import { getSFId } from "@/utils/common.js";
import { diffData } from "@/utils/dataDiffUtils.js";
import {
getobjectApi,
saveobjtlockApi,
loaddatabysqlApi,
saveobjtApi,
saveobjtV5Api,
loaddataApi,
} from "@/utils/doSql.js";
import math from "@/utils/math.js";
import router from "@/router/index.js";
import axios from "@/utils/axios";
import Link from "./link.vue";
export function openFeeLink(subid, type) {
const container = document.createElement("div");
document.body.appendChild(container);
let visible = true;
const vnode = createVNode(Link, {
subid,
type,
modelValue: visible,
"onUpdate:modelValue": (val) => {
visible = val;
},
onClose() {
render(null, container);
container.remove();
},
});
vnode.appContext = app._context;
render(vnode, container);
}
/**
* 生成账单
* @export
* @param {*} rows 选中行
* @param {*} type 类型
*/
export async function generateBill_old(subids, type) {
if (!Array.isArray(subids) || subids.length === 0) {
throw new Error("请选择操作行");
}
const userStore = useUserStore();
const sqlcondition = `AND subid IN (${subids.map((id) => `'${id}'`).join(",")})`;
const mappingid = type === "应收" ? "cwtoysbill" : "cwtoyfbill";
const viewname_main = type === "应收" ? "v_cw_ysbill" : "v_cw_yfbill";
const viewname_sub = type === "应收" ? "v_cw_ysbillsub" : "v_cw_yfbillsub";
const maindata = ref({});
const maindataorg = ref({});
const subdata = ref([]);
const subdataorg = ref([]);
const subdatacw = ref([]);
await handleMappingConfig(mappingid, sqlcondition, subdata);
if (subdata.value.length === 0) {
throw new Error("无有效数据");
}
// // 数据库再次校验,防止并发重复生成账单
// const subdatas = await loaddataApi(
// viewname_sub,
// `mx_fee_id IN (${subdata.value.map((x) => `'${x.mx_fee_id}'`).join(",")})`,
// );
// if (subdatas.length > 0) {
// throw new Error("选中数据已制单,请检查!");
// }
// 结算单位一致性校验
const tmpdwid = subdata.value[0].mx_dw_id || "";
for (const row of subdata.value) {
if ((row.mx_dw_id || "") !== tmpdwid) {
throw new Error("结算单位不一致,请检查!");
}
}
await getDefaultValue(maindata, viewname_main);
const mainid = await getSFId();
maindata.value = {
...maindata.value,
b_id: mainid,
b_state: "草拟",
b_module_id: type,
};
// const userid = userStore.getUserId();
// const updatetime = getDateTime();
for (const [index, item] of subdata.value.entries()) {
item.mx_xh = index;
item.father = mainid;
// subdatacw.value.push({
// subid: item.mx_fee_id,
// mx_bill_id: mainid,
// mx_bill_updatedatetime: updatetime,
// mx_bill_updateuser_id: userid,
// });
}
const first = subdata.value[0];
// maindata.value.v_dw_name = first.mx_dw_name;
let today = getDate();
maindata.value.b_dw_id = first.mx_dw_id;
maindata.value.b_amount = math
.add(
...subdata.value.map((row) => {
const amount = Number(row.mx_amount_rmb || 0);
if (type === "应收") {
return row.mx_type_id === "应收" ? amount : -amount;
}
return row.mx_type_id === "应付" ? amount : -amount;
}),
)
.toFixed(3);
maindata.value.b_date = today;
// 币种 desc
const amountData = subdata.value.reduce(
(result, row) => {
const moneytype = row.mx_fee_money_id || "";
const sign = type === row.mx_type_id ? 1 : -1;
const billAmount = math.multiply(row.mx_fee_amount || 0, sign);
const rmbAmount = math.multiply(row.mx_amount_rmb || 0, sign);
result.moneyMap[moneytype] = math.add(result.moneyMap[moneytype] || 0, billAmount);
result.rmbTotal = math.add(result.rmbTotal, rmbAmount);
return result;
},
{
moneyMap: {},
rmbTotal: 0,
},
);
maindata.value.b_amount_desc = [
...Object.entries(amountData.moneyMap).map(([type, amount]) => `${type}:${amount.toFixed(2)}`),
`本币种合计:${amountData.rmbTotal.toFixed(2)}`,
].join(";");
// 获取该合作伙伴的账龄、合同收款日、开票信息
const companydata = await getobjectApi("v_b_othercompany_all", "b_id", maindata.value.b_dw_id);
let zl = companydata.b_zl || 0;
maindata.value.b_zl = zl;
maindata.value.b_plandate = getDateAfter(today, zl);
maindata.value.b_dw_invaccount = companydata.b_invaccount;
maindata.value.b_dw_bankacount = companydata.b_bankacount;
const maindataChanges = diffData(maindata.value, maindataorg.value, "b_id", {
isSingle: true,
});
const subdataChanges = diffData(subdata.value, subdataorg.value, "subid");
if (!maindataChanges.hasChanges && !subdataChanges.hasChanges) {
return;
}
const requestData = [
{
tableName: "cw_bill",
keyField: "b_id",
inserts: maindataChanges.insertdata,
updates: [],
deletes: [],
},
{
tableName: "cw_billsub",
keyField: "subid",
inserts: subdataChanges.insertdata,
updates: [],
deletes: [],
},
];
await saveobjtV5Api(requestData);
const params = {
b_id: maindata.value.b_id,
};
try {
const response = await axios.post("fee/billconfirm", params);
if (response.data.success === true) {
ElMessage.success(response.data.message || "核销成功");
} else {
ElMessage.warning(response.data.message || "核销失败");
}
} catch (error) {
ElMessage.error("请求失败:" + error.message);
}
router.push({
name: type === "应收" ? "ysdetailbill" : "yfdetailbill",
query: {
id: mainid,
op: "mod",
},
});
}
/**
* 生成账单
* @export
* @param {*} rows 选中行
* @param {*} type 类型
*/
export async function generateBill(subids, configid) {
if (!Array.isArray(subids) || subids.length === 0) {
throw new Error("请选择操作行");
}
if (!configid) {
throw new Error("请传入有效数据");
}
const configs = await loaddataApi("s_module_config", `b_id = '${configid}'`);
if (configs.length === 0) {
throw new Error("配置无效,请检查配置!");
}
const moduleConfig = configs[0];
const sqlcondition = `AND subid IN (${subids.map((id) => `'${id}'`).join(",")})`;
const mappingid = moduleConfig.b_mapid;
const viewname_main = moduleConfig.b_viewtable;
const maindata = ref({});
const maindataorg = ref({});
const subdata = ref([]);
const subdataorg = ref([]);
await handleMappingConfig(mappingid, sqlcondition, subdata);
if (subdata.value.length === 0) {
throw new Error("无有效数据");
}
// 结算单位一致性校验
const tmpdwid = subdata.value[0].mx_dw_id || "";
for (const row of subdata.value) {
if ((row.mx_dw_id || "") !== tmpdwid) {
throw new Error("结算单位不一致,请检查!");
}
}
await getDefaultValue(maindata, viewname_main);
const mainid = await getSFId();
const type = moduleConfig.b_cwtype;
maindata.value = {
...maindata.value,
b_id: mainid,
b_state: "草拟",
b_cwtype: type,
b_module_id: moduleConfig.b_moduleid,
};
for (const [index, item] of subdata.value.entries()) {
item.mx_xh = index;
item.father = mainid;
}
const first = subdata.value[0];
// maindata.value.v_dw_name = first.mx_dw_name;
let today = getDate();
maindata.value.b_dw_id = first.mx_dw_id;
maindata.value.b_amount = math
.add(
...subdata.value.map((row) => {
const amount = Number(row.mx_amount_rmb || 0);
if (type === "应收") {
return row.mx_type_id === "应收" ? amount : -amount;
}
return row.mx_type_id === "应付" ? amount : -amount;
}),
)
.toFixed(3);
maindata.value.b_date = today;
// 币种 desc
const amountData = subdata.value.reduce(
(result, row) => {
const moneytype = row.mx_fee_money_id || "";
const sign = type === row.mx_type_id ? 1 : -1;
const billAmount = math.multiply(row.mx_fee_amount || 0, sign);
const rmbAmount = math.multiply(row.mx_amount_rmb || 0, sign);
result.moneyMap[moneytype] = math.add(result.moneyMap[moneytype] || 0, billAmount);
result.rmbTotal = math.add(result.rmbTotal, rmbAmount);
return result;
},
{
moneyMap: {},
rmbTotal: 0,
},
);
maindata.value.b_amount_desc = [
...Object.entries(amountData.moneyMap).map(([type, amount]) => `${type}:${amount.toFixed(2)}`),
`本币种合计:${amountData.rmbTotal.toFixed(2)}`,
].join(";");
// 获取该合作伙伴的账龄、合同收款日、开票信息
const companydata = await getobjectApi("v_b_othercompany_all", "b_id", maindata.value.b_dw_id);
let zl = companydata.b_zl || 0;
maindata.value.b_zl = zl;
maindata.value.b_plandate = getDateAfter(today, zl);
maindata.value.b_dw_invaccount = companydata.b_invaccount;
maindata.value.b_dw_bankacount = companydata.b_bankacount;
const maindataChanges = diffData(maindata.value, maindataorg.value, "b_id", {
isSingle: true,
});
const subdataChanges = diffData(subdata.value, subdataorg.value, "subid");
if (!maindataChanges.hasChanges && !subdataChanges.hasChanges) {
return;
}
const requestData = [
{
tableName: "cw_bill",
keyField: "b_id",
inserts: maindataChanges.insertdata,
updates: [],
deletes: [],
},
{
tableName: "cw_billsub",
keyField: "subid",
inserts: subdataChanges.insertdata,
updates: [],
deletes: [],
},
];
await saveobjtV5Api(requestData);
// 保存成功,开始核销,异常交给外部自己处理
const feeids = subdata.value
.map((item) => item.mx_fee_id)
.filter(Boolean)
.join(",");
const params = {
b_id: maindata.value.b_id,
fee_ids: feeids,
};
try {
const response = await axios.post("fee/billconfirm", params);
if (response.data.success === true) {
ElMessage.success(response.data.message || "核销成功");
} else {
ElMessage.warning(response.data.message || "核销失败");
}
} catch (error) {
ElMessage.error("请求失败:" + error.message);
}
router.push({
name: type === "应收" ? "ysdetailbill" : "yfdetailbill",
query: {
id: mainid,
op: "mod",
},
});
}
// 发票
export async function generateInvoice_old(subids, type) {
if (!Array.isArray(subids) || subids.length === 0) {
throw new Error("请选择操作行");
}
const userStore = useUserStore();
const sqlcondition = `AND subid IN (${subids.map((id) => `'${id}'`).join(",")})`;
const mappingid = type === "应收" ? "cwtoysinvoice" : "cwtoyfinvoice";
const viewname_main = type === "应收" ? "v_cw_ysinvoice" : "v_cw_yfinvoice";
const viewname_sub = type === "应收" ? "v_cw_ysinvoicesub" : "v_cw_yfinvoicesub";
const maindata = ref({});
const maindataorg = ref({});
const subdata = ref([]);
const subdataorg = ref([]);
const subdatacw = ref([]);
await handleMappingConfig(mappingid, sqlcondition, subdata);
if (subdata.value.length === 0) {
throw new Error("无有效数据");
}
// 数据库再次校验,防止并发重复生成发票
// const subdatas = await loaddataApi(
// viewname_sub,
// `mx_fee_id IN (${subdata.value.map((x) => `'${x.mx_fee_id}'`).join(",")})`,
// );
// if (subdatas.length > 0) {
// throw new Error("选中数据已开发票,请检查!");
// }
// 不同币种 不同结算单位
const tmpdwid = subdata.value[0].mx_dw_id || "";
const moneyid = subdata.value[0].mx_fee_money_id || "";
for (const row of subdata.value) {
if ((row.mx_dw_id || "") !== tmpdwid) {
throw new Error("结算单位不一致,请检查!");
}
if ((row.mx_fee_money_id || "") !== moneyid) {
throw new Error("币种不一致,请检查!");
}
}
await getDefaultValue(maindata, viewname_main);
const mainid = await getSFId();
maindata.value = {
...maindata.value,
b_id: mainid,
b_state: "草拟",
b_module_id: type,
};
const userid = userStore.getUserId();
const updatetime = getDateTime();
for (const [index, item] of subdata.value.entries()) {
const subid = await getSFId();
item.subid = subid;
item.mx_xh = index;
item.father = maindata.value.b_id;
// subdatacw.value.push({
// subid: item.mx_fee_id,
// mx_version: item.mx_version,
// mx_invoice_id: mainid,
// mx_invoice_updatedatetime: updatetime,
// mx_invoice_updateuser_id: userid,
// });
}
const first = subdata.value[0];
maindata.value.v_dw_name = first.mx_dw_name;
maindata.value.b_dw_id = first.mx_dw_id;
maindata.value.b_money_id = first.mx_fee_money_id;
maindata.value.b_amount = math
.add(...subdata.value.map((row) => row.mx_invoice_amount || 0))
.toFixed(2);
maindata.value.b_yw_ids = getFieldString(subdata.value, "b_ywno");
maindata.value.b_date = getDate();
const maindataChanges = diffData(maindata.value, maindataorg.value, "b_id", { isSingle: true });
const subdataChanges = diffData(subdata.value, subdataorg.value, "subid");
if (!maindataChanges.hasChanges && !subdataChanges.hasChanges) {
return;
}
const requestData = [
{
tableName: "cw_invoice",
keyField: "b_id",
inserts: maindataChanges.insertdata,
updates: [],
deletes: [],
},
{
tableName: "cw_invoicesub",
keyField: "subid",
inserts: subdataChanges.insertdata,
updates: [],
deletes: [],
},
];
await saveobjtV5Api(requestData);
const params = {
b_id: maindata.value.b_id,
};
try {
const response = await axios.post("fee/invoiceconfirm", params);
if (response.data.success === true) {
ElMessage.success(response.data.message || "核销成功");
} else {
ElMessage.warning(response.data.message || "核销失败");
}
} catch (error) {
ElMessage.error("请求失败:" + error.message);
}
router.push({
name: type === "应收" ? "ysdetailinvoice" : "yfdetailinvoice",
query: {
id: mainid,
op: "mod",
},
});
}
export async function generateInvoice(subids, configid) {
if (!Array.isArray(subids) || subids.length === 0) {
throw new Error("请选择操作行");
}
if (!configid) {
throw new Error("请传入有效数据");
}
const configs = await loaddataApi("s_module_config", `b_id = '${configid}'`);
if (configs.length === 0) {
throw new Error("配置无效,请检查配置!");
}
const moduleConfig = configs[0];
const sqlcondition = `AND subid IN (${subids.map((id) => `'${id}'`).join(",")})`;
const mappingid = moduleConfig.b_mapid;
const viewname_main = moduleConfig.b_viewtable;
const maindata = ref({});
const maindataorg = ref({});
const subdata = ref([]);
const subdataorg = ref([]);
await handleMappingConfig(mappingid, sqlcondition, subdata);
if (subdata.value.length === 0) {
throw new Error("无有效数据");
}
// 不同币种 不同结算单位
const tmpdwid = subdata.value[0].mx_dw_id || "";
const moneyid = subdata.value[0].mx_fee_money_id || "";
for (const row of subdata.value) {
if ((row.mx_dw_id || "") !== tmpdwid) {
throw new Error("结算单位不一致,请检查!");
}
if ((row.mx_fee_money_id || "") !== moneyid) {
throw new Error("币种不一致,请检查!");
}
}
await getDefaultValue(maindata, viewname_main);
const mainid = await getSFId();
const type = moduleConfig.b_cwtype;
maindata.value = {
...maindata.value,
b_id: mainid,
b_state: "草拟",
b_cwtype: type,
b_module_id: moduleConfig.b_moduleid,
};
for (const [index, item] of subdata.value.entries()) {
const subid = await getSFId();
item.subid = subid;
item.mx_xh = index;
item.father = maindata.value.b_id;
}
const first = subdata.value[0];
maindata.value.v_dw_name = first.mx_dw_name;
maindata.value.b_dw_id = first.mx_dw_id;
maindata.value.b_money_id = first.mx_fee_money_id;
maindata.value.b_amount = math
.add(...subdata.value.map((row) => row.mx_invoice_amount || 0))
.toFixed(2);
maindata.value.b_yw_ids = getFieldString(subdata.value, "b_ywno");
maindata.value.b_date = getDate();
const maindataChanges = diffData(maindata.value, maindataorg.value, "b_id", { isSingle: true });
const subdataChanges = diffData(subdata.value, subdataorg.value, "subid");
if (!maindataChanges.hasChanges && !subdataChanges.hasChanges) {
return;
}
const requestData = [
{
tableName: "cw_invoice",
keyField: "b_id",
inserts: maindataChanges.insertdata,
updates: [],
deletes: [],
},
{
tableName: "cw_invoicesub",
keyField: "subid",
inserts: subdataChanges.insertdata,
updates: [],
deletes: [],
},
];
await saveobjtV5Api(requestData);
// 保存成功,开始核销,异常交给外部自己处理
const feeids = subdata.value
.map((item) => item.mx_fee_id)
.filter(Boolean)
.join(",");
const params = {
b_id: maindata.value.b_id,
fee_ids: feeids,
};
try {
const response = await axios.post("fee/invoiceconfirm", params);
if (response.data.success === true) {
ElMessage.success(response.data.message || "核销成功");
} else {
ElMessage.warning(response.data.message || "核销失败");
}
} catch (error) {
ElMessage.error("请求失败:" + error.message);
}
router.push({
name: type === "应收" ? "ysdetailinvoice" : "yfdetailinvoice",
query: {
id: mainid,
op: "mod",
},
});
}
// 收付单
export async function generateSfd_old(subids, type) {
if (!Array.isArray(subids) || subids.length === 0) {
throw new Error("请选择操作行");
}
const userStore = useUserStore();
const sqlcondition = `AND subid IN (${subids.map((id) => `'${id}'`).join(",")})`;
const mappingid = type === "应收" ? "cwtoskd" : "cwtofkd";
const viewname_main = type === "应收" ? "v_cw_skd" : "v_cw_fkd";
const viewname_sub = type === "应收" ? "v_cw_skdsub" : "v_cw_fkdsub";
const maindata = ref({});
const maindataorg = ref({});
const subdata = ref([]);
const subdataorg = ref([]);
await handleMappingConfig(mappingid, sqlcondition, subdata);
if (subdata.value.length === 0) {
throw new Error("无有效数据");
}
// 不同币种 不同结算单位
const tmpdwid = subdata.value[0].mx_dw_id || "";
const moneyid = subdata.value[0].mx_moneytype_id || "";
for (const row of subdata.value) {
if ((row.mx_dw_id || "") !== tmpdwid) {
throw new Error("结算单位不一致,请检查!");
}
// if ((row.mx_moneytype_id || "") !== moneyid) {
// throw new Error("币种不一致,请检查!");
// }
}
await getDefaultValue(maindata, viewname_main);
const mainid = await getSFId();
maindata.value = {
...maindata.value,
b_id: mainid,
b_state: "草拟",
b_module_id: type === "应收" ? "实收" : "实付",
};
for (const [index, item] of subdata.value.entries()) {
const subid = await getSFId();
item.subid = subid;
item.mx_xh = index;
item.father = maindata.value.b_id;
}
const first = subdata.value[0];
maindata.value.v_dw_name = first.mx_dw_name;
maindata.value.b_dw_id = first.mx_dw_id;
maindata.value.b_money_id = first.mx_fee_money_id;
maindata.value.b_exrate = await getMoneyExRate({
rows: subdata.value,
});
// let amount = math.add(...subdata.value.map((row) => row.mx_sfd_totalamount_not || 0)).toFixed(3);
// maindata.value.b_amount_sj = amount;
// maindata.value.b_amount_hx = amount;
// maindata.value.b_amount = amount;
maindata.value.b_amount_sj = 0;
maindata.value.b_amount_hx = 0;
maindata.value.b_amount = 0;
maindata.value.b_amount_nothx = 0;
maindata.value.b_date = getDate();
maindata.value.b_yw_ids = getFieldString(subdata.value, "b_ywno");
maindata.value.b_bill_ids = getFieldString(subdata.value, "mx_bill_ywno");
maindata.value.b_inv_ids = getFieldString(subdata.value, "mx_invoice_ywno");
const maindataChanges = diffData(maindata.value, maindataorg.value, "b_id", { isSingle: true });
const subdataChanges = diffData(subdata.value, subdataorg.value, "subid");
if (!maindataChanges.hasChanges && !subdataChanges.hasChanges) {
return;
}
const requestData = [
{
tableName: "cw_sfd",
keyField: "b_id",
inserts: maindataChanges.insertdata,
updates: [],
deletes: [],
},
{
tableName: "cw_sfdsub",
keyField: "subid",
inserts: subdataChanges.insertdata,
updates: [],
deletes: [],
},
];
await saveobjtV5Api(requestData);
// 保存成功,开始核销,异常交给外部自己处理
const feeids = subdata.value
.map((item) => item.mx_fee_id)
.filter(Boolean)
.join(",");
const params = {
b_id: maindata.value.b_id,
fee_ids: feeids,
};
try {
const response = await axios.post("fee/feewriteoffbatch", params);
if (response.data.success === true) {
ElMessage.success(response.data.message || "核销成功");
} else {
ElMessage.warning(response.data.message || "核销失败");
}
} catch (error) {
ElMessage.error("请求失败:" + error.message);
}
router.push({
name: type === "应收" ? "ysdetailskd" : "yfdetailfkd",
query: {
id: mainid,
op: "mod",
},
});
}
export async function generateSfd(subids, configid) {
if (!Array.isArray(subids) || subids.length === 0) {
throw new Error("请选择操作行");
}
if (!configid) {
throw new Error("请传入有效数据");
}
const configs = await loaddataApi("s_module_config", `b_id = '${configid}'`);
if (configs.length === 0) {
throw new Error("配置无效,请检查配置!");
}
const moduleConfig = configs[0];
const sqlcondition = `AND subid IN (${subids.map((id) => `'${id}'`).join(",")})`;
const mappingid = moduleConfig.b_mapid;
const viewname_main = moduleConfig.b_viewtable;
const maindata = ref({});
const maindataorg = ref({});
const subdata = ref([]);
const subdataorg = ref([]);
await handleMappingConfig(mappingid, sqlcondition, subdata);
if (subdata.value.length === 0) {
throw new Error("无有效数据");
}
// 不同币种 不同结算单位
const tmpdwid = subdata.value[0].mx_dw_id || "";
for (const row of subdata.value) {
if ((row.mx_dw_id || "") !== tmpdwid) {
throw new Error("结算单位不一致,请检查!");
}
}
await getDefaultValue(maindata, viewname_main);
const mainid = await getSFId();
const type = moduleConfig.b_cwtype;
maindata.value = {
...maindata.value,
b_id: mainid,
b_state: "草拟",
b_cwtype: type,
b_module_id: moduleConfig.b_moduleid,
};
for (const [index, item] of subdata.value.entries()) {
const subid = await getSFId();
item.subid = subid;
item.mx_xh = index;
item.father = maindata.value.b_id;
}
const first = subdata.value[0];
maindata.value.v_dw_name = first.mx_dw_name;
maindata.value.b_dw_id = first.mx_dw_id;
maindata.value.b_money_id = first.mx_fee_money_id;
maindata.value.b_exrate = await getMoneyExRate({
rows: subdata.value,
});
// let amount = math.add(...subdata.value.map((row) => row.mx_sfd_totalamount_not || 0)).toFixed(3);
// maindata.value.b_amount_sj = amount;
// maindata.value.b_amount_hx = amount;
// maindata.value.b_amount = amount;
maindata.value.b_amount_sj = 0;
maindata.value.b_amount_hx = 0;
maindata.value.b_amount = 0;
maindata.value.b_amount_nothx = 0;
maindata.value.b_date = getDate();
maindata.value.b_yw_ids = getFieldString(subdata.value, "b_ywno");
maindata.value.b_bill_ids = getFieldString(subdata.value, "mx_bill_ywno");
maindata.value.b_inv_ids = getFieldString(subdata.value, "mx_invoice_ywno");
const maindataChanges = diffData(maindata.value, maindataorg.value, "b_id", { isSingle: true });
const subdataChanges = diffData(subdata.value, subdataorg.value, "subid");
if (!maindataChanges.hasChanges && !subdataChanges.hasChanges) {
return;
}
const requestData = [
{
tableName: "cw_sfd",
keyField: "b_id",
inserts: maindataChanges.insertdata,
updates: [],
deletes: [],
},
{
tableName: "cw_sfdsub",
keyField: "subid",
inserts: subdataChanges.insertdata,
updates: [],
deletes: [],
},
];
await saveobjtV5Api(requestData);
// 保存成功,开始核销,异常交给外部自己处理
const feeids = subdata.value
.map((item) => item.mx_fee_id)
.filter(Boolean)
.join(",");
const params = {
b_id: maindata.value.b_id,
fee_ids: feeids,
};
try {
const response = await axios.post("fee/feewriteoffbatch", params);
if (response.data.success === true) {
ElMessage.success(response.data.message || "核销成功");
} else {
ElMessage.warning(response.data.message || "核销失败");
}
} catch (error) {
ElMessage.error("请求失败:" + error.message);
}
router.push({
name: type === "应收" ? "ysdetailskd" : "yfdetailfkd",
query: {
id: mainid,
op: "mod",
},
});
}
function showSaveResultMessage(response) {
const data = response.data?.data || {};
const { insert, update, delete: del, insertBlocked, updateBlocked, deleteBlocked } = data;
const totalSuccess = (insert || 0) + (update || 0) + (del || 0);
const totalBlocked = (insertBlocked || 0) + (updateBlocked || 0) + (deleteBlocked || 0);
// 完全没有成功,也没有拦截(一般不会走到)
if (totalSuccess === 0 && totalBlocked === 0) {
ElMessage.info("没有数据发生变化");
return;
}
// ✅ 完全成功
if (totalBlocked === 0) {
ElMessage.success(`保存成功(新增 ${insert || 0},更新 ${update || 0},删除 ${del || 0})`);
return;
}
// ⚠️ 有拦截(重点)
let msg = "保存成功,但部分数据被业务规则拦截";
const parts = [];
if (insertBlocked > 0) parts.push(`新增 ${insertBlocked} 条`);
if (updateBlocked > 0) parts.push(`更新 ${updateBlocked} 条`);
if (deleteBlocked > 0) parts.push(`删除 ${deleteBlocked} 条`);
msg += `(${parts.join(",")})`;
// ✅ 用 warning 而不是 error
ElMessage.warning(msg);
}
+234
View File
@@ -0,0 +1,234 @@
<script setup>
import { ref } from "vue";
import { ElMessage } from "element-plus";
import { getTableColumns } from "@/utils/dodata";
import { formatValueByFormat, getAlignByFormat } from "@/utils/column";
import { loaddataApi } from "@/utils/doSql";
import { useRouter } from "vue-router";
const props = defineProps({
subid: {
default: "",
},
type: {
default: "",
},
});
const router = useRouter();
const visible = defineModel(false);
const activetab = ref("账单");
const loading = ref(false);
const columns = ref([]);
const subtable = ref([]);
const subdata = ref(null);
async function handleOpened() {
if (!props.subid || !props.type) {
ElMessage.warning("传递信息无效");
visible.value = false;
return;
}
loaddata();
}
function handleClosed() {
loading.value = true;
activetab.value = "账单";
columns.value = [];
subtable.value = [];
subdata.value = null;
}
async function loaddata() {
try {
loading.value = true;
const type = props.type;
const tab = activetab.value;
// 获取视图
const viewMap = {
账单: {
应收: "v_cw_ysbill",
应付: "v_cw_yfbill",
},
发票: {
应收: "v_cw_ysinvoice",
应付: "v_cw_yfinvoice",
},
记录: {
应收: "v_cw_skd",
应付: "v_cw_fkd",
},
};
const viewname = viewMap[tab]?.[type];
const datas = await loaddataApi(
type === "应收" ? "v_cw_fee_s" : "v_cw_fee_f",
`subid = '${props.subid}'`,
);
if (datas.length === 0) {
ElMessage.warning("数据无效");
return;
}
subdata.value = datas[0];
const result = await getTableColumns(viewname);
if (result.success) {
columns.value = result.data;
} else {
ElMessage.error(`加载失败: ${result.error}`);
return;
}
let data = [];
if (tab === "账单") {
if (subdata.value.mx_bill_id) {
data = await loaddataApi(viewname, `b_id = '${subdata.value.mx_bill_id}'`);
}
} else if (tab === "发票") {
if (subdata.value.mx_invoice_id) {
data = await loaddataApi(viewname, `b_id = '${subdata.value.mx_invoice_id}'`);
}
} else if (tab === "记录") {
if (subdata.value.mx_sfd_id) {
const subview = type === "应收" ? "v_cw_skdsub" : "v_cw_fkdsub";
const subdatas = await loaddataApi(subview, `mx_fee_id = '${subdata.value.subid}'`);
const fathers = subdatas.map((item) => item.father).filter(Boolean);
if (fathers.length > 0) {
const condition = `b_id in (${fathers.map((id) => `'${id}'`).join(",")})`;
data = await loaddataApi(viewname, condition);
}
}
}
subtable.value = data || [];
} catch (error) {
console.log(error);
} finally {
loading.value = false;
}
}
function handleTabChange() {
loaddata();
}
function handleToDetail(row) {
const viewMap = {
账单: {
应收: "/cw/ys/detailbill",
应付: "/cw/yf/detailbill",
},
发票: {
应收: "/cw/ys/detailinvoice",
应付: "/cw/yf/detailinvoice",
},
记录: {
应收: "/cw/ys/detailskd",
应付: "/cw/yf/detailfkd",
},
};
const type = props.type;
const tab = activetab.value;
const path = viewMap[tab]?.[type];
if (!path) {
ElMessage.warning("未找到对应页面");
return;
}
router.push({
path,
query: {
id: row.b_id,
op: "mod",
},
});
}
</script>
<template>
<el-dialog
v-model="visible"
title="费用关联信息"
width="800"
@opened="handleOpened"
@closed="handleClosed"
>
<el-tabs v-model="activetab" @tab-change="handleTabChange">
<el-tab-pane label="账单" name="账单" />
<el-tab-pane label="发票" name="发票" />
<el-tab-pane :label="props.type === '应收' ? '收款管理' : '付款管理'" name="记录" />
</el-tabs>
<vxe-table
border
stripe
header-align="center"
:data="subtable"
:loading="loading"
:sort-config="{
// showIcon: false,
trigger: 'cell',
}"
:filter-config="{
showIcon: false,
}"
size="small"
:cell-config="{
height: 26,
}"
show-overflow
show-header-overflow
height="400px"
>
<vxe-column field="seq" type="seq" width="50" align="center" title=" " fixed="left" />
<vxe-column
v-for="column in columns"
:key="column.prop"
:field="column.prop"
:title="column.label"
:width="column.width"
:align="getAlignByFormat(column.displayFormat)"
:params="column"
sortable
>
<template #default="{ row }">
<template v-if="column.edit_type == 'checkbox'">
<el-checkbox v-model="row[column.prop]" disabled true-value="1" false-value="0" />
</template>
<template v-else-if="['b_id', 'father', 'b_ywno'].includes(column.prop)">
<span class="g3-color" @click="handleToDetail(row)">
{{ row[column.prop] }}
</span>
</template>
<template v-else>
{{ formatValueByFormat(row[column.prop], column.displayFormat) }}
</template>
</template>
</vxe-column>
</vxe-table>
<template #footer> </template>
</el-dialog>
</template>
<style lang="css" scoped>
.g3-color {
color: #409eff;
cursor: pointer;
}
</style>