| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627 |
- <template>
- <div>
- <el-form :ref="'form'" :model="tableForm">
- <ele-pro-table
- ref="table"
- :needPage="false"
- :columns="columns"
- :datasource="tableForm.detailList"
- row-key="id"
- class="time-form"
- >
- <template v-slot:toolbar>
- <span>本次开票合计:{{ totalAmountTotalPrice }}</span>
- </template>
-
- <template v-slot:invoiceAmount="scope">
- <el-form-item
- style="width: 100%;"
- :prop="'detailList.' + scope.$index + '.invoiceAmount'"
-
- >
- <span v-if="dialogType === 'view'"> {{ scope.row.invoiceAmount }}</span>
- <el-input v-else v-model="scope.row.invoiceAmount" type="number" @input="(val) => invoiceAmountChange(val, scope.row, scope.$index)"></el-input>
- </el-form-item>
- </template>
- <!-- :rules="[
- {
- required: false,
- message: '请输入开票金额',
- trigger: 'blur'
- },
- {
- required: false,
- validator: (rule, value, callback) => {
- if (value === undefined || value === null || value === '') {
- callback('请输入开票金额');
- } else if (parseFloat(value) < 0 || parseFloat(value) > scope.row.defaultAmountTotalPrice) {
- callback('开票金额不能小于0且小于等于本次开票合计');
- } else {
- callback();
- }
- },
- trigger: 'blur'
- }
- ]" -->
- <template v-slot:taxRate="scope">
- <el-form-item
- style="width: 100%;"
- :prop="'detailList.' + scope.$index + '.taxRate'"
- :rules="[
- {
- required: true,
- message: '请输入税率',
- trigger: 'blur'
- },
- {
- validator: (rule, value, callback) => {
- if (value === undefined || value === null || value === '') {
- callback('请输入税率');
- } else if (parseFloat(value) < 0) {
- callback('税率不能小于0');
- } else {
- callback();
- }
- },
- trigger: 'blur'
- }
- ]"
- >
- <span v-if="dialogType === 'view'"> {{ scope.row.taxRate }}</span>
- <el-input v-else v-model="scope.row.taxRate" type="number" @input="getNotaxSinglePrice(scope.row, 0, scope.$index)" style="width: 80%;"></el-input>%
- </el-form-item>
- </template>
- </ele-pro-table>
- </el-form>
-
- </div>
- </template>
- <script>
- export default {
- name: 'tableInfo',
- components: {},
- props: {
- dialogType: {
- type: String,
- default: ''
- },
- isOtherSourceFlag: {
- type: Boolean,
- default: false
- },
- contactData: {
- type: Object,
- default: () => {
- return {};
- }
- },
- invoiceAmount: {
- type: Number,
- default: 0
- }
- },
- data() {
- return {
- columns: [
- {
- width: 45,
- type: 'index',
- columnKey: 'index',
- align: 'center',
- fixed: 'left'
- },
- {
- width: 100,
- prop: 'key',
- label: '编码',
- align: 'center'
- },
- {
- width: 100,
- prop: 'typeName',
- label: '类型',
- slot: 'typeName',
- align: 'center'
- },
- // {
- // minWidth: 100,
- // prop: 'sourceCode',
- // label: '类型编码',
- // slot: 'sourceCode',
- // align: 'center'
- // },
- // {
- // width: 100,
- // prop: 'productCategoryName',
- // label: '分类',
- // slot: 'productCategoryName',
- // align: "center"
- // },
- // {
- // width: 100,
- // prop: 'productCode',
- // label: '编码',
- // slot: 'productCode',
- // align: "center"
- // },
- {
- minWidth: 100,
- prop: 'productName',
- label: '产品名称',
- slot: 'productName',
- align: 'center'
- },
- {
- minWidth: 100,
- prop: 'modelType',
- label: '型号',
- slot: 'modelType',
- align: 'center'
- },
- {
- minWidth: 100,
- prop: 'specification',
- label: '规格',
- slot: 'specification',
- align: 'center'
- },
- // {
- // width: 100,
- // prop: 'unInvoiceAmount',
- // label: '未开票金额',
- // slot: 'unInvoiceAmount',
- // align: "center"
- // },
-
- // {
- // width: 80,
- // prop: 'singleWeight',
- // label: '单量',
- // align: 'center'
- // },
- {
- minWidth: 150,
- prop: 'invoiceAmount',
- label: '本次开票金额',
- slot: 'invoiceAmount',
- align: 'center'
- },
- {
- minWidth: 150,
- prop: 'invoicedAmount',
- label: '已开票金额',
- align: 'center'
- },
- {
- minWidth: 150,
- prop: 'unInvoiceAmount',
- label: '未开票金额',
- align: 'center'
- },
- {
- minWidth: 150,
- prop: 'taxRate',
- label: '税率',
- align: 'center',
- slot: 'taxRate',
- // formatter: (_row, _column, cellValue) => {
- // return _row.taxRate
- // ? _row.taxRate+'%'
- // : '';
- // },
- },
- {
- minWidth: 100,
- prop: 'noTaxSinglePrice',
- label: '不含税单价',
- slot: 'noTaxSinglePrice',
- align: 'center'
- },
- {
- width: 100,
- prop: 'totalCount',
- label: '订单数量',
- // slot: 'totalCount',
- align: 'center',
- },
- {
- width: 150,
- prop: 'quoteWay',
- label: '报价方式',
- formatter: (row, column) => {
- return row.quoteWay == 1
- ? '常规价'
- : row.quoteWay == 2
- ? '内部价'
- : row.quoteWay == 3 ? '议价' : '';
- },
- align: 'center'
- },
- {
- minWidth: 80,
- prop: 'singlePrice',
- label: '单价',
- slot: 'singlePrice',
- align: 'center'
- },
- {
- width: 100,
- prop: 'totalPrice',
- label: '合计',
- align: 'center'
- },
- {
- width: 100,
- prop: 'discountRatio',
- label: '折让比例',
- align: 'center'
- },
- {
- width: 100,
- prop: 'discountSinglePrice',
- label: '折让单价',
- align: 'center'
- },
- {
- width: 100,
- prop: 'discountAmount',
- label: '折让合计',
- align: 'center'
- },
- // {
- // width: 100,
- // prop: 'sourceType',
- // label: '来源类型',
- // slot: 'sourceType',
- // align: "center",
- // formatter: (row, column) => {
- // return row.sourceType == 2 ? '对账销售订单' : '对账采购订单';
- // }
- // },
- ],
- tableForm: {
- detailList: [
- {
- key: '',
- amountTotalPrice: 0,
- details: [{
- invoicedAmount: '',
- invoiceAmount: '',
- taxRate: '',
- noTaxSinglePrice: '',
- totalCount: '',
- quoteWay: '',
- singlePrice: '',
- totalPrice: '',
- discountRatio: 100,
- discountSinglePrice: '',
- discountAmount: '',
- }]
- }
- ],
- productMap: [],
- link: []
- },
- typeList: [
- {
- label: '销售发货',
- value: '10'
- },
- {
- label: '销售退货',
- value: '11'
- },
- {
- label: '采购收货',
- value: '20'
- },
- {
- label: '采购退货',
- value: '21'
- }
- ],
- };
- },
- computed: {
- totalAmountTotalPrice() {
- let tempTotal = this.tableForm.detailList.reduce((total, item) => {
- return total + (parseFloat(item.invoiceAmount) || 0);
- }, 0);
- return tempTotal.toFixed(2);
- }
- },
- mounted() {
- // this.tableForm = this.form;
- },
- methods: {
- convertToArrayFormat(data, type) {
- const result = [];
- Object.keys(data.productMap).forEach(key => {
- console.log('key!!!', key);
- const paymentItem = data.receiptPayments?.filter(item => item?.relatedOrderNo == key) || [];
- console.log('paymentItem', paymentItem);
- const amountTotalPrice = paymentItem.length ? paymentItem.reduce((acc, cur) => acc + cur.invoiceAmount, 0) : 0;
- const defaultAmountTotalPrice = paymentItem.length ? paymentItem.reduce((acc, cur) => acc + cur.unInvoiceAmount, 0) : 0;
- const details = data.productMap[key] || [];
-
- details.forEach(detail => {
- result.push({
- key: key,
- amountTotalPrice: amountTotalPrice,
- defaultAmountTotalPrice: defaultAmountTotalPrice,
- ...detail,
- invoiceAmount: detail.invoiceAmount || 0,
- });
- });
- });
- if(type == 'setValue') {
- const uniqueKeys = [...new Set(result.map(item => item.key))];
- uniqueKeys.forEach(key => {
- const sameKeyItems = result.filter(item => item.key === key);
- if (sameKeyItems.length > 0) {
- const defaultAmountTotalPrice = parseFloat(sameKeyItems[0].defaultAmountTotalPrice) || 0;
- let remainingTotal = defaultAmountTotalPrice;
-
- sameKeyItems.forEach(item => {
- if (remainingTotal <= 0) {
- item.invoiceAmount = 0;
- } else {
- const unInvoiceAmount = parseFloat(item.unInvoiceAmount) || 0;
- const allocateAmount = Math.min(remainingTotal, unInvoiceAmount);
- item.invoiceAmount = allocateAmount.toFixed(2);
- remainingTotal -= allocateAmount;
- }
- });
- }
- });
- }
-
-
-
- return result;
- },
- // 校验发票金额
- invoiceAmountChange(val, item, index) {
- console.log('invoiceAmountChange', val, item, index);
- console.log('this.tableForm.detailList', this.tableForm.detailList);
- if (index != null) {
- const key = item.key;
- const sameKeyItems = this.tableForm.detailList.filter(d => d.key === key);
- console.log('sameKeyItems', sameKeyItems);
- let sum = 0;
- sameKeyItems.forEach((r) => {
- if (r.invoiceAmount) {
- sum += Number(r.invoiceAmount);
- }
- });
- // if (val && +val > +item.unInvoiceAmount) {
- // this.$message.warning('物品开票金额不能大于未开票金额');
- // this.$set(item, 'invoiceAmount', '');
- // return;
- // }
- // if (sum > item.defaultAmountTotalPrice) {
- // this.$message.warning('物品开票金额不能大于本次开票合计');
- // this.$set(item, 'invoiceAmount', '');
- // return;
- // }
- this.$set(item, 'invoiceAmount', val);
- const amountTotalPrice = this.fromPrecision(sum);
- const targetItems = this.tableForm.detailList.filter(d => d.key === key);
- targetItems.forEach(targetItem => {
- this.$set(targetItem, 'amountTotalPrice', amountTotalPrice);
- });
- console.log('sum', sum, item.invoiceAmount);
- this.$emit('invoiceAmountChange', item, sum);
- }
-
- },
- //计算不含税单价
- getNotaxSinglePrice(item, idx, index) {
- if (item.singlePrice && item.taxRate) {
- this.$set(
- item,
- 'noTaxSinglePrice',
- parseFloat(
- (item.singlePrice / (1 + item.taxRate / 100)).toFixed(2)
- )
- );
- } else {
- this.$set(item, 'noTaxSinglePrice', '');
- }
- },
- putValue(data) {
- let tempData = JSON.parse(JSON.stringify(data));
- console.log('tableInfoNew putValue', tempData);
- tempData.detailList = this.convertToArrayFormat(tempData, 'putValue');
- this.tableForm = tempData;
- console.log('tableInfoNew putValue~~~', this.tableForm);
- },
- setValue(data) {
- let tempData = JSON.parse(JSON.stringify(data));
- tempData.detailList = this.convertToArrayFormat(tempData, 'setValue');
- console.log('tempData.detailList', tempData.detailList);
- this.tableForm = tempData;
- },
- /**
- * 分配开票金额到明细项(根据未开票金额unInvoiceAmount限制)
- * @param {Array|Object} data - 明细列表或单个明细对象
- * @returns {Array|Object} 处理后的数据
- */
- allocateInvoiceAmount(data) {
- if (Array.isArray(data)) {
- data.forEach(item => {
- if (item && typeof item === 'object') {
- this.allocateSingleInvoiceAmount(item);
- }
- });
- return data;
- } else if (data && typeof data === 'object') {
- this.allocateSingleInvoiceAmount(data);
- return data;
- }
- return data;
- },
- allocateSingleInvoiceAmount(item) {
- console.log('allocateSingleInvoiceAmount~~~', item);
- const key = item.key;
- const defaultAmountTotalPrice = this.toPrecision(item.defaultAmountTotalPrice);
- const sameKeyItems = this.tableForm.detailList.filter(d => d.key === key);
-
- let remainingTotal = defaultAmountTotalPrice;
-
- sameKeyItems.forEach((detail) => {
- if (remainingTotal <= 0) {
- detail.invoiceAmount = 0;
- } else {
- const unInvoiceAmount = this.toPrecision(detail.unInvoiceAmount);
-
- if (remainingTotal > unInvoiceAmount) {
- detail.invoiceAmount = this.fromPrecision(unInvoiceAmount);
- remainingTotal = this.subPrecision(remainingTotal, unInvoiceAmount);
- } else {
- detail.invoiceAmount = this.fromPrecision(remainingTotal);
- remainingTotal = 0;
- }
- }
- });
- },
- toPrecision(value) {
- const num = parseFloat(value) || 0;
- return Math.round(num * 100);
- },
- fromPrecision(value) {
- const num = parseFloat(value) || 0;
- return (num / 100).toFixed(2);
- },
- subPrecision(a, b) {
- return a - b;
- },
- setSinglePrice(row, data) {
- let index = this.tableForm.detailList.findIndex(item => item.key == row.relatedOrderNo);
- // let detail = this.tableForm.detailList[index];
- // console.log('tableInfoNew setPrice', row, data, index);
- const paymentItem = data.filter(item => item?.relatedOrderNo == row.relatedOrderNo);
- console.log('tableInfoNew~~~', this.tableForm.detailList[index]);
- this.tableForm.detailList[index].amountTotalPrice = paymentItem.length ? paymentItem.reduce((acc, cur) => acc + +cur.invoiceAmount, 0) : 0;
- this.tableForm.detailList[index].defaultAmountTotalPrice = paymentItem.length ? paymentItem.reduce((acc, cur) => acc + +cur.invoiceAmount, 0) : 0;
- // console.log('tableInfoNew tableForm', this.tableForm.detailList);
- // 直接修改对象,不需要赋值
- this.allocateInvoiceAmount(this.tableForm.detailList[index]);
- this.tableForm = {...this.tableForm};
- this.$forceUpdate();
- },
- clearTable() {
- this.tableForm = {
- detailList: [],
- productMap: [],
- receiptPayments: [],
- link: []
- };
- },
- // 当数量变化时更新金额
- updateTotalPrice(row) {
- if (row.totalCount && row.singlePrice) {
- row.totalPrice = (parseFloat(row.totalCount) * parseFloat(row.singlePrice)).toFixed(2);
- }
- },
- getTableValidate() {
- return new Promise(async (resolve, reject) => {
- // 2. 验证单个表格表单
- const formInstance = this.$refs['form'];
-
- if (formInstance && typeof formInstance.validate === 'function') {
- formInstance.validate(async (valid, errors) => {
- if (!valid && errors) {
- // 显示第一个错误信息
- const firstError = Object.values(errors)[0][0];
- if (firstError) {
- this.$message.warning(firstError.message);
- }
- reject(false);
- } else {
- // 3. 校验 amountTotalPrice 和 defaultAmountTotalPrice 是否相等
- // for (let i = 0; i < this.tableForm.detailList.length; i++) {
- // const item = this.tableForm.detailList[i];
- // const amountTotalPrice = parseFloat(item.amountTotalPrice) || 0;
- // const defaultAmountTotalPrice = parseFloat(item.defaultAmountTotalPrice) || 0;
-
- // if (amountTotalPrice !== defaultAmountTotalPrice) {
- // this.$message.warning(`第${i + 1}条本次开票合计(${amountTotalPrice})必须等于本次开票金额合计(${defaultAmountTotalPrice})`);
- // reject(false);
- // return;
- // }
- // }
-
- resolve(this.tableForm);
- console.log('this.tableForm~~~',this.tableForm);
- }
- });
- } else {
- // 4. 校验 amountTotalPrice 和 defaultAmountTotalPrice 是否相等
- // for (let i = 0; i < this.tableForm.detailList.length; i++) {
- // const item = this.tableForm.detailList[i];
- // const amountTotalPrice = parseFloat(item.amountTotalPrice) || 0;
- // const defaultAmountTotalPrice = parseFloat(item.defaultAmountTotalPrice) || 0;
-
- // // if (amountTotalPrice !== defaultAmountTotalPrice) {
- // // this.$message.warning(`第${i + 1}条本次开票合计(${amountTotalPrice})必须等于本次开票金额合计(${defaultAmountTotalPrice})`);
- // // reject(false);
- // // return;
- // // }
- // }
-
- resolve(this.tableForm);
- console.log('this.tableForm~~~',this.tableForm);
- }
- });
- },
- validateForm(callback) {
- //开始表单校验
- this.$refs.form.validate((valid, obj) => {
- if (obj) {
- let messages = Object.keys(obj).map((key) => obj[key][0]);
- if (messages.length > 0) {
- this.$message.warning(messages[0].message);
- }
- }
- callback(valid);
- });
- },
- setSelectData(val) {
- this.tableForm.link = [{}];
- this.$set(this.tableForm.link[0], 'linkId', val.id);
- this.$set(this.tableForm.link[0], 'linkName', val.name);
- this.$set(this.tableForm.link[0], 'linkCode', val.code);
- this.$set(this.tableForm.link[0], 'linkType', val.linkType);
- this.$set(this.tableForm.link[0], 'linkTypeName', val.linkTypeName);
- },
- getTableData() {
- const data = JSON.parse(JSON.stringify(this.tableForm.detailList));
- const transformedData = data.reduce((result, item) => {
- if (!result[item.key]) {
- result[item.key] = [];
- }
- const { key, amountTotalPrice, defaultAmountTotalPrice, ...detail } = item;
- result[item.key].push(detail);
- return result;
- }, {});
- return transformedData;
- }
- }
- };
- </script>
- <style scoped lang="scss">
- .time-form .el-form-item {
- margin-bottom: 0 !important;
- }
- </style>
|