diff --git a/src/api/clue/index.ts b/src/api/clue/index.ts index d318ef1..9e64080 100644 --- a/src/api/clue/index.ts +++ b/src/api/clue/index.ts @@ -87,4 +87,52 @@ export const getContractList = (params: any) => defHttp.get>({ url: '/dating-agency-mall/user/page/customized-service-contract/by/dating-store-team', params, -}) \ No newline at end of file +}) + +export const getTaskList = (params: any) => + defHttp.get>({ + url: '/dating-clue-service/user/page/dating-store-customer-task/by/dating-store', + params, +}) + +export const getClientList = (params: any) => + defHttp.get>({ + url: '/dating-clue-service/user/page/dating-store-customer/by/dating-store', + params, +}) + +export const allocationTask = (params: any) => defHttp.post({ url: '/dating-clue-service/user/allocate/dating-store-customer/service-matchmaker', params }) + +export const reportTask = (params: any) => defHttp.post({ url: '/dating-clue-service/user/delivery/dating-store-customer-task-item', params }) + +export const finishTask = (params: any) => defHttp.post({ url: '/dating-clue-service/user/operate/dating-store-customer-task', params }) + +export const getTaskItems = (params: any) => defHttp.get({ url: '/dating-clue-service/user/list/dating-store-customer-task-item', params}) + +export const signCustomer = (params: any) => defHttp.post({ url: '/dating-clue-service/user/sign/dating-store-customer', params }) + +export const resignCustomer = (params: any) => defHttp.post({ url: '/dating-clue-service/user/renew/dating-store-customer', params }) + +export const getStoreAppointmentList = (params: any) => + defHttp.get>({ + url: '/dating-clue-service/user/page/dating-store-appointment/by/dating-store-team', + params, +}) + +export const allocationSaler = (params: any) => defHttp.post({ url: '/dating-clue-service/user/allocate/dating-store-appointment/by-dating-store', params }) + +export const appointmentCustomer = (params: any) => defHttp.post({ url: '/dating-clue-service/user/change/dating-store-appointment-time/by-dating-store', params }) + +export const remarkCustomer = (params: any) => defHttp.post({ url: '/dating-clue-service/user/create/dating-store-appointment-record', params }) + +export const getContractInfo = (params: any) => defHttp.get({ url: '/dating-agency-mall/user/get/customized-service-contract/by/dating-store-customer', params}) + +export const getPaymentInfo = (params: any) => defHttp.get({ url: '/dating-agency-mall/user/get/payment-order/by/dating-store-customer', params}) + +export const getCustomerInfo = (params: any) => defHttp.get({ url: '/dating-clue-service/user/get/dating-store-customer/detail', params}) + +export const editCustomerInfo = (params: any) => defHttp.post({ url: '/dating-clue-service/user/edit/dating-store-customer', params }) + +export const getDemandInfo = (params: any) => defHttp.get({ url: '/dating-clue-service/user/get/dating-store-customer-demand/detail', params}) + +export const editDemandInfo = (params: any) => defHttp.post({ url: '/dating-clue-service/user/edit/dating-store-customer-demand', params }) diff --git a/src/enums/customerEnum.ts b/src/enums/customerEnum.ts index fa6c91d..7e771cb 100644 --- a/src/enums/customerEnum.ts +++ b/src/enums/customerEnum.ts @@ -105,6 +105,15 @@ export const storeAppointmentStatus = [ { label: '未到店', value: 3 }, ] +export const appointmentStatusList = [ + { label: '待到店', value: 1, color: 'gray' }, + { label: '已到店', value: 2, color: 'green' }, + { label: '未到店', value: 3, color: 'gray' }, + { label: '复邀', value: 4, color: 'green' }, + { label: '已签约', value: 5, color: 'red' }, + { label: '未签约', value: 6, color: 'gray' }, +] + export const femaleAgeList = [ { label: '20-28岁未婚', value: 1 }, @@ -185,4 +194,17 @@ export const maleHeightList = [ { label: '180cm-184cm', value: 4 }, { label: '185cm-194cm', value: 5 }, { label: '低于160cm,或高于195cm,或者有肥胖症的,或对生理、身体相关有特殊要求的', value: 6 }, +] + +export const contractStatusList = [ + { label: '未开始', value: 1 }, + { label: '生效中', value: 2 }, + { label: '已结束', value: 3 }, + { label: '已废弃', value: 4 }, +] + +export const paymentInfoList = [ + { label: '微信小程序付款', value: 1 }, + { label: '微信小程序H5', value: 2 }, + { label: '线下付款', value: 3 }, ] \ No newline at end of file diff --git a/src/locales/lang/zh-CN/routes/invite.ts b/src/locales/lang/zh-CN/routes/invite.ts index 0c54170..63fab03 100644 --- a/src/locales/lang/zh-CN/routes/invite.ts +++ b/src/locales/lang/zh-CN/routes/invite.ts @@ -5,5 +5,8 @@ export default { myList: '我的线索', seasList: '公海线索', market: '运营管理', - contract: '合同列表' + appointment: '预约列表', + contract: '合同列表', + task: '任务列表', + client: '客户列表' } diff --git a/src/router/menu.ts b/src/router/menu.ts index b447268..27ad6a2 100644 --- a/src/router/menu.ts +++ b/src/router/menu.ts @@ -130,7 +130,7 @@ const marketMenu: Menu = { path: '/market', name: 'Market', component: 'LAYOUT', - redirect: '/market/contract', + redirect: '/market/appointment', meta: { orderNo: 90005, hideChildrenInMenu: false, @@ -138,6 +138,22 @@ const marketMenu: Menu = { title: 'routes.invite.market', }, children: [ + { + path: 'appointment', + name: 'Appointment', + component: '/market/appointment/index.vue', + meta: { + title: 'routes.invite.appointment', + }, + }, + { + path: 'task', + name: 'Task', + component: '/market/task/index.vue', + meta: { + title: 'routes.invite.task', + }, + }, { path: 'contract', name: 'Contract', @@ -146,6 +162,14 @@ const marketMenu: Menu = { title: 'routes.invite.contract', }, }, + { + path: 'client', + name: 'Client', + component: '/market/client/index.vue', + meta: { + title: 'routes.invite.client', + }, + }, ], } diff --git a/src/views/clue/customer/modal.vue b/src/views/clue/customer/modal.vue index 64c889e..5f3c9c1 100644 --- a/src/views/clue/customer/modal.vue +++ b/src/views/clue/customer/modal.vue @@ -54,7 +54,7 @@ } else { values.datingClueId = datingClueId.value await createAppointment(values) - createMessage.success(`新增成功!`) + createMessage.success(`邀约成功!`) } emits('success') } finally { diff --git a/src/views/invite/myList/data.ts b/src/views/invite/myList/data.ts index 726b17f..9ff4a2c 100644 --- a/src/views/invite/myList/data.ts +++ b/src/views/invite/myList/data.ts @@ -12,6 +12,8 @@ export const tableColumns: BasicColumn[] = [ // }, // }, { title: '分配信息', dataIndex: 'allocateInfo', slots: { customRender: 'allocateInfo' } }, + + { title: '跟进进度', dataIndex: 'datingStoreAppointmentStatus', slots: { customRender: 'datingStoreAppointmentStatus' } }, // { width: 80, title: '状态', dataIndex: 'validStatus', // customRender: ({ text }) => { // return clueStatusList.find((find) => find.value === text)?.label diff --git a/src/views/invite/myList/index.vue b/src/views/invite/myList/index.vue index 616b840..ad6d902 100644 --- a/src/views/invite/myList/index.vue +++ b/src/views/invite/myList/index.vue @@ -21,14 +21,20 @@ + + + @@ -43,16 +49,17 @@ diff --git a/src/views/market/appointment/data.ts b/src/views/market/appointment/data.ts new file mode 100644 index 0000000..4c9ce46 --- /dev/null +++ b/src/views/market/appointment/data.ts @@ -0,0 +1,77 @@ +import { BasicColumn, FormSchema } from '/@/components/Table' +import { genderList, incomeList, maritalList, appointmentStatusList } from '/@/enums/customerEnum' + +export const tableColumns: BasicColumn[] = [ + { width: 120, title: '用户名称', dataIndex: 'nickName' }, + { width: 90, title: '用户性别', dataIndex: 'genderCode', customRender: ({ text }) => { return genderList.find((find) => find.value === text)?.label} }, + { width: 120, title: '手机号码', dataIndex: 'phone' }, + { width: 80, title: '年龄', dataIndex: 'age' }, + { width: 90, title: '婚姻状态', dataIndex: 'maritalStatusCode', + customRender: ({ text }) => { + return maritalList.find((find) => find.value === text)?.label + }, + }, + { width: 120, title: '月收入', dataIndex: 'incomeCode', + customRender: ({ text }) => { + return incomeList.find((find) => find.value === text)?.label + }, + }, + { width: 120, title: '面谈销售', dataIndex: 'salesConsultantName' }, + { width: 160, title: '预约时间', dataIndex: 'appointmentTime' }, + { title: '跟进进度', dataIndex: 'datingStoreAppointmentStatus', slots: { customRender: 'datingStoreAppointmentStatus' } }, +] + +export const tableFormSchema: FormSchema[] = [ + { + field: 'phone', + label: ' 用户电话号码', + component: 'Input', + colProps: { span: 6 }, + }, + { + field: 'salesConsultantName', + label: '面谈销售', + component: 'Input', + colProps: { span: 6 }, + }, + { + field: 'createTime', + label: '预约时间', + component: 'RangePicker', + colProps: { span: 6 }, + }, +] + +export const appointmentFormSchema: FormSchema[] = [ + { + label: '跟进阶段', + component: 'Select', + field: 'datingStoreAppointmentFollowStage', + required: true, + componentProps: { + options: appointmentStatusList, + style: { width: '100%' }, + }, + }, + { + label: '约见时间', + component: 'DatePicker', + field: 'appointmentTime', + required: true, + componentProps: { + showTime: true, + style: { width: '100%' }, + }, + }, + { + field: 'remark', + label: '备注', + required: false, + component: 'InputTextArea', + componentProps: { + autosize: { + minRows: 4, + }, + }, + }, +] diff --git a/src/views/market/appointment/index.vue b/src/views/market/appointment/index.vue new file mode 100644 index 0000000..2fef0d4 --- /dev/null +++ b/src/views/market/appointment/index.vue @@ -0,0 +1,163 @@ + + + + + diff --git a/src/views/market/appointment/modal.vue b/src/views/market/appointment/modal.vue new file mode 100644 index 0000000..d42315b --- /dev/null +++ b/src/views/market/appointment/modal.vue @@ -0,0 +1,68 @@ + + + \ No newline at end of file diff --git a/src/views/market/client/contract.vue b/src/views/market/client/contract.vue new file mode 100644 index 0000000..169ac1e --- /dev/null +++ b/src/views/market/client/contract.vue @@ -0,0 +1,90 @@ + + + \ No newline at end of file diff --git a/src/views/market/client/data.ts b/src/views/market/client/data.ts new file mode 100644 index 0000000..75ca74d --- /dev/null +++ b/src/views/market/client/data.ts @@ -0,0 +1,376 @@ +import { BasicColumn, FormSchema } from '/@/components/Table' + +export const contactStatusList = [ + { label: '进行中', value: 1 }, + { label: '生效中', value: 2 }, + { label: '已终止', value: 3 }, +] + +export const tableColumns: BasicColumn[] = [ + { title: '用户信息', dataIndex: 'userInfo', slots: { customRender: 'userInfo' } }, + { width: 120, title: '手机号码', dataIndex: 'phone' }, + { width: 240, title: '服务任务', dataIndex: 'inProgressTaskId', slots: { customRender: 'inProgressTaskId' } }, + { width: 120, title: '服务红娘', dataIndex: 'serviceMatchmakerName' }, + { width: 160, title: '面谈销售', dataIndex: 'salesConsultantName' }, + { width: 160, title: '创建时间', dataIndex: 'createTime' }, +] + +export const tableFormSchema: FormSchema[] = [ + { + field: 'name', + label: '客户姓名', + component: 'Input', + colProps: { span: 6 }, + }, + { + field: 'phone', + label: '电话', + component: 'Input', + colProps: { span: 6 }, + }, + { + field: 'salesConsultantName', + label: '面谈销售', + component: 'Input', + colProps: { span: 6 }, + }, + { + field: 'serviceMatchmakerName', + label: '服务红娘', + component: 'Input', + colProps: { span: 6 }, + }, +] + + +import { ref } from 'vue' +import dayjs, { Dayjs } from 'dayjs' +import { genderList, incomeList } from '/@/enums/customerEnum' +import { useAddressData } from '/@/hooks/common' +import { + getNationList, + getEducationList, + getOccupationList, + getPropertyPermits, + getMaritalStatusList, + getConstellationList, + getCarPurchaseSituation, +} from '/@/api/essentialData' + +// 基础信息的额外数据 +export const basicInfoData = ref({}) +// 获取地区数据 +const { addressList, domicilePlaceList } = useAddressData() + +// 获取职业列表 +export const occupationList = ref([]) +getOccupationList().then((res) => { + handleOccupationList(res) + occupationList.value = res || [] +}) +function handleOccupationList(data: any, ifFirst = true) { + data?.forEach?.((item: any) => { + const { industry, industryCode, occupation, occupationCode, occupationList } = item + item.label = ifFirst ? industry : occupation + item.value = ifFirst ? industryCode : occupationCode + if (occupationList?.length) { + item.children = occupationList + handleOccupationList(occupationList, false) + } + }) +} + +export const addressName = ref([]) +// 基本信息 +export const modalFormSchema: FormSchema[] = [ + { field: 'name', label: '客户姓名', component: 'Input', required: true, colProps: { span: 12 },}, + { + field: 'genderCode', + label: '性别', + colProps: { span: 12 }, + component: 'Select', + required: true, + componentProps: { + options: genderList, + }, + }, + { field: 'phone', label: '电话号码', component: 'Input', required: true, colProps: { span: 12 },}, + { + label: '出生日期', + component: 'DatePicker', + field: 'birthDate', + required: true, + colProps: { span: 12 }, + componentProps: { + style: { width: '100%' }, + }, + }, + { + field: 'maritalStatusCode', + label: '婚姻状况', + colProps: { span: 12 }, + component: 'ApiSelect', + componentProps: { + labelField: 'desc', + api: getMaritalStatusList, + getPopupContainer: () => document.body, + onChange: (_: any, v: any) => { + basicInfoData.value.maritalStatusName = v?.label + }, + }, + }, + { + field: 'educationCode', + label: '学历', + colProps: { span: 12 }, + component: 'ApiSelect', + componentProps: { + labelField: 'desc', + api: getEducationList, + getPopupContainer: () => document.body, + onChange: (_: any, v: any) => { + basicInfoData.value.education = v?.label + }, + }, + }, + { field: 'height', label: '身高(cm)', component: 'InputNumber', colProps: { span: 12 }, }, + { field: 'weight', label: '体重(kg)', component: 'InputNumber', colProps: { span: 12 }, }, + { field: 'annualIncome', label: '年收入(万元)', component: 'InputNumber', colProps: { span: 12 }, }, + { field: 'netAsset', label: '净资产(万元)', component: 'InputNumber', colProps: { span: 12 }, }, + { field: 'graduateSchool', label: '毕业高校', component: 'InputNumber', colProps: { span: 12 }, }, + { + field: 'nationCode', + label: '民族', + colProps: { span: 12 }, + component: 'ApiSelect', + componentProps: { + labelField: 'cn', + valueField: 'id', + api: getNationList, + getPopupContainer: () => document.body, + onChange: (_: any, v: any) => { + demandMarriageMoreData.value.nation = v?.label + }, + }, + }, + { + field: 'homeAddress', + label: '现居住地', + colProps: { span: 12 }, + component: 'Cascader', + componentProps: { + options: addressList, + onChange: (_: any, v: any) => { + basicInfoData.value.homeProvinceName = v?.[0]?.label + basicInfoData.value.homeCityName = v?.[1]?.label + basicInfoData.value.homeDistrictName = v?.[2]?.label + }, + }, + }, + { field: 'homeDetailAddress', label: '详细地址', component: 'Input', colProps: { span: 12 }, }, + { + label: '职业', + field: 'occupationList', + colProps: { span: 12 }, + component: 'Cascader', + componentProps: { + options: occupationList, + getPopupContainer: () => document.body, + onChange: (_: any, v: any) => { + const industry = v?.[0] || {} + const occupation = v?.[1] || {} + basicInfoData.value.industry = industry.label + basicInfoData.value.industryCode = industry.value + basicInfoData.value.occupation = occupation.label + basicInfoData.value.occupationCode = occupation.value + }, + }, + }, + { field: 'childrenNum', label: '孩子数量', component: 'InputNumber', colProps: { span: 12 }, }, + { + field: 'housePurchase', + label: '购房情况', + colProps: { span: 12 }, + component: 'Select', + componentProps: { + options: [ + { label: '已购房', value: 1 }, + { label: '未购房', value: 0 }, + ], + }, + }, + { + field: 'carPurchase', + label: '购车情况', + colProps: { span: 12 }, + component: 'Select', + componentProps: { + options: [ + { label: '已购车', value: 1 }, + { label: '未购车', value: 0 }, + ], + }, + }, + { + field: 'profilePhoto', + component: 'Upload', + label: '资料头像', + colProps: { span: 8 }, + slot: 'profilePhoto', + }, + { + field: 'remark', + label: '个人描述', + component: 'InputTextArea', + colProps: { span: 16 }, + componentProps: ({ formModel }) => { + return { + autoSize: { + minRows: 4, + }, + disabled: formModel?.describeAudit, + } + }, + }, +] + +// 择偶标准的额外数据 +export const demandMarriageMoreData = ref({}) +// 择偶标准 +export const demandMarriageSchema: FormSchema[] = [ + { + field: 'educationCode', + label: '学历要求', + colProps: { span: 12 }, + component: 'ApiSelect', + componentProps: { + labelField: 'desc', + api: getEducationList, + getPopupContainer: () => document.body, + onChange: (_: any, v: any) => { + demandMarriageMoreData.value.education = v?.label + }, + }, + }, + { + field: 'minimumAnnualIncome', + label: '年收入(万元)', + colProps: { span: 12 }, + component: 'InputNumber', + slot: 'income', + }, + { + field: 'maximumAnnualIncome', + label: '年收入', + colProps: { span: 12 }, + component: 'InputNumber', + ifShow: false, + }, + { + field: 'cityList', + label: '所在城市', + colProps: { span: 24 }, + component: 'Cascader', + componentProps: { + options: domicilePlaceList, + onChange: (_: any, v: any) => { + demandMarriageMoreData.value.provinceName = v?.[0]?.label + demandMarriageMoreData.value.cityName = v?.[1]?.label + }, + }, + }, + { + field: 'minAge', + label: '年龄范围', + colProps: { span: 12 }, + component: 'InputNumber', + slot: 'age', + }, + { + field: 'maxAge', + label: '年龄', + colProps: { span: 12 }, + component: 'InputNumber', + ifShow: false, + }, + { + field: 'minHeight', + label: '身高(cm)', + colProps: { span: 12 }, + component: 'InputNumber', + slot: 'height', + }, + { + field: 'maxHeight', + label: '身高', + colProps: { span: 12 }, + component: 'InputNumber', + ifShow: false, + }, + { + field: 'minWeight', + label: '体重(kg)', + colProps: { span: 12 }, + component: 'InputNumber', + slot: 'weight', + }, + { + field: 'maxWeight', + label: '体重', + colProps: { span: 12 }, + component: 'InputNumber', + ifShow: false, + }, + + { + field: 'isDivorceAccepted', + label: '是否接受离异', + colProps: { span: 12 }, + component: 'Select', + componentProps: { + options: [ + { label: '不接受', value: 0 }, + { label: '接受', value: 1 }, + ], + }, + }, + { + field: 'isChildAccepted', + label: '是否跟老人一起生活', + colProps: { span: 12 }, + component: 'Select', + componentProps: { + options: [ + { label: '不接受', value: 0 }, + { label: '接受', value: 1 }, + ], + }, + }, + { + field: 'isLivingWithElderly', + label: '是否跟老人一起生活', + colProps: { span: 12 }, + component: 'Select', + componentProps: { + options: [ + { label: '跟男方', value: 1 }, + { label: '跟女方', value: 2 }, + { label: '不跟老人居住', value: 3 }, + ], + }, + }, + { + field: 'otherRequirements', + label: '其他需求', + component: 'InputTextArea', + colProps: { span: 24 }, + componentProps: ({ formModel }) => { + return { + autoSize: { + minRows: 4, + }, + disabled: formModel?.describeAudit, + } + }, + }, +] \ No newline at end of file diff --git a/src/views/market/client/index.vue b/src/views/market/client/index.vue new file mode 100644 index 0000000..c7243c5 --- /dev/null +++ b/src/views/market/client/index.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/views/market/client/modal.vue b/src/views/market/client/modal.vue new file mode 100644 index 0000000..4c0e4be --- /dev/null +++ b/src/views/market/client/modal.vue @@ -0,0 +1,203 @@ + + + + + diff --git a/src/views/market/components/data.ts b/src/views/market/components/data.ts new file mode 100644 index 0000000..4b54da9 --- /dev/null +++ b/src/views/market/components/data.ts @@ -0,0 +1,74 @@ +import { FormSchema } from '/@/components/Form' +import { genderList } from '/@/enums/customerEnum' + +export const modalFormSchema: FormSchema[] = [ + { + field: 'phone', + label: '客户电话', + colProps: { span: 12 }, + component: 'Input', + required: true, + }, + { + field: 'genderCode', + label: '客户性别', + required: true, + component: 'Select', + colProps: { span: 12 }, + componentProps: { + options: genderList, + }, + }, + { + field: 'name', + label: '客户姓名', + component: 'Input', + required: true, + colProps: { span: 12 }, + }, + { + field: 'identityCard', + label: '身份证号', + component: 'Input', + required: true, + colProps: { span: 12 }, + }, + { + field: 'amount', + label: '服务金额', + component: 'Input', + required: true, + colProps: { span: 12 }, + }, + { + field: 'numberOfServices', + label: '服务次数', + component: 'Input', + required: true, + colProps: { span: 12 }, + }, + { + label: '结束时间', + component: 'DatePicker', + field: 'serviceEndDate', + required: true, + colProps: { span: 12 }, + componentProps: { + style: { width: '100%' }, + }, + }, + { + label: '合同凭证', + required: true, + field: 'imageList1', + component: 'Upload', + slot: 'imageList1', + }, + { + label: '付款凭证', + required: true, + field: 'imageList2', + component: 'Upload', + slot: 'imageList2', + }, +] \ No newline at end of file diff --git a/src/views/market/components/modal.vue b/src/views/market/components/modal.vue new file mode 100644 index 0000000..3222700 --- /dev/null +++ b/src/views/market/components/modal.vue @@ -0,0 +1,95 @@ + + + \ No newline at end of file diff --git a/src/views/market/contract/index.vue b/src/views/market/contract/index.vue index 69de543..b2f1f74 100644 --- a/src/views/market/contract/index.vue +++ b/src/views/market/contract/index.vue @@ -38,14 +38,11 @@ + + diff --git a/src/views/market/task/modal.vue b/src/views/market/task/modal.vue new file mode 100644 index 0000000..3706f78 --- /dev/null +++ b/src/views/market/task/modal.vue @@ -0,0 +1,89 @@ + + + \ No newline at end of file