feat: 合同模板设置

This commit is contained in:
Zzz1zz 2025-11-05 22:26:35 +08:00
parent 84aaa9ac10
commit 89960f749f
7 changed files with 139 additions and 31 deletions

View file

@ -366,12 +366,16 @@ export function updateTermsSetting(
export function delTermsSetting(id: number): Promise<HttpResponse> { export function delTermsSetting(id: number): Promise<HttpResponse> {
return axios.get(`contractSetting/delTermsSetting?id=${id}`); return axios.get(`contractSetting/delTermsSetting?id=${id}`);
} }
// 合同设置-合同条款设置-单个详情 // 合同设置-合同条款设置-单个条款配置详情
export function getTermsSettingFromId( export function getTermsSettingFromId(
id: number id: number
): Promise<SettingContractTermInfo> { ): Promise<SettingContractTermInfo> {
return axios.get(`contractSetting/getTermsSetting?id=${id}`); return axios.get(`contractSetting/getTermsSetting?id=${id}`);
} }
// 合同设置-合同条款设置-单个条款数据详情
export function getTermsDataFromId(params: any): Promise<any> {
return axios.post(`contractSetting/getTerm`, params);
}
// 合同设置-合同条款设置-启用/禁用 // 合同设置-合同条款设置-启用/禁用
export function disableTermsSetting( export function disableTermsSetting(
params: DisableUserParam params: DisableUserParam

View file

@ -206,7 +206,10 @@
{{ item.title }} {{ item.title }}
<icon-close v-if="item.isChoose === 1" /> <icon-close v-if="item.isChoose === 1" />
</a-tag> </a-tag>
<a-tag class="cursor-pointer mb-[10px]" @click="handleAddTerm"> <a-tag
class="cursor-pointer mb-[10px]"
@click="handleAddDiscountTerm"
>
<icon-plus /> <icon-plus />
优惠条款 优惠条款
</a-tag> </a-tag>
@ -214,11 +217,13 @@
<bond <bond
v-if="isBondShown" v-if="isBondShown"
ref="bondRef" ref="bondRef"
:detail-info="termsDetailInfo?.bondTerm"
:title="'保证金条款(租金保证金)'" :title="'保证金条款(租金保证金)'"
/> />
<incremental <incremental
v-if="isIncrementalShown" v-if="isIncrementalShown"
ref="incrementalRef" ref="incrementalRef"
:detail-info="termsDetailInfo?.incrementalTerm"
:title="'递增条款'" :title="'递增条款'"
/> />
<discount <discount
@ -226,15 +231,17 @@
:key="d.key" :key="d.key"
:ref="(el) => setDiscountRef(el, di)" :ref="(el) => setDiscountRef(el, di)"
:title="d.title" :title="d.title"
:detail-info="termsDetailInfo?.discountTerm?.[di]"
/> />
<lateFee <lateFee
v-if="isLateFeeShown" v-if="isLateFeeShown"
ref="lateFeeRef" ref="lateFeeRef"
:detail-info="termsDetailInfo?.lateFeeTerm"
:title="'滞纳金条款'" :title="'滞纳金条款'"
/> />
<rentSetting <rentSetting
ref="rentSettingRef" ref="rentSettingRef"
:term-setting-info="termSettingInfo" :detail-info="termsDetailInfo?.leaseTerm"
/> />
</div> </div>
</template> </template>
@ -254,6 +261,7 @@
getContractTagsList, getContractTagsList,
updateTemplateSetting, updateTemplateSetting,
getAllTermsSettingList, getAllTermsSettingList,
getTermsDataFromId,
} from '@/api/setting'; } from '@/api/setting';
import contractTemplateForm from './modal/contract-template-form.vue'; import contractTemplateForm from './modal/contract-template-form.vue';
import { DepartmentItem } from '@/types/setting'; import { DepartmentItem } from '@/types/setting';
@ -276,6 +284,7 @@
{ type: 1, text: '含税合同' }, { type: 1, text: '含税合同' },
{ type: 2, text: '不含税合同' }, { type: 2, text: '不含税合同' },
]; ];
const termsDetailInfo = ref<any>(null);
// 表单数据 // 表单数据
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const defaultForm: any = { const defaultForm: any = {
@ -394,6 +403,7 @@
(i: any) => i.type === 'lateFee' && i.isChoose === 1 (i: any) => i.type === 'lateFee' && i.isChoose === 1
) )
); );
// 获取条款设置相关设置
async function getTermsSettingFromIdData(id) { async function getTermsSettingFromIdData(id) {
const { code, data } = await getTermsSettingFromId(id); const { code, data } = await getTermsSettingFromId(id);
if (code === 200) { if (code === 200) {
@ -409,12 +419,31 @@
termTabList.value = next; termTabList.value = next;
} }
} }
async function getTermsInfoFromId(contractTermsSettingId) {
const currentTerm =
(currentContractTemplateInfo.value?.terms || []).find(
(t: any) => t.id === currentId.value
) || {};
const params = {
type: 1,
contractTemplateSettingId: currentTerm?.id,
contractTermsSettingId,
};
const { code, data } = await getTermsDataFromId(params);
if (code === 200) {
termsDetailInfo.value = data?.term ?? {};
}
}
const handleChoose = (id: number, str: string, termId: number) => { const handleChoose = (id: number, str: string, termId: number) => {
if (id === currentId.value) return; if (id === currentId.value) return;
currentId.value = id; currentId.value = id;
title.value = str; title.value = str;
if (id === 0) {
termsDetailInfo.value = {};
}
if (id === 0 || termId === 0) return; if (id === 0 || termId === 0) return;
getTermsSettingFromIdData(termId); getTermsSettingFromIdData(termId);
getTermsInfoFromId(termId);
}; };
const handleBaseInfoEdit = () => { const handleBaseInfoEdit = () => {
showModal.value = true; showModal.value = true;
@ -652,7 +681,7 @@
info.isChoose = info.isChoose === 1 ? 2 : 1; info.isChoose = info.isChoose === 1 ? 2 : 1;
} }
} }
function handleAddTerm() { function handleAddDiscountTerm() {
const idx = termTabList.value.filter( const idx = termTabList.value.filter(
(i: any) => i.type === 'discount' (i: any) => i.type === 'discount'
).length; ).length;

View file

@ -54,10 +54,12 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive } from 'vue'; import { ref, reactive, watch } from 'vue';
defineProps<{ title?: string }>();
import type { FormInstance } from '@arco-design/web-vue'; import type { FormInstance } from '@arco-design/web-vue';
const props = defineProps<{
title?: string;
detailInfo?: any | null;
}>();
// 表单数据 // 表单数据
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const defaultForm: any = { const defaultForm: any = {
@ -83,7 +85,20 @@
const choosePayDateType = (type) => { const choosePayDateType = (type) => {
bondForm.payType = type; bondForm.payType = type;
}; };
watch(
() => props.detailInfo,
(newVal) => {
const data = { ...newVal };
if (data.payType === 0) {
data.payType = undefined;
}
if (data.priceType === 0) {
data.priceType = undefined;
}
Object.assign(bondForm, defaultForm, data);
},
{ immediate: true, deep: true }
);
// 暴露保存数据 // 暴露保存数据
function getData() { function getData() {
return { ...bondForm }; return { ...bondForm };

View file

@ -56,9 +56,11 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive } from 'vue'; import { ref, reactive, watch } from 'vue';
import type { FormInstance } from '@arco-design/web-vue'; import type { FormInstance } from '@arco-design/web-vue';
const props = defineProps<{
detailInfo?: any | null;
}>();
// 表单数据 // 表单数据
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const defaultForm: any = { const defaultForm: any = {
@ -75,7 +77,17 @@
startNum: [{ required: true, message: '开始期数不能为空' }], startNum: [{ required: true, message: '开始期数不能为空' }],
endNum: [{ required: true, message: '持续期数不能为空' }], endNum: [{ required: true, message: '持续期数不能为空' }],
}); });
watch(
() => props.detailInfo,
(newVal) => {
const data = { ...newVal };
if (data.type === 0) {
data.type = undefined;
}
Object.assign(discountForm, defaultForm, data);
},
{ immediate: true, deep: true }
);
// 向父组件暴露数据与校验方法 // 向父组件暴露数据与校验方法
function getData() { function getData() {
const isEmptyValue = (v: any) => const isEmptyValue = (v: any) =>

View file

@ -58,9 +58,11 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive } from 'vue'; import { ref, reactive, watch } from 'vue';
import type { FormInstance } from '@arco-design/web-vue'; import type { FormInstance } from '@arco-design/web-vue';
const props = defineProps<{
detailInfo?: any | null;
}>();
// 表单数据 // 表单数据
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const defaultForm: any = { const defaultForm: any = {
@ -78,6 +80,21 @@
bondIncrease: [{ required: true, message: '保证金递增不能为空' }], bondIncrease: [{ required: true, message: '保证金递增不能为空' }],
}); });
watch(
() => props.detailInfo,
(newVal) => {
const data = { ...newVal };
if (data.priceIncreaseType === 0) {
data.priceIncreaseType = undefined;
}
if (data.bondIncreaseType === 0) {
data.bondIncreaseType = undefined;
}
Object.assign(increamForm, defaultForm, data);
},
{ immediate: true, deep: true }
);
// 向父组件暴露数据与校验方法 // 向父组件暴露数据与校验方法
function getData() { function getData() {
const isEmptyValue = (v: any) => const isEmptyValue = (v: any) =>

View file

@ -65,9 +65,11 @@
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { ref, reactive } from 'vue'; import { ref, reactive, watch } from 'vue';
import type { FormInstance } from '@arco-design/web-vue'; import type { FormInstance } from '@arco-design/web-vue';
const props = defineProps<{
detailInfo?: any | null;
}>();
// 表单数据 // 表单数据
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const defaultForm: any = { const defaultForm: any = {
@ -89,6 +91,24 @@
ceilingType: [{ required: true, message: '上限单位不能为空' }], ceilingType: [{ required: true, message: '上限单位不能为空' }],
}); });
watch(
() => props.detailInfo,
(newVal) => {
const data = { ...newVal };
if (data.chargeType === 0) {
data.chargeType = undefined;
}
if (data.ratioType === 0) {
data.ratioType = undefined;
}
if (data.ceilingType === 0) {
data.ceilingType = undefined;
}
Object.assign(lateFeeForm, defaultForm, data);
},
{ immediate: true, deep: true }
);
// 向父组件暴露数据与校验方法 // 向父组件暴露数据与校验方法
function getData() { function getData() {
const isEmptyValue = (v: any) => const isEmptyValue = (v: any) =>

View file

@ -22,16 +22,6 @@
layout="vertical" layout="vertical"
> >
<a-row :gutter="24"> <a-row :gutter="24">
<a-col :span="12">
<a-form-item label="首期账单缴费日期" field="firstPayDate" required>
<a-date-picker
v-model="rentSettingInfo.firstPayDate"
:disabled-date="
(current) => dayjs(current).isBefore(dayjs().subtract(1, 'day'))
"
/>
</a-form-item>
</a-col>
<a-col :span="12"> <a-col :span="12">
<a-form-item label="账单缴费日期" field="payDay" required> <a-form-item label="账单缴费日期" field="payDay" required>
<a-input-number v-model="rentSettingInfo.payDay"> <a-input-number v-model="rentSettingInfo.payDay">
@ -100,7 +90,6 @@
partitionMode: 1, // 租期划分模式 partitionMode: 1, // 租期划分模式
firstLessMonthType: 1, // 首月不足月租金处理 firstLessMonthType: 1, // 首月不足月租金处理
otherLeaseProcessing: 1, // 免租期、装修期租期处理 otherLeaseProcessing: 1, // 免租期、装修期租期处理
firstPayDate: '',
payDay: '', payDay: '',
payDateType: 1, payDateType: 1,
payDayType: 1, payDayType: 1,
@ -108,7 +97,6 @@
const rentSettingInfo = ref<any>({ ...defaultForm }); const rentSettingInfo = ref<any>({ ...defaultForm });
const formRef = ref<FormInstance>(); const formRef = ref<FormInstance>();
const rules = reactive({ const rules = reactive({
firstPayDate: [{ required: true, message: '请选择首期账单缴费日期' }],
payDay: [{ required: true, message: '请输入账单缴费日期' }], payDay: [{ required: true, message: '请输入账单缴费日期' }],
financeTurnoverAccountSettingId: [ financeTurnoverAccountSettingId: [
{ required: true, message: '请选择默认收款账户' }, { required: true, message: '请选择默认收款账户' },
@ -117,7 +105,7 @@
const turnoverAccountList = ref<any>([]); const turnoverAccountList = ref<any>([]);
const props = defineProps<{ const props = defineProps<{
termSettingInfo?: any | null; detailInfo?: any | null;
}>(); }>();
// 文案映射与计算属性 // 文案映射与计算属性
const chargeTypeMap = new Map([ const chargeTypeMap = new Map([
@ -253,14 +241,37 @@
} }
onMounted(() => { onMounted(() => {
triggerTurnoverList(props.termSettingInfo); triggerTurnoverList(props.detailInfo);
}); });
watch( watch(
() => props.termSettingInfo, () => props.detailInfo,
(newVal) => { (newVal) => {
const data = { ...(newVal || {}) };
const fieldsToProcess = [
'payDateType',
'payDayType',
'financeTurnoverAccountSettingId',
'chargeType',
'priceUnit',
'dayPriceAlgorithm',
'dayPriceUnit',
'calculationAccuracy',
'billAccuracy',
'partitionMode',
'firstLessMonthType',
'otherLeaseProcessing',
];
fieldsToProcess.forEach((field) => {
if (data[field] === 0) {
data[field] = undefined;
}
});
rentSettingInfo.value = { ...defaultForm, ...data };
triggerTurnoverList(newVal); triggerTurnoverList(newVal);
}, },
{ deep: false } { deep: true }
); );
defineExpose({ getData, validate }); defineExpose({ getData, validate });