客户组件封装
parent
a98497cf47
commit
185b306240
|
|
@ -6,8 +6,9 @@ VITE_DEV=true
|
|||
# 请求路径
|
||||
# VITE_BASE_URL='http://8.130.12.151:48080'
|
||||
# VITE_BASE_URL='http://lhy.free.idcfengye.com'
|
||||
# VITE_BASE_URL='http://m94844f6.natappfree.cc'
|
||||
VITE_BASE_URL='http://172.22.3.168:48080'
|
||||
VITE_BASE_URL='http://m94844f6.natappfree.cc'
|
||||
# VITE_BASE_URL='http://172.22.3.168:48080'
|
||||
# VITE_BASE_URL='http://172.22.3.203:48080'
|
||||
|
||||
# 文件上传类型:server - 后端上传, client - 前端直连上传,仅支持 S3 服务
|
||||
VITE_UPLOAD_TYPE=server
|
||||
|
|
|
|||
|
|
@ -40,6 +40,13 @@ export const getForm = async (id: number) => {
|
|||
})
|
||||
}
|
||||
|
||||
// 获得工作流的业务表单定义
|
||||
export const getBusinessForm = async (params) => {
|
||||
return await request.get({
|
||||
url: 'bpm/form-visible/get?id=', params
|
||||
})
|
||||
}
|
||||
|
||||
// 获得工作流的表单定义分页
|
||||
export const getFormPage = async (params) => {
|
||||
return await request.get({
|
||||
|
|
|
|||
|
|
@ -90,6 +90,16 @@ export const QuotationApi = {
|
|||
return await request.get({ url: `/crm/service-fee-collection-method/page`, params })
|
||||
},
|
||||
|
||||
// 获取服务费次数
|
||||
getServerFee: async (data: any) => {
|
||||
return await request.post({ url: `/crm/quotation/get-service-fee`, data })
|
||||
},
|
||||
|
||||
// 获取第几次报价
|
||||
getQutoTimes: async (params: any) => {
|
||||
return await request.get({ url: `/crm/quotation/get-quotation-times`, params })
|
||||
},
|
||||
|
||||
// ==================== 子表(CRM 报价产品关联) ====================
|
||||
|
||||
// 获得CRM 报价产品关联列表
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
import SelectComponent from './src/index.vue'
|
||||
|
||||
export { SelectComponent }
|
||||
|
|
@ -0,0 +1,121 @@
|
|||
<template>
|
||||
<el-select
|
||||
:disabled="disabled"
|
||||
v-model="selectValue"
|
||||
:loading="loading"
|
||||
loading-text="数据加载中..."
|
||||
filterable
|
||||
clearable
|
||||
popper-class="event-select-poper"
|
||||
v-el-select-loadmore="loadmore"
|
||||
placeholder="请选择"
|
||||
style="width: 100%"
|
||||
:filter-method="filterOptions"
|
||||
@change="handleEventsChange"
|
||||
@visible-change="handleVisibleChange">
|
||||
<el-option
|
||||
v-for="item in options"
|
||||
:key="item.id"
|
||||
:label="item.name"
|
||||
:value="item.id" />
|
||||
|
||||
</el-select>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
|
||||
defineOptions({ name: 'SelectCustomer' })
|
||||
const props = defineProps({
|
||||
disabled: propTypes.number.def(undefined),
|
||||
value: propTypes.number.def(undefined),
|
||||
customerList: propTypes.object.def([]), //所有数据
|
||||
})
|
||||
const selectValue = ref( '')
|
||||
watch(() => props.value, (val) => {
|
||||
selectValue.value = val
|
||||
}, {
|
||||
immediate: true,
|
||||
});
|
||||
watch(() => props.customerList, (val) => {
|
||||
options.value = val.slice(0, 10)
|
||||
}, {
|
||||
deep: true,
|
||||
});
|
||||
|
||||
let pageNo = ref(1)
|
||||
let pageSize = ref(10)
|
||||
const loading = ref(false);
|
||||
const allFilterEvents = reactive([]);
|
||||
const options = ref([]) //显示的数据
|
||||
const vElSelectLoadmore = {
|
||||
beforeMount(el, binding) {
|
||||
const selectDom = document.querySelector('.event-select-poper .el-select-dropdown__wrap');
|
||||
const loadMores = function() {
|
||||
const isBase = this.scrollHeight - this.scrollTop <= this.clientHeight + 20;
|
||||
if (isBase) {
|
||||
binding.value && binding.value();
|
||||
}
|
||||
};
|
||||
el.selectDomInfo = selectDom;
|
||||
el.selectLoadMore = loadMores;
|
||||
selectDom?.addEventListener('scroll', loadMores.bind(selectDom));
|
||||
},
|
||||
beforeUnmount(el) {
|
||||
if (el.selectLoadMore) {
|
||||
el.selectDomInfo.removeEventListener('scroll', el.selectLoadMore);
|
||||
delete el.selectDomInfo;
|
||||
delete el.selectLoadMore;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
watch(() => allFilterEvents, () => {
|
||||
let startIndex = pageNo.value * pageSize.value - pageSize.value;
|
||||
let endIndex = pageNo.value * pageSize.value;
|
||||
options.value = allFilterEvents.slice(startIndex, endIndex);
|
||||
}, {
|
||||
immediate: true,
|
||||
deep: true
|
||||
});
|
||||
|
||||
const loadmore = () => {
|
||||
if (props.customerList.length <= options.value.length) return;
|
||||
pageNo.value++;
|
||||
nextTick(() => {
|
||||
loading.value = true;
|
||||
let startIndex = pageNo.value * pageSize.value - pageSize.value;
|
||||
let endIndex = pageNo.value * pageSize.value;
|
||||
options.value = [
|
||||
...options.value,
|
||||
...props.customerList.slice(startIndex, endIndex)
|
||||
];
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const filterOptions = (query = '') => {
|
||||
pageNo.value = 1;
|
||||
nextTick(() => {
|
||||
if (query === '') {
|
||||
allFilterEvents.splice(0, allFilterEvents.length, ...props.customerList);
|
||||
} else {
|
||||
allFilterEvents.splice(0, allFilterEvents.length, ...props.customerList.filter(item => item.name.includes(query)));
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const handleVisibleChange = (visible) => {
|
||||
if (!visible) {
|
||||
pageNo.value = 1;
|
||||
nextTick(() => {
|
||||
allFilterEvents.splice(0, allFilterEvents.length, ...props.customerList);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
const handleEventsChange = (val) => {
|
||||
console.log('update:selectValue:', val);
|
||||
};
|
||||
|
||||
</script>
|
||||
|
|
@ -178,6 +178,9 @@ onMounted(async () => {
|
|||
const bpmnForm = (await getForm(bpmnModel.formId)) as unknown as FormVO
|
||||
formFields.value = bpmnForm?.fields
|
||||
}
|
||||
if (formType.value === BpmModelFormType.CUSTOM && bpmnModel.formId) {
|
||||
window.localStorage.setItem('businessKey', bpmnModel.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
// 获得角色列表
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ export function useFormFieldsPermission(defaultPermission: FieldPermissionType)
|
|||
|
||||
const getNodeConfigFormFields = (nodeFormFields?: Array<Record<string, string>>) => {
|
||||
nodeFormFields = toRaw(nodeFormFields)
|
||||
console.log('%csrc/components/SimpleProcessDesignerV2/src/node.ts:60 nodeFormFields', 'color: #007acc;', nodeFormFields);
|
||||
if (!nodeFormFields || nodeFormFields.length === 0) {
|
||||
fieldsPermissionConfig.value = getDefaultFieldsPermission(unref(formFields))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
</el-radio>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
<el-tabs type="border-card" v-model="activeTabName" v-if="approveType === ApproveType.USER">
|
||||
<el-tabs type="border-card" v-model="activeTabName" v-if="approveType === ApproveType.USER" @tab-click="tabClick">
|
||||
<el-tab-pane :label="`${nodeTypeName}人`" name="user">
|
||||
<div>
|
||||
<el-form ref="formRef" :model="configForm" label-position="top" :rules="formRules">
|
||||
|
|
@ -448,6 +448,58 @@
|
|||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="表单字段权限" name="businessFields" v-if="formType === 20">
|
||||
<div class="field-setting-pane">
|
||||
<div class="field-setting-desc">字段权限</div>
|
||||
<div class="field-permit-title">
|
||||
<div class="setting-title-label first-title"> 字段名称 </div>
|
||||
<div class="other-titles">
|
||||
<span class="setting-title-label cursor-pointer" @click="updatePermission('READ')">
|
||||
只读
|
||||
</span>
|
||||
<span class="setting-title-label cursor-pointer" @click="updatePermission('WRITE')">
|
||||
可编辑
|
||||
</span>
|
||||
<span class="setting-title-label cursor-pointer" @click="updatePermission('NONE')">
|
||||
隐藏
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="field-setting-item"
|
||||
v-for="(item, index) in fieldsPermissionConfig"
|
||||
:key="index"
|
||||
>
|
||||
<div class="field-setting-item-label"> {{ item.title }} </div>
|
||||
<el-radio-group class="field-setting-item-group" v-model="item.permission">
|
||||
<div class="item-radio-wrap">
|
||||
<el-radio
|
||||
:value="FieldPermissionType.READ"
|
||||
size="large"
|
||||
:label="FieldPermissionType.READ"
|
||||
><span></span
|
||||
></el-radio>
|
||||
</div>
|
||||
<div class="item-radio-wrap">
|
||||
<el-radio
|
||||
:value="FieldPermissionType.WRITE"
|
||||
size="large"
|
||||
:label="FieldPermissionType.WRITE"
|
||||
><span></span
|
||||
></el-radio>
|
||||
</div>
|
||||
<div class="item-radio-wrap">
|
||||
<el-radio
|
||||
:value="FieldPermissionType.NONE"
|
||||
size="large"
|
||||
:label="FieldPermissionType.NONE"
|
||||
><span></span
|
||||
></el-radio>
|
||||
</div>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="表单字段权限" name="fields" v-if="formType === 10">
|
||||
<div class="field-setting-pane">
|
||||
<div class="field-setting-desc">字段权限</div>
|
||||
|
|
@ -558,6 +610,7 @@ import { defaultProps } from '@/utils/tree'
|
|||
import { cloneDeep } from 'lodash-es'
|
||||
import { convertTimeUnit, getApproveTypeText } from '../utils'
|
||||
import UserTaskListener from './components/UserTaskListener.vue'
|
||||
import { getBusinessForm, FormVO } from '@/api/bpm/form'
|
||||
defineOptions({
|
||||
name: 'UserTaskNodeConfig'
|
||||
})
|
||||
|
|
@ -971,6 +1024,17 @@ const updatePermission = (type: string) => {
|
|||
: FieldPermissionType.NONE
|
||||
})
|
||||
}
|
||||
|
||||
const tabClick = async (tab) => {
|
||||
console.log('%csrc/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue:1029 activeTabName.value', 'color: #007acc;', tab.props);
|
||||
if(tab.props.name === 'businessFields') {
|
||||
const bpmnForm = (await getBusinessForm({
|
||||
key: window.localStorage.getItem('businessKey'),
|
||||
modelNodeId: props.flowNode.id
|
||||
})) as unknown as FormVO
|
||||
console.log('%csrc/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue:1035 object', 'color: #007acc;', bpmnForm);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ import install from '@form-create/element-ui/auto-import'
|
|||
import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
|
||||
import { processForm } from '@/components/processForm'
|
||||
import { processTable } from '@/components/processTable'
|
||||
import { SelectComponent } from '@/components/SelectCustomer'
|
||||
import { useApiSelect } from '@/components/FormCreate'
|
||||
import { Editor } from '@/components/Editor'
|
||||
import DictSelect from '@/components/FormCreate/src/components/DictSelect.vue'
|
||||
|
|
@ -116,6 +117,7 @@ const components = [
|
|||
UploadFile,
|
||||
processForm,
|
||||
processTable,
|
||||
SelectComponent,
|
||||
DictSelect,
|
||||
UserSelect,
|
||||
DeptSelect,
|
||||
|
|
|
|||
|
|
@ -34,7 +34,8 @@
|
|||
<el-row>
|
||||
<el-col :span="12">
|
||||
<el-form-item label="客户名称" prop="customerId">
|
||||
<el-select
|
||||
<SelectComponent :customerList="customerList" :disabled="formData.customerDefault" :value="formData.customerId" />
|
||||
<!-- <el-select
|
||||
:disabled="formData.customerDefault"
|
||||
v-model="formData.customerId"
|
||||
:loading="loading"
|
||||
|
|
@ -54,7 +55,7 @@
|
|||
:label="item.name"
|
||||
:value="item.id" />
|
||||
|
||||
</el-select>
|
||||
</el-select> -->
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="12">
|
||||
|
|
@ -178,7 +179,7 @@ import * as CustomerApi from '@/api/crm/customer'
|
|||
import * as AreaApi from '@/api/system/area'
|
||||
import { defaultProps } from '@/utils/tree'
|
||||
import { useUserStore } from '@/store/modules/user'
|
||||
|
||||
import SelectComponent from '@/components/SelectCustomer/src/index.vue'
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
|
|
|
|||
|
|
@ -56,7 +56,45 @@
|
|||
<dict-tag v-else :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="线上价格" align="center" min-width="150">
|
||||
<el-table-column label="基础服务费(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.basicServiceFee`" :rules="formRules.basicServiceFee" class="mb-0px!">
|
||||
<!-- <el-input v-model="row.basicServiceFee" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" /> -->
|
||||
{{row.basicServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="垫资服务费(元)" min-width="140">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.offlinePrice`" :rules="formRules.offlinePrice" class="mb-0px!">
|
||||
<!-- <el-input v-model="row.offlinePrice" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" /> -->
|
||||
{{row.advancePaymentServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="代订服务费(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.advancePaymentServiceFee`" :rules="formRules.advancePaymentServiceFee" class="mb-0px!">
|
||||
{{row.bookingPaymentServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="票据分拣服务费(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.billSortingServiceFee`" :rules="formRules.billSortingServiceFee" class="mb-0px!">
|
||||
{{row.billSortingServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="服务费收入合计(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.totalServiceFee`" :rules="formRules.totalServiceFee" class="mb-0px!">
|
||||
{{row.totalServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- <el-table-column label="线上价格" align="center" min-width="150">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.onlinePrice`" :rules="formRules.onlinePrice" class="mb-0px!" v-if="!type">
|
||||
<el-input v-model="row.onlinePrice" placeholder="请输入线上价格" disabled />
|
||||
|
|
@ -78,14 +116,11 @@
|
|||
</el-table-column>
|
||||
<el-table-column label="总计价格" align="center" min-width="150">
|
||||
<template #default="{ row }">
|
||||
<!-- <el-form-item :prop="`${$index}.totalPrice`" :rules="formRules.totalPrice" class="mb-0px!">
|
||||
<el-input v-model="row.totalPrice" placeholder="请输入总计价格" disabled />
|
||||
</el-form-item> -->
|
||||
<div>
|
||||
{{row.onlinePrice}}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column> -->
|
||||
<el-table-column label="产品票据" align="center" min-width="140">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.productInvoice`" :rules="formRules.productInvoice" class="mb-0px!" v-if="!type">
|
||||
|
|
@ -207,8 +242,11 @@ const onChangeProduct = (productId, row) => {
|
|||
if (product) {
|
||||
row.productUnit = product.unit
|
||||
row.productNo = product.no
|
||||
row.productPrice = product.price
|
||||
row.contractPrice = product.price
|
||||
row.basicServiceFee = product.basicServiceFee
|
||||
row.advancePaymentServiceFee = product.advancePaymentServiceFee
|
||||
row.bookingPaymentServiceFee = product.bookingPaymentServiceFee
|
||||
row.billSortingServiceFee = product.billSortingServiceFee
|
||||
row.totalServiceFee = product.totalServiceFee
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -235,7 +235,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="拓展人" prop="expanderUserId">
|
||||
<el-select v-model="formData.expanderUserId" placeholder="" disabled>
|
||||
<el-option
|
||||
|
|
@ -246,7 +246,7 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="方案报价人" prop="pricingUserId">
|
||||
<el-select v-model="formData.pricingUserId" placeholder="" disabled>
|
||||
|
|
@ -259,7 +259,7 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="报价签约人" prop="signUserId">
|
||||
<el-select v-model="formData.signUserId" placeholder="" disabled>
|
||||
<el-option
|
||||
|
|
@ -270,7 +270,7 @@
|
|||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="签约人联系电话" prop="signPhoneNumber">
|
||||
<el-input v-model="formData.signPhoneNumber" placeholder="请输入签约人联系电话" />
|
||||
|
|
@ -323,11 +323,6 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="授信额度" prop="creditLimit">
|
||||
<el-input v-model="formData.creditLimit" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="票据模板" prop="invoiceTemplateId">
|
||||
<el-select v-model="formData.invoiceTemplateId" placeholder="" disabled >
|
||||
|
|
@ -340,10 +335,33 @@
|
|||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="第几次报价" prop="quotationTimes">
|
||||
<el-input v-model="formData.quotationTimes" disabled placeholder="" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="授信额度" prop="creditLimit">
|
||||
<el-input v-model="formData.creditLimit" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="线上总金额" prop="onlinePrice">
|
||||
<el-form-item label="服务费收取方式" prop="serviceFeeCollectionMethodId">
|
||||
<el-select v-model="formData.serviceFeeCollectionMethodId" disabled placeholder="">
|
||||
<el-option
|
||||
v-for="dict in serverMethodList"
|
||||
:key="dict.id"
|
||||
:label="dict.productDetail"
|
||||
:value="dict.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="基础服务费合计" prop="onlinePrice">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.onlinePrice"
|
||||
|
|
@ -351,7 +369,7 @@
|
|||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="线下总金额" prop="offlinePrice">
|
||||
<el-input
|
||||
disabled
|
||||
|
|
@ -359,9 +377,9 @@
|
|||
:formatter="erpPriceInputFormatter"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="总金额" prop="totalPrice">
|
||||
<el-form-item label="服务费收入合计" prop="totalPrice">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.totalPrice"
|
||||
|
|
@ -395,6 +413,7 @@ import { propTypes } from '@/utils/propTypes'
|
|||
/** CRM 方案报价 表单 */
|
||||
defineOptions({ name: 'QuotationForm' })
|
||||
|
||||
const serverMethodList = ref([])
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
const customerList = ref([]) // 客户列表的数据
|
||||
|
|
@ -481,6 +500,32 @@ const formRules = reactive({
|
|||
// creditMethod: [{ required: true, message: '授信方式不能为空', trigger: 'change' }],
|
||||
// creditCalcCycle: [{ required: true, message: '授信计算周期不能为空', trigger: 'change' }],
|
||||
})
|
||||
watch(
|
||||
() => formData.value.products,
|
||||
(newProducts) => {
|
||||
if (!Array.isArray(newProducts)) {
|
||||
console.warn('formData.value.products is not an array');
|
||||
return;
|
||||
}
|
||||
|
||||
let totalOnlinePrice = 0;
|
||||
let totalOfflinePrice = 0;
|
||||
|
||||
for (const product of newProducts) {
|
||||
if (typeof product.basicServiceFee) {
|
||||
totalOnlinePrice += Number(product.basicServiceFee);
|
||||
}
|
||||
if (typeof product.totalServiceFee) {
|
||||
totalOfflinePrice += Number(product.totalServiceFee);
|
||||
}
|
||||
}
|
||||
formData.value.onlinePrice = totalOnlinePrice.toFixed(2)
|
||||
// formData.value.offlinePrice = (totalOfflinePrice + totalOnlinePrice).toFixed(2)
|
||||
// let all = totalOnlinePrice + totalOfflinePrice + totalOnlinePrice
|
||||
formData.value.totalPrice = totalOfflinePrice.toFixed(2)
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 子表的表单 */
|
||||
|
|
@ -582,6 +627,7 @@ const open = async (type: string) => {
|
|||
totalOfflinePrice += Number(product.offlinePrice);
|
||||
}
|
||||
}
|
||||
formData.value.serviceFeeCollectionMethodId = Number(formData.value.serviceFeeCollectionMethodId)
|
||||
formData.value.onlinePrice = totalOnlinePrice.toFixed(2)
|
||||
formData.value.offlinePrice = (totalOfflinePrice + totalOnlinePrice).toFixed(2)
|
||||
let all = totalOnlinePrice + totalOfflinePrice + totalOnlinePrice
|
||||
|
|
@ -670,7 +716,6 @@ const resetForm = () => {
|
|||
|
||||
const route = useRoute();
|
||||
onMounted(async () => {
|
||||
console.log('%csrc/views/crm/quotation/QuotationDetail.vue:651 props.id', 'color: #007acc;', props.id, route.query.id);
|
||||
formType.value = props.id || route.query.id;
|
||||
|
||||
if (formType.value) open(formType.value)
|
||||
|
|
@ -688,6 +733,9 @@ onMounted(async () => {
|
|||
businessList.value = await BusinessApi.getSelfSimpleBusinessList()
|
||||
// 获得部门树
|
||||
deptTree.value = handleTree(await DeptApi.getSimpleDeptList())
|
||||
//服务费收取方式
|
||||
let serverList = await QuotationApi.getServerMethodList({pageNo: 1, pageSize: 1000})
|
||||
serverMethodList.value = serverList.list
|
||||
const org = await ContractApi.getOrg({
|
||||
pageNo: 1,
|
||||
pageSize: 1000
|
||||
|
|
|
|||
|
|
@ -203,18 +203,7 @@
|
|||
<el-input v-model="formData.businessLicense" disabled />
|
||||
</el-form-item>
|
||||
</el-col>-->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="服务费收取方式" prop="serviceFeeCollectionMethodId">
|
||||
<el-select v-model="formData.serviceFeeCollectionMethodId" placeholder="请选择服务费收取方式">
|
||||
<el-option
|
||||
v-for="dict in serverMethodList"
|
||||
:key="dict.id"
|
||||
:label="dict.productDetail"
|
||||
:value="dict.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
|
||||
<el-row>
|
||||
|
|
@ -360,7 +349,19 @@
|
|||
</el-row>
|
||||
<el-row>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="线上总金额" prop="onlinePrice">
|
||||
<el-form-item label="服务费收取方式" prop="serviceFeeCollectionMethodId">
|
||||
<el-select v-model="formData.serviceFeeCollectionMethodId" @change="changeQuotationTimes" placeholder="请选择服务费收取方式">
|
||||
<el-option
|
||||
v-for="dict in serverMethodList"
|
||||
:key="dict.id"
|
||||
:label="dict.productDetail"
|
||||
:value="dict.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="基础服务费合计" prop="onlinePrice">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.onlinePrice"
|
||||
|
|
@ -368,7 +369,7 @@
|
|||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<!-- <el-col :span="8">
|
||||
<el-form-item label="线下总金额" prop="offlinePrice">
|
||||
<el-input
|
||||
disabled
|
||||
|
|
@ -376,9 +377,9 @@
|
|||
:formatter="erpPriceInputFormatter"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-col> -->
|
||||
<el-col :span="8">
|
||||
<el-form-item label="总金额" prop="totalPrice">
|
||||
<el-form-item label="服务费收入合计" prop="totalPrice">
|
||||
<el-input
|
||||
disabled
|
||||
v-model="formData.totalPrice"
|
||||
|
|
@ -391,7 +392,7 @@
|
|||
<!-- 子表的表单 -->
|
||||
<el-tabs v-model="subTabsName" @tab-Click="handleClick">
|
||||
<el-tab-pane label="报价产品关联" name="quotationProduct">
|
||||
<QuotationProductForm ref="quotationProductFormRef" :handleType="handleType" :quotation-id="formData.id" :business-id="formData.businessId" :billTemplateId="formData.invoiceTemplateId" :products="formData.products" @success="setSuccess" />
|
||||
<QuotationProductForm ref="quotationProductFormRef" :handleType="handleType" :quotation-id="formData.id" :serviceFeeId ="formData.serviceFeeCollectionMethodId" :business-id="formData.businessId" :billTemplateId="formData.invoiceTemplateId" :products="formData.products" :QuotationTimes="formData.QuotationTimes" @success="setSuccess" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="营收分析" name="RevenueAnalysis">
|
||||
<RevenueAnalysis ref="RevenueAnalysisFormRef" :quotation-id="formData.id" :products="formData.products" />
|
||||
|
|
@ -530,17 +531,17 @@ watch(
|
|||
let totalOfflinePrice = 0;
|
||||
|
||||
for (const product of newProducts) {
|
||||
if (typeof product.onlinePrice) {
|
||||
totalOnlinePrice += Number(product.onlinePrice);
|
||||
if (typeof product.basicServiceFee) {
|
||||
totalOnlinePrice += Number(product.basicServiceFee);
|
||||
}
|
||||
if (typeof product.offlinePrice) {
|
||||
totalOfflinePrice += Number(product.offlinePrice);
|
||||
if (typeof product.totalServiceFee) {
|
||||
totalOfflinePrice += Number(product.totalServiceFee);
|
||||
}
|
||||
}
|
||||
formData.value.onlinePrice = totalOnlinePrice.toFixed(2)
|
||||
formData.value.offlinePrice = (totalOfflinePrice + totalOnlinePrice).toFixed(2)
|
||||
let all = totalOnlinePrice + totalOfflinePrice + totalOnlinePrice
|
||||
formData.value.totalPrice = all.toFixed(2)
|
||||
// formData.value.offlinePrice = (totalOfflinePrice + totalOnlinePrice).toFixed(2)
|
||||
// let all = totalOnlinePrice + totalOfflinePrice + totalOnlinePrice
|
||||
formData.value.totalPrice = totalOfflinePrice.toFixed(2)
|
||||
},
|
||||
{ deep: true }
|
||||
);
|
||||
|
|
@ -549,16 +550,40 @@ const setSuccess = (val) => {
|
|||
formData.value.products = val
|
||||
}
|
||||
|
||||
const changeQuotationTimes = async() => {
|
||||
if(formData.value.serviceFeeCollectionMethodId && formData.value.businessId) {
|
||||
newProducts.value = []
|
||||
formData.value.products.forEach( item => {
|
||||
newProducts.value.push({
|
||||
id: item.productId,
|
||||
productUnit: item.productUnit,
|
||||
productName: item.productName,
|
||||
detailType: item.detailType,
|
||||
category: item.category
|
||||
})
|
||||
})
|
||||
let data = {
|
||||
businessId: formData.value.businessId,
|
||||
creditMethod: formData.value.creditMethod,
|
||||
serviceFeeCollectionMethodId: formData.value.serviceFeeCollectionMethodId,
|
||||
paymentTerm: formData.value.paymentTerm,
|
||||
quotationProducts: newProducts.value
|
||||
}
|
||||
|
||||
let num = await QuotationApi.getServerFee(data)
|
||||
formData.value.QuotationTimes = num.quotationProducts
|
||||
console.log('%csrc/views/crm/quotation/QuotationForm.vue:574 formData.value.QuotationTimes', 'color: #007acc;', formData.value.QuotationTimes);
|
||||
}
|
||||
}
|
||||
|
||||
//获取营收分析
|
||||
const RevenueAnalysisFormRef = ref('')
|
||||
const newProducts = ref([])
|
||||
const handleClick = (val) => {
|
||||
console.log('%csrc/views/crm/quotation/QuotationForm.vue:556 subTabsName.value ', 'color: #007acc;', subTabsName.value );
|
||||
if (subTabsName.value == 'RevenueAnalysis') return
|
||||
|
||||
if(!formData.value.serviceFeeCollectionMethodId) return message.warning('请选择服务费收取方式')
|
||||
|
||||
console.log('%csrc/views/crm/quotation/QuotationForm.vue:561 1111', 'color: #007acc;', 1111);
|
||||
newProducts.value = []
|
||||
formData.value.products.forEach( item => {
|
||||
newProducts.value.push({
|
||||
|
|
@ -586,6 +611,8 @@ console.log('%csrc/views/crm/quotation/QuotationForm.vue:561 1111', 'color: #007
|
|||
const onBusinessChange = async (businessId: string) => {
|
||||
if (!businessId) return
|
||||
|
||||
changeQuotationTimes()
|
||||
|
||||
handleType.value = 1
|
||||
try {
|
||||
formLoading.value = true;
|
||||
|
|
@ -604,6 +631,7 @@ const onBusinessChange = async (businessId: string) => {
|
|||
|
||||
// 🔁 自动加载客户详情
|
||||
await onCustomerChange(res.customerId);
|
||||
await getQutotaionTimes(res.customerId);
|
||||
} catch (err) {
|
||||
} finally {
|
||||
formLoading.value = false;
|
||||
|
|
@ -661,6 +689,10 @@ const onPartnerChange = async (id: string) => {
|
|||
formLoading.value = false;
|
||||
}
|
||||
}
|
||||
const getQutotaionTimes = async (val) => {
|
||||
console.log('%csrc/views/crm/quotation/QuotationForm.vue:692 val', 'color: #007acc;', val);
|
||||
formData.value.quotationTimes = await QuotationApi.getQutoTimes({customerId: val})
|
||||
}
|
||||
|
||||
const changeNum = (val) => {
|
||||
formData.value.creditLimit = (Number(val) + (formData.value.creditAmount || 0)).toFixed(2)
|
||||
|
|
|
|||
|
|
@ -32,24 +32,42 @@
|
|||
<dict-tag :type="DICT_TYPE.CRM_PRODUCT_UNIT" :value="row.productUnit" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="线上价格" align="center" min-width="150">
|
||||
<template #default="{ row }">
|
||||
{{row.onlinePrice}}
|
||||
<el-table-column label="基础服务费(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.basicServiceFee`" :rules="formRules.basicServiceFee" class="mb-0px!">
|
||||
<!-- <el-input v-model="row.basicServiceFee" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" /> -->
|
||||
{{row.basicServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="线下手续费" align="center" min-width="150">
|
||||
<template #default="{ row }">
|
||||
{{row.offlinePrice}}
|
||||
|
||||
<el-table-column label="垫资服务费(元)" min-width="140">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.advancePaymentServiceFee`" :rules="formRules.offlinePrice" class="mb-0px!">
|
||||
<!-- <el-input v-model="row.offlinePrice" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" /> -->
|
||||
{{row.advancePaymentServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="线下价格(元)" align="center" min-width="130">
|
||||
<template #default="{ row }">
|
||||
{{row.downlinePrice}}
|
||||
<el-table-column label="代订服务费(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.bookingPaymentServiceFee`" :rules="formRules.advancePaymentServiceFee" class="mb-0px!">
|
||||
{{row.bookingPaymentServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总计价格" align="center" min-width="150">
|
||||
<template #default="{ row }">
|
||||
{{row.totalPrice}}
|
||||
<el-table-column label="票据分拣服务费(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.billSortingServiceFee`" :rules="formRules.billSortingServiceFee" class="mb-0px!">
|
||||
{{row.billSortingServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="服务费收入合计(元)" min-width="130">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.totalServiceFee`" :rules="formRules.totalServiceFee" class="mb-0px!">
|
||||
{{row.totalServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="产品票据" align="center" min-width="150">
|
||||
|
|
@ -117,14 +135,14 @@ watch(
|
|||
}
|
||||
nextTick(() => {
|
||||
// 循环处理
|
||||
val.forEach((item) => {
|
||||
if (item.offlinePrice != null && item.onlinePrice != null) {
|
||||
item.downlinePrice = Number((Number(item.offlinePrice) + Number(item.onlinePrice)).toFixed(2)) || 0;
|
||||
item.totalPrice = Number((Number(item.downlinePrice) + Number(item.onlinePrice)).toFixed(2)) || 0;
|
||||
} else {
|
||||
item.totalPrice = 0;
|
||||
}
|
||||
});
|
||||
// val.forEach((item) => {
|
||||
// if (item.offlinePrice != null && item.onlinePrice != null) {
|
||||
// item.downlinePrice = Number((Number(item.offlinePrice) + Number(item.onlinePrice)).toFixed(2)) || 0;
|
||||
// item.totalPrice = Number((Number(item.downlinePrice) + Number(item.onlinePrice)).toFixed(2)) || 0;
|
||||
// } else {
|
||||
// item.totalPrice = 0;
|
||||
// }
|
||||
// });
|
||||
formData.value = val
|
||||
})
|
||||
},
|
||||
|
|
|
|||
|
|
@ -46,32 +46,41 @@
|
|||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="线上价格(元)" min-width="130">
|
||||
<el-table-column label="基础服务费(元)" min-width="160">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.onlinePrice`" :rules="formRules.onlinePrice" class="mb-0px!">
|
||||
<el-input v-model="row.onlinePrice" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" />
|
||||
<el-form-item :prop="`${$index}.basicServiceFee`" :rules="formRules.basicServiceFee" class="mb-0px!">
|
||||
<!-- <el-input v-model="row.basicServiceFee" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" /> -->
|
||||
{{row.basicServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="线下手续费(元)" min-width="140">
|
||||
<el-table-column label="垫资服务费(元)" min-width="160">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.offlinePrice`" :rules="formRules.offlinePrice" class="mb-0px!">
|
||||
<el-input v-model="row.offlinePrice" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" />
|
||||
<!-- <el-input v-model="row.offlinePrice" oninput="value=value.match(/^\d+(?:\.\d{0,2})?/)" placeholder="" /> -->
|
||||
{{row.advancePaymentServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="线下价格(元)" min-width="130">
|
||||
<el-table-column label="代订服务费(元)" min-width="160">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.downlinePrice`" :rules="formRules.onlinePrice" class="mb-0px!">
|
||||
{{row.downlinePrice}}
|
||||
<el-form-item :prop="`${$index}.advancePaymentServiceFee`" :rules="formRules.advancePaymentServiceFee" class="mb-0px!">
|
||||
{{row.bookingPaymentServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="总计价格(元)" min-width="130">
|
||||
<el-table-column label="票据分拣服务费(元)" min-width="172">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.totalPrice`" :rules="formRules.totalPrice" class="mb-0px!">
|
||||
{{row.totalPrice}}
|
||||
<el-form-item :prop="`${$index}.billSortingServiceFee`" :rules="formRules.billSortingServiceFee" class="mb-0px!">
|
||||
{{row.billSortingServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="服务费收入合计(元)" min-width="172">
|
||||
<template #default="{ row, $index }">
|
||||
<el-form-item :prop="`${$index}.totalServiceFee`" :rules="formRules.totalServiceFee" class="mb-0px!">
|
||||
{{row.totalServiceFee}}
|
||||
</el-form-item>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
|
@ -153,7 +162,9 @@ const props = defineProps<{
|
|||
businessId: undefined,
|
||||
billTemplateId: undefined,
|
||||
products: undefined,
|
||||
handleType: undefined
|
||||
handleType: undefined,
|
||||
serviceFeeId: undefined
|
||||
QuotationTimes: []
|
||||
}>()
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formData = ref([])
|
||||
|
|
@ -164,8 +175,8 @@ const formRules = reactive({
|
|||
category: [{ required: true, message: '产品类型不能为空', trigger: 'blur' }],
|
||||
detailType: [{ required: true, message: '产品明细类型不能为空', trigger: 'blur' }],
|
||||
productUnit: [{ required: true, message: '产品单位不能为空', trigger: 'blur' }],
|
||||
onlinePrice: [{ required: true, message: '线上价格不能为空', trigger: 'blur' }],
|
||||
offlinePrice: [{ required: true, message: '线下价格不能为空', trigger: 'blur' }],
|
||||
basicServiceFee: [{ required: true, message: '基础服务费不能为空', trigger: 'blur' }],
|
||||
// offlinePrice: [{ required: true, message: '线下价格不能为空', trigger: 'blur' }],
|
||||
totalPrice: [{ required: true, message: '总计价格不能为空', trigger: 'blur' }],
|
||||
productInvoiceItem: [{ required: true, message: '产品开具项目不能为空', trigger: 'blur' }],
|
||||
serviceInvoice: [{ required: true, message: '服务费票据不能为空', trigger: 'blur' }],
|
||||
|
|
@ -254,6 +265,46 @@ watch(
|
|||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
watch(
|
||||
() => props.QuotationTimes,
|
||||
async (val) => {
|
||||
// 2. val 非空,则加载数据
|
||||
if (!val || !val.length) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
formLoading.value = true
|
||||
for(let i = 0; i < val.length; i++) {
|
||||
let data = val[i]
|
||||
if(!data.id) {
|
||||
data.basicServiceFee = ''
|
||||
data.advancePaymentServiceFee = ''
|
||||
data.bookingPaymentServiceFee = ''
|
||||
data.billSortingServiceFee = ''
|
||||
data.totalServiceFee = ''
|
||||
}
|
||||
console.log('%csrc/views/crm/quotation/components/QuotationProductForm.vue:289 formData.value,data', 'color: #007acc;', formData.value,data);
|
||||
let foundItem = formData.value.find(item => item.productId == data.id);
|
||||
console.log('%csrc/views/crm/quotation/components/QuotationProductForm.vue:290 foundItem', 'color: #007acc;', foundItem);
|
||||
if (foundItem) {
|
||||
foundItem.basicServiceFee = data.serviceFeeVO.basicServiceFee
|
||||
foundItem.advancePaymentServiceFee = data.serviceFeeVO.advancePaymentServiceFee
|
||||
foundItem.bookingPaymentServiceFee = data.serviceFeeVO.bookingPaymentServiceFee
|
||||
foundItem.billSortingServiceFee = data.serviceFeeVO.billSortingServiceFee
|
||||
foundItem.totalServiceFee = data.serviceFeeVO.totalServiceFee
|
||||
}
|
||||
}
|
||||
// formData.value = data
|
||||
// emit('update:handleType', 0)
|
||||
// }
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
},
|
||||
{ deep: true }
|
||||
)
|
||||
|
||||
// 监听合同产品变化,计算合同产品总价
|
||||
watch(
|
||||
() => formData.value,
|
||||
|
|
@ -262,14 +313,14 @@ watch(
|
|||
return;
|
||||
}
|
||||
// 循环处理
|
||||
val.forEach((item) => {
|
||||
if (item.offlinePrice != null && item.onlinePrice != null) {
|
||||
item.downlinePrice = Number((Number(item.offlinePrice) + Number(item.onlinePrice)).toFixed(2)) || 0;
|
||||
item.totalPrice = Number((Number(item.downlinePrice) + Number(item.onlinePrice)).toFixed(2)) || 0;
|
||||
} else {
|
||||
item.totalPrice = 0;
|
||||
}
|
||||
});
|
||||
// val.forEach((item) => {
|
||||
// if (item.offlinePrice != null && item.basicServiceFee != null) {
|
||||
// item.downlinePrice = Number((Number(item.offlinePrice) + Number(item.basicServiceFee)).toFixed(2)) || 0;
|
||||
// item.totalServiceFee = Number((Number(item.downlinePrice) + Number(item.basicServiceFee)).toFixed(2)) || 0;
|
||||
// } else {
|
||||
// item.totalServiceFee = 0;
|
||||
// }
|
||||
// });
|
||||
emit('success', formData.value)
|
||||
},
|
||||
{ deep: true }
|
||||
|
|
@ -297,9 +348,9 @@ const handleAdd = () => {
|
|||
productName: undefined,
|
||||
detailType: undefined,
|
||||
productUnit: undefined,
|
||||
onlinePrice: undefined,
|
||||
basicServiceFee: undefined,
|
||||
offlinePrice: undefined,
|
||||
totalPrice: undefined,
|
||||
totalServiceFee: undefined,
|
||||
productInvoice: undefined,
|
||||
productInvoiceItem: undefined,
|
||||
serviceInvoice: undefined,
|
||||
|
|
|
|||
Loading…
Reference in New Issue