diff --git a/src/api/crm/feedback/index.ts b/src/api/crm/feedback/index.ts
new file mode 100644
index 000000000..1ff57293b
--- /dev/null
+++ b/src/api/crm/feedback/index.ts
@@ -0,0 +1,54 @@
+import request from '@/config/axios'
+
+// 客户反馈 VO
+export interface CustomerFeedbackVO {
+ id: number // 主键
+ customerId: number // 客户ID
+ contactId: number // 反馈联系人ID
+ mobile: string // 联系电话
+ email: string // 电子邮箱
+ feedbackType: number // 反馈类型
+ feedbackLevel: number // 反馈级别
+ urgencyLevel: number // 紧急程度
+ feedbackTime: Date // 反馈时间
+ relatedPerson: number // 当事人用户ID
+ deptId: number // 所属部门ID
+ customerFeedbackCount: number // 客户累计计数
+ relatedPersonFeedbackCount: number // 当事人累计计数
+ feedbackCompanyEntity: string // 反馈主体
+ feedbackContent: string // 反馈内容
+ attachment: string // 附件
+}
+
+// 客户反馈 API
+export const CustomerFeedbackApi = {
+ // 查询客户反馈分页
+ getCustomerFeedbackPage: async (params: any) => {
+ return await request.get({ url: `/crm/customer-feedback/page`, params })
+ },
+
+ // 查询客户反馈详情
+ getCustomerFeedback: async (id: number) => {
+ return await request.get({ url: `/crm/customer-feedback/get?id=` + id })
+ },
+
+ // 新增客户反馈
+ createCustomerFeedback: async (data: CustomerFeedbackVO) => {
+ return await request.post({ url: `/crm/customer-feedback/create`, data })
+ },
+
+ // 修改客户反馈
+ updateCustomerFeedback: async (data: CustomerFeedbackVO) => {
+ return await request.put({ url: `/crm/customer-feedback/update`, data })
+ },
+
+ // 删除客户反馈
+ deleteCustomerFeedback: async (id: number) => {
+ return await request.delete({ url: `/crm/customer-feedback/delete?id=` + id })
+ },
+
+ // 导出客户反馈 Excel
+ exportCustomerFeedback: async (params) => {
+ return await request.download({ url: `/crm/customer-feedback/export-excel`, params })
+ },
+}
\ No newline at end of file
diff --git a/src/api/crm/quotation/index.ts b/src/api/crm/quotation/index.ts
index b197d71b9..f8becd6ee 100644
--- a/src/api/crm/quotation/index.ts
+++ b/src/api/crm/quotation/index.ts
@@ -100,6 +100,11 @@ export const QuotationApi = {
return await request.get({ url: `/crm/quotation/get-quotation-times`, params })
},
+ // 获取保险列表
+ getInsuranceList: async (params: any) => {
+ return await request.get({ url: `/crm/service-fee-collection-method/get-insurance-list`, params })
+ },
+
// ==================== 子表(CRM 报价产品关联) ====================
// 获得CRM 报价产品关联列表
diff --git a/src/components/SelectCustomer/src/index.vue b/src/components/SelectCustomer/src/index.vue
index 928522178..bf0312295 100644
--- a/src/components/SelectCustomer/src/index.vue
+++ b/src/components/SelectCustomer/src/index.vue
@@ -45,15 +45,27 @@ const allFilterEvents = ref([])
watch(() => props.modelValue, (val) => {
selectValue.value = val
- let arr = options.value.filter(v => v.id === val)
- if (!arr.length) {
- let selectItem = props.customerList.filter(v => v.id === val)
- options.value = [...options.value, ...selectItem]
- }
+ console.log('%csrc/components/SelectCustomer/src/index.vue:48 val,', 'green', val,props.customerList);
+ nextTick(() => {
+ let arr = options.value.filter(v => v.id === val)
+ if (!arr.length) {
+ let selectItem = props.customerList.filter(v => v.id === val)
+ options.value = [...options.value, ...selectItem]
+ }
+ })
}, { immediate: true })
watch(() => props.customerList, (val) => {
options.value = val.slice(0, 10)
+ console.log('%csrc/components/SelectCustomer/src/index.vue:60 props.customerList,4444', 'color: pink;', props.modelValue,props.customerList,4444);
+ nextTick(() => {
+ let arr = options.value.filter(v => v.id === props.modelValue)
+ if (!arr.length) {
+ let selectItem = props.customerList.filter(v => v.id === props.modelValue)
+ console.log('%csrc/components/SelectCustomer/src/index.vue:65 selectItem', 'color: #007acc;', selectItem);
+ options.value = [...options.value, ...selectItem]
+ }
+ })
}, { deep: true })
let pageNo = ref(1)
diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts
index 1ff9a2541..625807510 100644
--- a/src/router/modules/remaining.ts
+++ b/src/router/modules/remaining.ts
@@ -773,6 +773,42 @@ const remainingRouter: AppRouteRecordRaw[] = [
activeMenu: '/crm/customer-complaints'
}
},
+ {
+ path: 'feedback/CustomerFeedbackForm',
+ component: () => import('@/views/crm/feedback/CustomerFeedbackForm.vue'),
+ name: 'CustomerFeedbackCreate',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ title: '客户反馈新增',
+ activeMenu: '/crm/feed-back'
+ }
+ },
+ {
+ path: 'feedback/CustomerFeedbackFormEdit',
+ component: () => import('@/views/crm/feedback/CustomerFeedbackForm.vue'),
+ name: 'CustomerFeedbackEdit',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ title: '客户反馈编辑',
+ activeMenu: '/crm/feed-back'
+ }
+ },
+ {
+ path: 'feedback/CustomerFeedbackDetail',
+ component: () => import('@/views/crm/feedback/CustomerFeedbackDetail.vue'),
+ name: 'CustomerFeedbackDetail',
+ meta: {
+ noCache: true,
+ hidden: true,
+ canTo: true,
+ title: '客户反馈详情',
+ activeMenu: '/crm/feed-back'
+ }
+ },
{
path: 'filetemplate/previewDoc',
component: () => import('@/views/crm/filetemplate/previewDoc.vue'),
diff --git a/src/styles/index.scss b/src/styles/index.scss
index 7607941c4..fa7dbda99 100644
--- a/src/styles/index.scss
+++ b/src/styles/index.scss
@@ -35,3 +35,7 @@
border-left-color: var(--el-color-primary);
}
}
+
+.mt-3 {
+ margin-bottom: 10px;
+}
\ No newline at end of file
diff --git a/src/utils/dict.ts b/src/utils/dict.ts
index 90a67f639..edbc8bd2b 100644
--- a/src/utils/dict.ts
+++ b/src/utils/dict.ts
@@ -220,6 +220,7 @@ export enum DICT_TYPE {
SALE_STAGE='sale_stage',// 销售阶段
TIME_TYPE='time_type',// 时间类型
CRM_PARTNER_TYPE = 'crm_partner_type',//合作类型
+ CRM_PARTNER_TYPE1 = 'CRM_PARTNER_TYPE1',//合作类型
CRM_SERVICE_FEE_COLLECTION_METHOD = 'crm_service_fee_collection_method',//服务费收取方式
CRM_CONTACT_ROLE_TYPE = 'crm_contact_role_type',//角色
@@ -242,6 +243,9 @@ export enum DICT_TYPE {
SYNCHRONIZATION_STATUS="synchronization_status", //同步状态
MATCHING_PRODUCT_TYPES="matching_product_types", //对接产品类型
CRM_SERVICE_FEE_COLLECTION_METHOD_TYPE = 'crm_service_fee_collection_method_type', // 服务费收取方式类型
+ CRM_URGENCY_LEVEL = "crm_urgency_level", // 紧急程度
+ CRM_FEEDBACK_LEVEL = "crm_feedback_level", // 反馈级别
+ CRM_FEEDBACK_TYPE = "crm_feedback_type", // 反馈类型
// ========== ERP - 企业资源计划模块 ==========
diff --git a/src/views/crm/business/BusinessForm.vue b/src/views/crm/business/BusinessForm.vue
index 0a6a3c939..1815308d3 100644
--- a/src/views/crm/business/BusinessForm.vue
+++ b/src/views/crm/business/BusinessForm.vue
@@ -8,11 +8,11 @@
v-loading="formLoading"
>
-
+
@@ -34,11 +34,11 @@
-
+
-->
-
+
-->
-
-
-
-
-
-
+
+
+ 项目难度
+
@@ -219,11 +212,39 @@
+
+
+
+
+
+
+
+
+
+ 注:行政自主在线上预定,无审批流,无差标,无客服服务
+
+
+
+
+
+ {{dict.label}}
+
+
+
@@ -232,6 +253,7 @@
@@ -288,12 +310,15 @@ import { defaultProps, handleTree } from '@/utils/tree';
import BusinessProductForm from './components/BusinessProductForm.vue';
import { erpPriceMultiply, erpPriceInputFormatter } from '@/utils';
import { propTypes } from '@/utils/propTypes'
+import { json } from 'stream/consumers';
const { proxy }: any = getCurrentInstance();
const { t } = useI18n();
const message = useMessage();
+const checkList = ref([])
+const productsTypeList = ref([])
const dialogVisible = ref(false);
const dialogTitle = ref('');
const formLoading = ref(false);
@@ -305,7 +330,7 @@ const formData = ref({
followUpStatus: undefined,
contactLastTime: undefined,
contactNextTime: undefined,
- ownerUserId: undefined,
+ clueDeveloper: undefined,
deptId: undefined,
requestorUserId: undefined,
statusTypeId: undefined,
@@ -327,7 +352,7 @@ const formData = ref({
const formRules = reactive({
name: [{ required: true, message: '商机名称不能为空', trigger: 'blur' }],
customerId: [{ required: true, message: '客户不能为空', trigger: 'blur' }],
- ownerUserId: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
+ clueDeveloper: [{ required: true, message: '负责人不能为空', trigger: 'blur' }],
statusTypeId: [{ required: true, message: '商机状态组不能为空', trigger: 'blur' }],
saleStage: [{ required: true, message: '销售阶段不能为空', trigger: 'change' }],
paymentTerm: [{ required: true, message: '账期不能为空', trigger: 'change' }],
@@ -391,10 +416,16 @@ const open = async (id?: number, customerId?: number) => {
formLoading.value = true;
try {
const data = await BusinessApi.getBusiness(id);
+ productsTypeList.value = JSON.parse(JSON.stringify(data.products))
formData.value = {
...data,
products: data.products || []
};
+ let newData = []
+ data.products.map(v => {
+ newData.push(v.category)
+ })
+ checkList.value = [...new Set(newData)]
} finally {
formLoading.value = false;
}
@@ -408,6 +439,7 @@ const open = async (id?: number, customerId?: number) => {
};
const setList = (newProducts) => {
+ checkList.value = []
formData.value.products = newProducts;
};
@@ -456,7 +488,7 @@ const resetForm = () => {
id: undefined,
name: undefined,
customerId: undefined,
- ownerUserId: undefined,
+ clueDeveloper: undefined,
statusTypeId: undefined,
dealTime: undefined,
totalPrice: 0,
@@ -468,10 +500,15 @@ const resetForm = () => {
formRef.value?.resetFields();
};
+const changeCheck = (val) => {
+ productFormRef.value.getData(val)
+}
+
const route = useRoute();
onMounted(async () => {
const customerId = route.query.customerId;
- formData.value.ownerUserId = customerId ? '' : useUserStore().getUser.id;
+ formData.value.clueDeveloper = customerId ? '' : useUserStore().getUser.id;
+ formData.value.requestorUserId = customerId ? '' : useUserStore().getUser.id;
formType.value = route.query.id || route.params.id;
if (formType.value) open(formType.value, customerId)
customerList.value = await CustomerApi.getSelfCustomerSimpleList();
@@ -485,3 +522,12 @@ onMounted(async () => {
deptTree.value = handleTree(await DeptApi.getSimpleDeptList());
});
+
+
diff --git a/src/views/crm/business/components/BusinessProductForm.vue b/src/views/crm/business/components/BusinessProductForm.vue
index ffddd6fce..69db18253 100644
--- a/src/views/crm/business/components/BusinessProductForm.vue
+++ b/src/views/crm/business/components/BusinessProductForm.vue
@@ -62,17 +62,11 @@
-
-
+
{{row.totalPrice}}
-
-
-
-
-
- —
+
@@ -91,6 +85,7 @@ import { DICT_TYPE, getIntDictOptions } from '@/utils/dict';
const formLoading = ref(false); // 表单的加载中
const formData = ref([]); // 表单数据
+const listData = ref([])
const formRules = reactive({
detailType: [{ required: true, message: '产品明细不能为空', trigger: 'blur' }],
productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }],
@@ -103,12 +98,22 @@ const productList = ref([]); // 产品列表
const props = defineProps<{
products: any[]; // 确保 products 是一个数组
disabled: boolean; // 确保 disabled 是一个布尔值
+ productsTypeList: any[]
}>();
// 初始化设置产品项
watch(
() => props.products,
(val) => {
formData.value = val || []; // 确保 formData 是一个数组
+ // listData.value = JSON.parse(JSON.stringify(formData.value))
+ },
+ { immediate: true }
+);
+
+watch(
+ () => props.productsTypeList,
+ (val) => {
+ listData.value = val || []; // 确保 formData 是一个数组
},
{ immediate: true }
);
@@ -170,6 +175,8 @@ const getList = (val: []) => {
})
}
})
+ listData.value = JSON.parse(JSON.stringify(formData.value))
+ console.log('%csrc/views/crm/business/components/BusinessProductForm.vue:170 listData', 'color: #007acc;', listData.value);
emit('success', formData.value)
}
@@ -204,7 +211,25 @@ const onChangeProduct = (productId, row) => {
const validate = () => {
return formRef.value.validate()
};
-defineExpose({ validate });
+
+const getData = (val) => {
+
+ let newArrList = []
+ for(let i = 0; i < val.length; i++) {
+ let item = val[i]
+ let newArr = listData.value.filter(v => v.category === item)
+ newArrList = [...newArrList, ...newArr]
+ }
+ formData.value = newArrList
+
+ console.log('%csrc/views/crm/business/components/BusinessProductForm.vue:215 listData.value', 'color: #007acc;',!val.length, listData.value);
+if(!val.length) {
+ console.log('%csrc/views/crm/business/components/BusinessProductForm.vue:208 121212', 'color: #007acc;', 121212);
+ return formData.value = JSON.parse(JSON.stringify(listData.value))
+ }
+ console.log('%csrc/views/crm/business/components/BusinessProductForm.vue:218 formData.value', 'color: #007acc;', formData.value);
+};
+defineExpose({ validate, getData });
// 初始化
onMounted(async () => {
diff --git a/src/views/crm/business/index.vue b/src/views/crm/business/index.vue
index 8238a6920..13ce4003c 100644
--- a/src/views/crm/business/index.vue
+++ b/src/views/crm/business/index.vue
@@ -8,9 +8,15 @@
class="-mb-15px"
label-width="68px"
>
-
-
-
+
-
+
@@ -137,13 +143,13 @@
-
-
+ /> -->
+
-
-
+
+
-
+
-
+
diff --git a/src/views/crm/contract/ContractForm.vue b/src/views/crm/contract/ContractForm.vue
index 5251f126c..e7a5f869e 100644
--- a/src/views/crm/contract/ContractForm.vue
+++ b/src/views/crm/contract/ContractForm.vue
@@ -11,22 +11,22 @@
基础信息
-
+
-
+
-
+
+
+
+
+
+
+
+
@@ -246,7 +259,7 @@
-
+
- 单次合同
- 框架合同
+ 甲方合同
+ 乙方合同
@@ -320,6 +333,7 @@
-
+
@@ -388,19 +403,19 @@
-->
- 财务与客服对接信息
+ 对接信息
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -460,12 +555,12 @@
-
+
@@ -491,6 +586,7 @@ import { propTypes } from '@/utils/propTypes'
import { getIntDictOptions, getStrDictOptions, DICT_TYPE } from '@/utils/dict'
import { defaultProps, handleTree } from '@/utils/tree'
import * as DeptApi from '@/api/system/dept'
+import moment from 'moment';
const { t } = useI18n() // 国际化
@@ -578,8 +674,8 @@ const formData = ref({
offlinePrice: undefined,
onlinePrice: undefined,
ownerUserId: undefined,
- expanderUserId: undefined,
- pricingUserId: undefined,
+ clueDeveloper: undefined,
+ contractor: undefined,
afterSaleUserId: undefined,
collUserId: undefined,
totalPrice: undefined,
@@ -683,12 +779,12 @@ const submitForm = async () => {
return message.warning('请完善合同甲方授权人信息')
}
- if(contractBAuthorizedPersonFormRef.value.getData().length) {
- const contractBAuthorizedPersonPerson = await contractBAuthorizedPersonFormRef.value.validate()
- if (!contractBAuthorizedPersonPerson) return message.warning('请完善合同乙方授权人信息')
- } else {
- return message.warning('请完善合同乙方授权人信息')
- }
+ // if(contractBAuthorizedPersonFormRef.value.getData().length) {
+ // const contractBAuthorizedPersonPerson = await contractBAuthorizedPersonFormRef.value.validate()
+ // if (!contractBAuthorizedPersonPerson) return message.warning('请完善合同乙方授权人信息')
+ // } else {
+ // return message.warning('请完善合同乙方授权人信息')
+ // }
formLoading.value = true
@@ -697,7 +793,7 @@ const submitForm = async () => {
// 拼接子表的数据
data.contractAAuthorizedCompanys = contractAAuthorizedCompanyFormRef.value.getData()
data.contractAAuthorizedPersons = contractAAuthorizedPersonFormRef.value.getData()
- data.contractBAuthorizedPersons = contractBAuthorizedPersonFormRef.value.getData()
+ // data.contractBAuthorizedPersons = contractBAuthorizedPersonFormRef.value.getData()
if (!formType.value ) {
await ContractApi.createContract(data)
message.success(t('common.createSuccess'))
@@ -743,8 +839,8 @@ const resetForm = () => {
offlinePrice: undefined,
onlinePrice: undefined,
ownerUserId: undefined,
- expanderUserId: undefined,
- pricingUserId: undefined,
+ clueDeveloper: undefined,
+ contractor: undefined,
afterSaleUserId: undefined,
collUserId: undefined,
totalPrice: undefined,
@@ -777,7 +873,7 @@ const handleQuotationChange = async (quotationId: number) => {
formData.value.ownerUserMobile = quotation.ownerUserMobile;
formData.value.ownerUserWechat = quotation.ownerUserWechat;
formData.value.ownerUserEmail = quotation.ownerUserEmail;
- formData.value.expanderUserId = quotation.expanderUserId;
+ formData.value.clueDeveloper = quotation.clueDeveloper;
formData.value.signUserId = quotation.signUserId;
formData.value.signPhoneNumber = quotation.signPhoneNumber;
formData.value.signEmail = quotation.signEmail;
@@ -830,6 +926,11 @@ const onCustomerChange = async (customerId: string) => {
formData.value.socialEmployeeNum = customerRes.socialEmployeeNum;
formData.value.registeredAddress = customerRes.registeredAddress;
formData.value.quotationId = customerRes.quotationId;
+ formData.value.afterSaleUserId = customerRes.maintainer;
+ formData.value.servicor = customerRes.servicor;
+ formData.value.clueDeveloper = customerRes.developer;
+ formData.value.technicalLead = customerRes.technicalLead;
+ formData.value.settlementLead = customerRes.settlementLead;
await handleQuotationChange(customerRes.quotationId);
} catch (err) {
@@ -856,6 +957,25 @@ const onPartnerChange = async (id: string) => {
}
}
+const changeTime = ()=> {
+ if(formData.value.startTime && formData.value.contractTerm) {
+ let year = new Date(formData.value.startTime).getFullYear()
+ let month = new Date(formData.value.startTime).getMonth() + 1
+ let day = new Date(formData.value.startTime).getDate()
+ let addYear = Math.floor(formData.value.contractTerm / 12)
+ let addMonth = formData.value.contractTerm % 12
+ let remainMonth = addMonth + month
+ let lastMonth = remainMonth
+ if (remainMonth >= 12) {
+ lastMonth = remainMonth - 12
+ addYear = addYear + 1
+ }
+ let lastYear = addYear + year
+ formData.value.endTime = lastYear + '-' + lastMonth + '-' + day
+
+ }
+}
+
/** 动态获取客户联系人 */
const getContactOptions = computed(() =>
@@ -864,6 +984,8 @@ const getContactOptions = computed(() =>
const route = useRoute();
onMounted(async () => {
+ formData.value.contractor = useUserStore().getUser.id;
+
if(!props.changeType) {
formType.value = props.id || route.query.id
diff --git a/src/views/crm/contract/components/ContractAAuthorizedPersonForm.vue b/src/views/crm/contract/components/ContractAAuthorizedPersonForm.vue
index 74af8aefa..b8e9304bc 100644
--- a/src/views/crm/contract/components/ContractAAuthorizedPersonForm.vue
+++ b/src/views/crm/contract/components/ContractAAuthorizedPersonForm.vue
@@ -31,9 +31,9 @@
-->
-
-
-
+
+
+
+
+
+ {{getName(getIntDictOptions(DICT_TYPE.CRM_CONTACT_ROLE_TYPE), row.authPersonType)}}
@@ -206,6 +206,7 @@ const getList = (val: []) => {
val.forEach(item => {
formData.value.push({
"customerContactId": item.id,
+ "authPersonType": item.contactRoleType,
"customerName": item.name,
"phoneNumber": item.mobile,
"wechat":item. wechat,
diff --git a/src/views/crm/contract/detail/ContractDetail.vue b/src/views/crm/contract/detail/ContractDetail.vue
index 21a7c1dd5..ae454f4a2 100644
--- a/src/views/crm/contract/detail/ContractDetail.vue
+++ b/src/views/crm/contract/detail/ContractDetail.vue
@@ -40,13 +40,13 @@
-
+
@@ -67,13 +67,13 @@
-
+
-
+
@@ -307,7 +307,7 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -560,14 +636,14 @@
-
+
@@ -612,7 +688,7 @@ const formFields = ref({
customerId: 1,
no: 1,
quotationId: 1,
- pricingUserId: 1,
+ contractor: 1,
creditLimit: 1,
creditMethod: 1,
creditCalcCycle: 1,
@@ -645,11 +721,15 @@ const formFields = ref({
penaltyRate: 1,
latePaymentRate: 1,
other4: 1,
- settleMethod: 1,
+ // settleMethod: 1,
afterSaleUserId: 1,
- collUserId: 1,
- contractBody: 1,
- contractAgreement: 1,
+ expanderUserId: 1,
+ servicor: 1,
+ technicalLead: 1,
+ settlementLead: 1,
+ // collUserId: 1,
+ // contractBody: 1,
+ // contractAgreement: 1,
other5: 1,
productsother: 1,
productsproductName: 1,
@@ -722,7 +802,7 @@ const formData = ref({
onlinePrice: undefined,
ownerUserId: undefined,
expanderUserId: undefined,
- pricingUserId: undefined,
+ contractor: undefined,
afterSaleUserId: undefined,
collUserId: undefined,
totalPrice: undefined,
@@ -885,7 +965,7 @@ const resetForm = () => {
onlinePrice: undefined,
ownerUserId: undefined,
expanderUserId: undefined,
- pricingUserId: undefined,
+ contractor: undefined,
afterSaleUserId: undefined,
collUserId: undefined,
totalPrice: undefined,
diff --git a/src/views/crm/contract/index.vue b/src/views/crm/contract/index.vue
index 17974e831..bdac64b06 100644
--- a/src/views/crm/contract/index.vue
+++ b/src/views/crm/contract/index.vue
@@ -58,7 +58,7 @@
新增
-
导出
-
+ -->
-
+
diff --git a/src/views/crm/customer/CustomerForm.vue b/src/views/crm/customer/CustomerForm.vue
index e224c7739..95298b7ae 100644
--- a/src/views/crm/customer/CustomerForm.vue
+++ b/src/views/crm/customer/CustomerForm.vue
@@ -26,11 +26,11 @@
-
+
-
+
{
// 默认新建时选中自己
if (formType.value === 'create') {
formData.value.ownerUserId = useUserStore().getUser.id
- formData.value.developer = useUserStore().getUser.id
+ formData.value.clueDeveloper = useUserStore().getUser.id
// formData.value.assist = useUserStore().getUser.id
}
@@ -546,7 +546,7 @@ const resetForm = () => {
level: undefined,
source: undefined,
reamark: undefined,
- developer: undefined,
+ clueDeveloper: undefined,
assist: [],
clueDeveloper: undefined,
}
diff --git a/src/views/crm/customer/detail/CustomerDetailsHeader.vue b/src/views/crm/customer/detail/CustomerDetailsHeader.vue
index 6b04e8933..26f04be30 100644
--- a/src/views/crm/customer/detail/CustomerDetailsHeader.vue
+++ b/src/views/crm/customer/detail/CustomerDetailsHeader.vue
@@ -41,7 +41,7 @@
-
+
diff --git a/src/views/crm/customer/detail/index.vue b/src/views/crm/customer/detail/index.vue
index 166684643..2bc99c19c 100644
--- a/src/views/crm/customer/detail/index.vue
+++ b/src/views/crm/customer/detail/index.vue
@@ -51,7 +51,7 @@
-
+
@@ -230,7 +230,7 @@ const ContractListRef = ref('')
const handleClick = async (val) => {
let name = val.props.name
-
+
if(!name) return
if (val.props.name) {
diff --git a/src/views/crm/customer/index.vue b/src/views/crm/customer/index.vue
index e6eafb409..31d2f6d79 100644
--- a/src/views/crm/customer/index.vue
+++ b/src/views/crm/customer/index.vue
@@ -150,7 +150,7 @@
{{scope.row.clueDeveloperName || '暂无'}}
-->
-
+
{{scope.row.contractorName || '暂无'}}
diff --git a/src/views/crm/feedback/CustomerFeedbackDetail.vue b/src/views/crm/feedback/CustomerFeedbackDetail.vue
new file mode 100644
index 000000000..9945b36b5
--- /dev/null
+++ b/src/views/crm/feedback/CustomerFeedbackDetail.vue
@@ -0,0 +1,374 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/crm/feedback/CustomerFeedbackForm.vue b/src/views/crm/feedback/CustomerFeedbackForm.vue
new file mode 100644
index 000000000..1c178e991
--- /dev/null
+++ b/src/views/crm/feedback/CustomerFeedbackForm.vue
@@ -0,0 +1,314 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 确 定
+ 取 消
+
+
+
+
\ No newline at end of file
diff --git a/src/views/crm/feedback/index.vue b/src/views/crm/feedback/index.vue
new file mode 100644
index 000000000..1664d879d
--- /dev/null
+++ b/src/views/crm/feedback/index.vue
@@ -0,0 +1,313 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 搜索
+ 重置
+
+ 新增
+
+
+ 导出
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 预览
+
+ 无附件
+
+
+
+
+
+
+
+ 详情
+
+
+ 进度
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/views/crm/quotation/QuotationForm.vue b/src/views/crm/quotation/QuotationForm.vue
index ed0f0d5b2..267c7cfa4 100644
--- a/src/views/crm/quotation/QuotationForm.vue
+++ b/src/views/crm/quotation/QuotationForm.vue
@@ -114,7 +114,7 @@
-->
-
+
是
否
@@ -122,7 +122,7 @@
-
+
是
否
@@ -130,7 +130,7 @@
-
+
是
否
@@ -138,7 +138,7 @@
-
+
是
否
@@ -146,7 +146,7 @@
-
+
是
否
@@ -154,7 +154,7 @@
-
+
是
否
@@ -168,7 +168,7 @@
-->
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+ 需求信息
+
+
+
-
+
-
-
-
+
+
+
+
+
+
+ {{remark}}
+
+
+
+
+
+
-
-
-
-
-
-
+
-
+
-
+
@@ -440,6 +454,11 @@ defineOptions({ name: 'QuotationForm' })
const props = defineProps({
id: propTypes.number.def(undefined),
})
+const serviceDesc = ref({
+ 1:'按单项产品的订单量(机票/张,酒店/间夜,火车票/张、用车/单)分别收取服务费',
+ 2: '按订单总金额乘以比例收取服务费用',
+ 3: ''
+})
const { t } = useI18n() // 国际化
const message = useMessage() // 消息弹窗
const customerList = ref([]) // 客户列表的数据
@@ -450,8 +469,8 @@ const deptTree = ref() // 部门树形结构
const deptList = ref() // 部门
const orgList = ref([])
const handleType = ref('')
-const serverMethodList = ref([])
-
+const insuranceList = ref([])
+const remark = ref('')
const invoiceTemplateList = ref([])
const { proxy }: any = getCurrentInstance();
@@ -459,6 +478,69 @@ const dialogVisible = ref(false) // 弹窗的是否展示
const dialogTitle = ref('') // 弹窗的标题
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
const formType = ref('') // 表单的类型:create - 新增;update - 修改
+const formFields = ref({ //字段显示隐藏权限控制,字段顺序就是显示的顺序
+ businessId: 1,
+ no: 1,
+ other: 1,
+ creditAmount: 1,
+ creditLimitNum: 1,
+ creditLimit: 1,
+ customerId: 1,
+ cooperationType: 1,
+ regType: 1,
+ financingInfo: 1,
+ actualCapital: 1,
+ socialEmployeeNum: 1,
+ startDate: 1,
+ defendantRecord: 1,
+ abnormalService: 1,
+ equityPledge: 1,
+ dishonestyRecord: 1,
+ financeRecord: 1,
+ judgmentRecord: 1,
+ other1: 1,
+ partnerCompanyId: 1,
+ creditCode: 1,
+ bankName: 1,
+ bankAccount: 1,
+ legalRepresentative: 1,
+ deptId: 1,
+ ownerUserId: 1,
+ pricingUserId: 1,
+ paymentTerm: 1,
+ creditMethod: 1,
+ creditCalcCycle: 1,
+ invoiceTemplateId: 1,
+ quotationTimes: 1,
+ creditLimit1: 1,
+ serviceFeeCollectionMethodId: 1,
+ onlinePrice: 1,
+ totalPrice: 1,
+ productsother: 1,
+ productscategory: 1,
+ productsdetailType: 1,
+ productsproductUnit: 1,
+ productsbasicServiceFee: 1,
+ productsadvancePaymentServiceFee: 1,
+ productsbookingPaymentServiceFee: 1,
+ productsbillSortingServiceFee: 1,
+ productstotalServiceFee: 1,
+ productsproductInvoice: 1,
+ productsproductInvoiceItem: 1,
+ productsserviceInvoice: 1,
+ productsserviceInvoiceItem: 1,
+ quotationProductscategory: 1,
+ quotationProductsdetailType: 1,
+ quotationProductsrevenueAnalysisVOsalesVolume: 1,
+ quotationProductsrevenueAnalysisVOtotalOrderVolume: 1,
+ quotationProductsrevenueAnalysisVOtotalIncome: 1,
+ quotationProductsrevenueAnalysisVOincomeInterestRate: 1,
+ quotationProductsrevenueAnalysisVOdeductibleCost: 1,
+ quotationProductsrevenueAnalysisVOprofit: 1,
+ quotationProductsrevenueAnalysisVOprofitRate: 1,
+ quotationProductsrevenueAnalysisVOprofitSharingRatio: 1,
+ quotationProductsrevenueAnalysisVOprofitSharingIncome: 1,
+ })
const formData = ref({
no: undefined,
customerId: undefined,
@@ -529,6 +611,7 @@ const formRules = reactive({
creditCalcCycle: [{ required: true, message: '授信计算周期不能为空', trigger: 'change' }],
quotationTimes: [{ required: true, message: '第几次报价不能为空', trigger: 'change' }],
serviceFeeCollectionMethodId: [{ required: true, message: '服务费收取方式不能为空', trigger: 'change' }],
+ insuranceId: [{ required: true, message: '保险类型不能为空', trigger: 'change' }],
})
const formRef = ref() // 表单 Ref
@@ -567,7 +650,24 @@ const setSuccess = (val) => {
formData.value.products = val
}
-const changeQuotationTimes = async() => {
+const changeInsuranceId = (val) => {
+ let arr = insuranceList.value.filter(v => v.id === val)
+ remark.value = (arr.length && arr[0]['describes']) ? '注:' + arr[0]['describes'] : ''
+
+}
+
+const changeQuotation = (val) => {
+ if(serviceDesc.value[val]) {
+ remark.value = '注:' + serviceDesc.value[val]
+ } else {
+ remark.value = ''
+ }
+ formData.value.insuranceId = ''
+ changeQuotationTimes(val)
+}
+
+const changeQuotationTimes = async(val) => {
+
if(formData.value.serviceFeeCollectionMethodId && formData.value.businessId) {
newProducts.value = []
formData.value.products.forEach( item => {
@@ -833,8 +933,8 @@ onMounted(async () => {
// 获得部门树
deptTree.value = handleTree(await DeptApi.getSimpleDeptList())
//服务费收取方式
- let serverList = await QuotationApi.getServerMethodList({pageNo: 1, pageSize: 1000})
- serverMethodList.value = serverList.list
+ insuranceList.value = await QuotationApi.getInsuranceList()
+
const org = await ContractApi.getOrg({
pageNo: 1,
pageSize: 1000
@@ -842,3 +942,12 @@ onMounted(async () => {
orgList.value = org.list
});
+
+
diff --git a/src/views/crm/quotation/components/QuotationProductForm.vue b/src/views/crm/quotation/components/QuotationProductForm.vue
index b48e979bc..15b5a6b37 100644
--- a/src/views/crm/quotation/components/QuotationProductForm.vue
+++ b/src/views/crm/quotation/components/QuotationProductForm.vue
@@ -84,9 +84,9 @@
-
-
-
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -163,10 +193,33 @@
label="创建时间"
align="center"
prop="createTime"
- :formatter="dateFormatter"
width="180px"
- />
-
+ >
+ {{ moment(createTime).format('YYYY-MM-DD')}}
+
+
+
+
+
+ 详情
+
+
+ 进度
+
+
+
+
+
({
nickname: [{ required: true, message: '用户昵称不能为空', trigger: 'blur' }],
password: [{ required: true, message: '用户密码不能为空', trigger: 'blur' }],
postIds: [{ required: true, message: '岗位不能为空', trigger: 'blur' }],
+ deptId: [{ required: true, message: '归属部门不能为空', trigger: 'change' }],
email: [
{
type: 'email',