|
@@ -1,6 +1,12 @@
|
|
|
<template>
|
|
|
<div class="w-full h-full flex flex-col">
|
|
|
<div class="flex-1 overflow-y-auto">
|
|
|
+ <van-field v-model="value" label="合同所属部门" placeholder="请选择" input-align="right" readonly
|
|
|
+ @click="showDepartmentSelection">
|
|
|
+ <template #input v-if="departmentRow.departmentName != ''">
|
|
|
+ <TranslationComponent type="departmentName" :openId="departmentRow.departmentName" />
|
|
|
+ </template>
|
|
|
+ </van-field>
|
|
|
<CustomerForm ref="formFormRef" :formJson="formJson" :formValue="formVal"></CustomerForm>
|
|
|
<template v-for="(item, index) in paymentPlanList">
|
|
|
<FoldingPanel :title="`回款计划(${index + 1})`" class="mb-4">
|
|
@@ -19,9 +25,10 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</van-cell>
|
|
|
- <van-cell title="回款日期" @click="showDatePicker(index)">
|
|
|
+ <van-cell title="回款日期" @click="showDatePicker(index, 'payDate')">
|
|
|
<template #default>
|
|
|
- <van-field v-model="item.payDate" input-align="right" placeholder="请选择日期" class="resetStyles" readonly />
|
|
|
+ <van-field v-model="item.payDate" input-align="right" placeholder="请选择日期" class="resetStyles"
|
|
|
+ readonly />
|
|
|
</template>
|
|
|
</van-cell>
|
|
|
<van-cell title="回款金额">
|
|
@@ -30,6 +37,37 @@
|
|
|
class="resetStyles" />
|
|
|
</template>
|
|
|
</van-cell>
|
|
|
+ <van-cell title="是否已开票">
|
|
|
+ <template #default>
|
|
|
+ <div class="flex justify-end">
|
|
|
+ <van-checkbox v-model="item.isBilled">已开票</van-checkbox>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ <van-cell title="开票日期" @click="showDatePicker(index, 'billDate')">
|
|
|
+ <template #default>
|
|
|
+ <van-field v-model="item.billDate" input-align="right" placeholder="请选择日期" class="resetStyles"
|
|
|
+ readonly />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ <van-cell title="开票种类增值税" @click="showSelectTaxAmount(index)">
|
|
|
+ <template #default >
|
|
|
+ <van-field v-model="item.invoiceTypeName" type="text" input-align="right" placeholder="请选择"
|
|
|
+ class="resetStyles" readonly="" />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ <van-cell title="税率%">
|
|
|
+ <template #default>
|
|
|
+ <van-field v-model="item.taxRate" type="digit" input-align="right" placeholder="请输入"
|
|
|
+ class="resetStyles" @change="inputNumberChange(index)" />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
+ <van-cell title="税额">
|
|
|
+ <template #default>
|
|
|
+ <van-field v-model="item.taxAmount" type="digit" input-align="right" placeholder="请输入"
|
|
|
+ class="resetStyles" />
|
|
|
+ </template>
|
|
|
+ </van-cell>
|
|
|
</div>
|
|
|
</template>
|
|
|
</FoldingPanel>
|
|
@@ -45,7 +83,48 @@
|
|
|
<van-popup v-model:show="showPicker" destroy-on-close position="bottom" :style="{ height: '50%' }">
|
|
|
<van-date-picker v-model="pickerValue" @confirm="showPickerConfirm" @cancel="showPicker = false" />
|
|
|
</van-popup>
|
|
|
+
|
|
|
+ <!-- 部门选择 -->
|
|
|
+ <!-- <treeSelect
|
|
|
+ ref="treeSelectRef"
|
|
|
+ v-model:show="departmentShow"
|
|
|
+ :modelValue="departmentShow.departmentId"
|
|
|
+ :listData="options"
|
|
|
+ :multiple='false'
|
|
|
+ placeholder="请选择"
|
|
|
+ @changeModelValue="changeModelValue"
|
|
|
+ :configurationItem="{ label: 'label', value: 'id', children: 'children' }"
|
|
|
+ ></treeSelect> -->
|
|
|
+
|
|
|
+ <van-popup v-model:show="departmentShow" destroy-on-close position="bottom" :style="{ height: '85%' }">
|
|
|
+ <div class="selectDepartment">
|
|
|
+ <div class="w-full absolute top-12 z-10">
|
|
|
+ <van-tabs v-model:active="departmentRow.tabIndex" shrink scrollspy @click-tab="tabClick">
|
|
|
+ <van-tab v-for="item in tableSelectSelectionShowList">
|
|
|
+ <template #title>
|
|
|
+ <TranslationComponent type="departmentName" :openId="item.label" />
|
|
|
+ </template>
|
|
|
+ </van-tab>
|
|
|
+ </van-tabs>
|
|
|
+ </div>
|
|
|
+ <div class="soDept">
|
|
|
+ <van-cascader v-model="departmentRow.departmentId" ref="cascaderDeptRef" title="合同所属部门" :options="deptOptions"
|
|
|
+ @change="changeModelValue" @close="departmentShow = false" :field-names="fieldNames"
|
|
|
+ @finish="finishModelValue">
|
|
|
+ <template #option="{ option }">
|
|
|
+ <div>
|
|
|
+ <TranslationComponent type="departmentName" :openId="option.label" />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </van-cascader>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </van-popup>
|
|
|
</div>
|
|
|
+
|
|
|
+ <van-popup v-model:show="showSelectTaxAmountShow" destroy-on-close position="bottom" :style="{ height: '50%' }">
|
|
|
+ <van-picker :columns="columns" @confirm="onConfirm" />
|
|
|
+ </van-popup>
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
@@ -61,6 +140,8 @@ import dayjs from 'dayjs';
|
|
|
import commonUtil from "@utility/commonUtil"
|
|
|
import { number } from 'echarts';
|
|
|
|
|
|
+import TreeSelect from "@components/common/treeSelect/selectTree.vue"
|
|
|
+
|
|
|
const router = useRouterStore()
|
|
|
const { toastText, toastSuccess, toastFail, toastLoading } = useToast()
|
|
|
const props = defineProps({
|
|
@@ -74,6 +155,28 @@ const paymentPlanList = ref([{}])
|
|
|
const showPicker = ref(false)
|
|
|
const pickerValue = ref([])
|
|
|
const rowIndex = ref(0)
|
|
|
+const departmentRow = ref({
|
|
|
+ departmentName: '',
|
|
|
+ departmentId: '',
|
|
|
+ sureDepartmentId: '',
|
|
|
+ tableSelect: ''
|
|
|
+})
|
|
|
+const departmentShow = ref(false)
|
|
|
+const deptOptions = ref([])
|
|
|
+const tableSelectSelectionShowList = ref([])
|
|
|
+const fieldNames = {
|
|
|
+ text: 'label',
|
|
|
+ value: 'id',
|
|
|
+ children: 'children',
|
|
|
+};
|
|
|
+const cascaderDeptRef = ref(null)
|
|
|
+const dataType = ref('payDate')
|
|
|
+const showSelectTaxAmountShow = ref(false)
|
|
|
+const selectIndex = ref(0)
|
|
|
+const columns = [
|
|
|
+ { text: '增值税专用发票', value: 0 },
|
|
|
+ { text: '增值税普通发票', value: 1 },
|
|
|
+]
|
|
|
|
|
|
watch(() => formVal.value, (newValue) => {
|
|
|
console.log(newValue, '<==== 看看')
|
|
@@ -81,10 +184,71 @@ watch(() => formVal.value, (newValue) => {
|
|
|
paymentPlanList.value = [{}]
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+ departmentRow.value = {
|
|
|
+ departmentName: newValue.departmentName,
|
|
|
+ departmentId: newValue.departmentId,
|
|
|
+ sureDepartmentId: newValue.departmentId,
|
|
|
+ tableSelect: ''
|
|
|
+ }
|
|
|
getPaymentCollectionList(newValue.id)
|
|
|
})
|
|
|
|
|
|
+function inputNumberChange(index) {
|
|
|
+ const { amount = 0, taxRate = 0, taxAmount = 0 } = paymentPlanList.value[index]
|
|
|
+ if(!amount && !amount) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ paymentPlanList.value[index].taxAmount = +((amount * taxRate / 100).toFixed(2))
|
|
|
+}
|
|
|
+
|
|
|
+function onConfirm(val) {
|
|
|
+ const selectedOptions = val.selectedOptions[0]
|
|
|
+ paymentPlanList.value[selectIndex.value].invoiceType = selectedOptions.value
|
|
|
+ paymentPlanList.value[selectIndex.value].invoiceTypeName = selectedOptions.text
|
|
|
+ showSelectTaxAmountShow.value = false
|
|
|
+}
|
|
|
+function showSelectTaxAmount(index) {
|
|
|
+ selectIndex.value = index
|
|
|
+ showSelectTaxAmountShow.value = true
|
|
|
+}
|
|
|
+
|
|
|
+function finishModelValue({ value, selectedOptions }) {
|
|
|
+ const row = selectedOptions.find(item => item.id == value)
|
|
|
+ departmentRow.value.sureDepartmentId = row.id
|
|
|
+ departmentRow.value.departmentName = row.label
|
|
|
+ departmentShow.value = false
|
|
|
+}
|
|
|
+
|
|
|
+function tabClick(name) {
|
|
|
+ const elements = cascaderDeptRef.value.$el.querySelectorAll('[role="tab"]');
|
|
|
+ elements[name.name].click()
|
|
|
+ tableSelectSelectionShowList.value.splice(name.name + 1, tableSelectSelectionShowList.value.length)
|
|
|
+}
|
|
|
+
|
|
|
+function changeModelValue({ value, selectedOptions, tabIndex }) {
|
|
|
+ const row = selectedOptions.find(item => item.id == value)
|
|
|
+ tableSelectSelectionShowList.value.push({
|
|
|
+ label: row.label,
|
|
|
+ index: tabIndex,
|
|
|
+ id: row.id
|
|
|
+ })
|
|
|
+ setTimeout(() => {
|
|
|
+ departmentRow.value.tabIndex = tableSelectSelectionShowList.value.length - 1
|
|
|
+ }, 200)
|
|
|
+}
|
|
|
+
|
|
|
+function showDepartmentSelection() {
|
|
|
+ tableSelectSelectionShowList.value = []
|
|
|
+ departmentRow.value.departmentId = ''
|
|
|
+ departmentShow.value = true
|
|
|
+}
|
|
|
+
|
|
|
+function obtainDepartmentalData() {
|
|
|
+ requests.post('/department/list', {}).then((res) => {
|
|
|
+ deptOptions.value = res.data
|
|
|
+ })
|
|
|
+}
|
|
|
|
|
|
function onSubmit() {
|
|
|
formFormRef.value.getJsonData().then((res) => {
|
|
@@ -93,33 +257,44 @@ function onSubmit() {
|
|
|
}
|
|
|
const determineArray = paymentPlanList.value.filter(item => item.isPayed || (item.payDate || item.amount))
|
|
|
let totalNum = 0
|
|
|
- for(let i in determineArray) {
|
|
|
+ for (let i in determineArray) {
|
|
|
const row = determineArray[i]
|
|
|
- if(!row.payDate) {
|
|
|
+ if (!row.payDate) {
|
|
|
toastText('回款日期不能为空')
|
|
|
return
|
|
|
}
|
|
|
- if(!row.amount || row.amount == 0) {
|
|
|
+ if (!row.amount || row.amount == 0) {
|
|
|
toastText('回款金额不能为空和0')
|
|
|
return
|
|
|
}
|
|
|
totalNum += Number(determineArray[i].amount)
|
|
|
- if(formVal.value.id) {
|
|
|
+ if (formVal.value.id) {
|
|
|
determineArray[i].contractId = formVal.value.id
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if(totalNum > 0 && !res.data.amounts) {
|
|
|
+ if (totalNum > 0 && !res.data.amounts) {
|
|
|
toastText('请输入合同金额')
|
|
|
return
|
|
|
}
|
|
|
- if(totalNum > res.data.amounts) {
|
|
|
+ if (totalNum > res.data.amounts) {
|
|
|
toastText('回款金额不能大于合同金额')
|
|
|
return
|
|
|
}
|
|
|
|
|
|
toastLoading('保存中', 0)
|
|
|
- requests.post(props.formValue?.id ? CONTRACT_EDITING : CONTRACT_ADDITION_EDITING, { ...commonUtil.getFromValue({ ...props.formValue, ...res.data, paymentListStr: JSON.stringify(determineArray || []) }) }).then(() => {
|
|
|
+ requests.post(props.formValue?.id ? CONTRACT_EDITING : CONTRACT_ADDITION_EDITING, { ...commonUtil.getFromValue({
|
|
|
+ ...props.formValue,
|
|
|
+ ...res.data,
|
|
|
+ paymentListStr: JSON.stringify((determineArray || []).map(item => {
|
|
|
+ delete item.invoiceTypeName
|
|
|
+ return {
|
|
|
+ ...item,
|
|
|
+ isBilled: item.isBilled ? 1 : 0
|
|
|
+ }
|
|
|
+ }))}),
|
|
|
+ departmentId: departmentRow.value.sureDepartmentId
|
|
|
+ }).then(() => {
|
|
|
toastSuccess('保存成功')
|
|
|
setTimeout(() => {
|
|
|
router.navigateBack({
|
|
@@ -135,23 +310,30 @@ function onSubmit() {
|
|
|
}
|
|
|
|
|
|
function addPaymentCollection(index) {
|
|
|
- paymentPlanList.value.splice(index + 1, 0, { isPayed: false, payDate: dayjs(new Date()).format('YYYY-MM-DD'), amount: null })
|
|
|
+ paymentPlanList.value.splice(index + 1, 0, { isPayed: false, payDate: dayjs(new Date()).format('YYYY-MM-DD'), amount: null, isBilled: true })
|
|
|
}
|
|
|
|
|
|
function deletePaymentCollection(index) {
|
|
|
paymentPlanList.value.splice(index, 1)
|
|
|
}
|
|
|
|
|
|
-function showDatePicker(index) {
|
|
|
- const { payDate } = paymentPlanList.value[index];
|
|
|
+function showDatePicker(index, type) {
|
|
|
+ const { payDate, billDate } = paymentPlanList.value[index];
|
|
|
+ dataType.value = type
|
|
|
rowIndex.value = index;
|
|
|
- const currentDate = dayjs(payDate ? new Date(payDate) : new Date()).format('YYYY-MM-DD').split('-');
|
|
|
+ const dates = type == 'payDate' ? payDate : billDate
|
|
|
+ const currentDate = dayjs(dates ? new Date(dates) : new Date()).format('YYYY-MM-DD').split('-');
|
|
|
pickerValue.value = currentDate;
|
|
|
showPicker.value = true;
|
|
|
}
|
|
|
|
|
|
function showPickerConfirm({ selectedValues }) {
|
|
|
- paymentPlanList.value[rowIndex.value].payDate = selectedValues.join("-");
|
|
|
+ if (dataType.value == 'payDate') {
|
|
|
+ paymentPlanList.value[rowIndex.value].payDate = selectedValues.join("-");
|
|
|
+ }
|
|
|
+ if (dataType.value == 'billDate') {
|
|
|
+ paymentPlanList.value[rowIndex.value].billDate = selectedValues.join("-");
|
|
|
+ }
|
|
|
showPicker.value = false;
|
|
|
}
|
|
|
|
|
@@ -165,10 +347,12 @@ useLifecycle({
|
|
|
load: () => {
|
|
|
formVal.value = props.formValue
|
|
|
paymentPlanList.value = [{}]
|
|
|
+ obtainDepartmentalData()
|
|
|
},
|
|
|
init: () => {
|
|
|
formVal.value = props.formValue
|
|
|
paymentPlanList.value = [{}]
|
|
|
+ obtainDepartmentalData()
|
|
|
}
|
|
|
});
|
|
|
|
|
@@ -182,4 +366,12 @@ onActivated(() => {
|
|
|
.resetStyles {
|
|
|
padding: 0;
|
|
|
}
|
|
|
+
|
|
|
+.soDept {
|
|
|
+ position: relative;
|
|
|
+
|
|
|
+ :deep(.van-tabs__nav--complete) {
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|