Browse Source

no message

master
xpz2018 8 months ago
parent
commit
0afb57d7f1
6 changed files with 345 additions and 39 deletions
  1. 10
      src/api/clue/index.ts
  2. 88
      src/enums/customerEnum.ts
  3. 28
      src/views/clue/components/data.ts
  4. 94
      src/views/clue/customer/data.ts
  5. 100
      src/views/clue/customer/index.vue
  6. 64
      src/views/clue/customer/modal.vue

10
src/api/clue/index.ts

@ -71,3 +71,13 @@ export const getSeasList = (params: any) =>
params, params,
}) })
export const getStoreTeam = (params: any) => defHttp.get<any>({ url: '/dating-agency-uec/user/list/dating-store-team', params})
export const getAppointmentList = (params: any) => defHttp.get<any>({ url: '/dating-clue-service/user/list/dating-store-appointment', params})
export const createAppointment = (params: any) => defHttp.post({ url: '/dating-clue-service/user/create/dating-store-appointment/by-telemarketer', params })
export const editAppointment = (params: any) => defHttp.post({ url: '/dating-clue-service/user/edit/dating-store-appointment/by-telemarketer', params })
export const evaluateService = (params: any) => defHttp.post({ url: '/dating-clue-service/user/evaluate/custom-service', params })

88
src/enums/customerEnum.ts

@ -97,4 +97,92 @@ export const marriageList = [
{ label: '2年内', value: 2 }, { label: '2年内', value: 2 },
{ label: '3年内', value: 3 }, { label: '3年内', value: 3 },
{ label: '先恋爱', value: 4 }, { label: '先恋爱', value: 4 },
]
export const storeAppointmentStatus = [
{ label: '待到店', value: 1 },
{ label: '已到店', value: 2 },
{ label: '未到店', value: 3 },
]
export const femaleAgeList = [
{ label: '20-28岁未婚', value: 1 },
{ label: '28-32岁未婚', value: 2 },
{ label: '32-35岁或30岁以下离异不带娃', value: 3 },
{ label: '36-40岁或30岁以上离异带娃', value: 4 },
{ label: '40-45岁或31岁以上离异带娃', value: 5 },
{ label: '45岁以上或40岁以上离异带娃', value: 6 },
]
export const femaleAnnualIncomeList = [
{ label: '10w以下', value: 1 },
{ label: '15w/或净资产50万以上', value: 2 },
{ label: '25w/或净资产200万以上', value: 3 },
{ label: '50w/或净资产500万以上', value: 4 },
{ label: '80w/或净资产1000万以上', value: 5 },
{ label: '100w/资产2000万以上', value: 6 },
]
export const femaleAppearanceList = [
{ label: '六分', value: 1 },
{ label: '七分', value: 2 },
{ label: '八分', value: 3 },
{ label: '九分', value: 4 },
{ label: '五官或身体有轻微缺陷', value: 5 },
{ label: '五官或身体有中度以上缺陷', value: 6 },
]
export const femaleHeightList = [
{ label: '150cm-154cm', value: 1 },
{ label: '155cm-159cm', value: 2 },
{ label: '160cm-167cm', value: 3 },
{ label: '168cm-171cm', value: 4 },
{ label: '172cm-179cm', value: 5 },
{ label: '低于150cm,或高于180cm,或者有肥胖症的,或对生理、身体相关有特殊要求的', value: 6 },
]
export const maleAgeList = [
{ label: '20-28岁未婚', value: 1 },
{ label: '28-35岁未婚', value: 2 },
{ label: '35-40岁或35岁以下离异不带娃', value: 3 },
{ label: '40-45岁或35岁以上离异带娃', value: 4 },
{ label: '45岁-50岁或40岁以上离异带娃', value: 5 },
{ label: '50岁以上或45岁以上离异带娃', value: 6 },
]
export const maleAnnualIncomeList = [
{ label: '10w以下', value: 1 },
{ label: '30w/或净资产200万以上', value: 2 },
{ label: '50w/或净资产500万以上', value: 3 },
{ label: '100w/或净资产1000万以上', value: 4 },
{ label: '500w/或净资产5000万以上', value: 5 },
{ label: '1000w/或资产过亿', value: 6 },
]
export const maleAppearanceList = [
{ label: '六分', value: 1 },
{ label: '七分', value: 2 },
{ label: '八分', value: 3 },
{ label: '九分', value: 4 },
{ label: '五官或身体有轻微缺陷', value: 5 },
{ label: '五官或身体有中度以上缺陷', value: 6 },
]
export const maleEducationList = [
{ label: '高中', value: 1 },
{ label: '大专', value: 2 },
{ label: '本科', value: 3 },
{ label: '211/硕士以上', value: 4 },
{ label: '普通985/博士以上', value: 5 },
{ label: '国内top10或海外名校', value: 6 },
]
export const maleHeightList = [
{ label: '160cm-164cm', value: 1 },
{ label: '165cm-174cm', value: 2 },
{ label: '175cm-179cm', value: 3 },
{ label: '180cm-184cm', value: 4 },
{ label: '185cm-194cm', value: 5 },
{ label: '低于160cm,或高于195cm,或者有肥胖症的,或对生理、身体相关有特殊要求的', value: 6 },
] ]

28
src/views/clue/components/data.ts

@ -278,31 +278,27 @@ export const modalFormSchema: FormSchema[] = [
// }, // },
// }, // },
{ {
field: 'propertyPermitsCode',
field: 'housePurchase',
label: '购房情况', label: '购房情况',
colProps: { span: 8 }, colProps: { span: 8 },
component: 'ApiSelect',
component: 'Select',
componentProps: { componentProps: {
labelField: 'desc',
api: getPropertyPermits,
getPopupContainer: () => document.body,
onChange: (_: any, v: any) => {
basicInfoData.value.propertyPermits = v?.label
},
options: [
{ label: '已购房', value: 1 },
{ label: '未购房', value: 0 },
],
}, },
}, },
{ {
field: 'carPurchaseSituationCode',
field: 'carPurchase',
label: '购车情况', label: '购车情况',
colProps: { span: 8 }, colProps: { span: 8 },
component: 'ApiSelect',
component: 'Select',
componentProps: { componentProps: {
labelField: 'desc',
api: getCarPurchaseSituation,
getPopupContainer: () => document.body,
onChange: (_: any, v: any) => {
basicInfoData.value.carPurchaseSituation = v?.label
},
options: [
{ label: '已购车', value: 1 },
{ label: '未购车', value: 0 },
],
}, },
}, },
{ {

94
src/views/clue/customer/data.ts

@ -2,7 +2,7 @@ import { useAddressData } from '/@/hooks/common'
import { ref } from 'vue' import { ref } from 'vue'
import dayjs, { Dayjs } from 'dayjs' import dayjs, { Dayjs } from 'dayjs'
import { FormSchema } from '/@/components/Form' import { FormSchema } from '/@/components/Form'
import { genderList, followTypeList, followStageList, paymentList, marriageList } from '/@/enums/customerEnum'
import { genderList, followTypeList, followStageList, paymentList, marriageList, storeAppointmentStatus } from '/@/enums/customerEnum'
import { import {
getIncomeList, getIncomeList,
getNationList, getNationList,
@ -18,6 +18,8 @@ import {
getCarPurchaseSituation, getCarPurchaseSituation,
} from '/@/api/essentialData' } from '/@/api/essentialData'
import { getStoreTeam } from '/@/api/clue'
// 基础信息的额外数据 // 基础信息的额外数据
export const basicInfoMoreData = ref<any>({}) export const basicInfoMoreData = ref<any>({})
// 获取地区数据 // 获取地区数据
@ -266,29 +268,25 @@ export const basicSchema: FormSchema[] = [
{ {
field: 'housePurchase', field: 'housePurchase',
label: '购房情况', label: '购房情况',
component: 'ApiSelect',
component: 'Select',
colProps: { span: 8 }, colProps: { span: 8 },
componentProps: { componentProps: {
labelField: 'desc',
api: getPropertyPermits,
getPopupContainer: () => document.body,
onChange: (_: any, v: any) => {
basicInfoMoreData.value.propertyPermits = v?.label
},
options: [
{ label: '已购房', value: 1 },
{ label: '未购房', value: 0 },
],
}, },
}, },
{ {
field: 'carPurchase', field: 'carPurchase',
label: '购车情况', label: '购车情况',
component: 'ApiSelect',
component: 'Select',
colProps: { span: 8 }, colProps: { span: 8 },
componentProps: { componentProps: {
labelField: 'desc',
api: getCarPurchaseSituation,
getPopupContainer: () => document.body,
onChange: (_: any, v: any) => {
basicInfoMoreData.value.carPurchaseSituation = v?.label
},
options: [
{ label: '已购车', value: 1 },
{ label: '未购车', value: 0 },
],
}, },
}, },
{ {
@ -364,4 +362,70 @@ export const modalFormSchema: FormSchema[] = [
}, },
}, },
}, },
]
export const appointmentFormSchema: FormSchema[] = [
{
field: 'datingStoreOrgId',
label: '预约门店',
component: 'ApiSelect',
required: true,
componentProps: {
valueField: 'orgId',
labelField: 'orgName',
api: getStoreTeam,
},
},
{
label: '预约到店时间',
component: 'DatePicker',
field: 'appointmentTime',
required: true,
componentProps: {
showTime: true,
style: { width: '100%' },
},
},
{
field: 'remark',
label: '备注',
required: false,
component: 'InputTextArea',
componentProps: {
autosize: {
minRows: 4,
},
},
},
]
import { BasicColumn } from '/@/components/Table'
export const tableColumns: BasicColumn[] = [
// { width: 70, title: '性别', dataIndex: 'genderCode', customRender: ({ text }) => { return genderList.find((find) => find.value === text)?.label} },
{ title: '门店', dataIndex: 'datingStoreOrgName' },
// { width: 100, title: '渠道来源', dataIndex: 'channelType',
// customRender: ({ text }) => {
// return channelList.find((find) => find.value === text)?.label
// },
// },
{ title: '预约到店时间', dataIndex: 'appointmentTime' },
{ title: '到店状态', dataIndex: 'datingStoreAppointmentStatus',
customRender: ({ text }) => {
return storeAppointmentStatus.find((find) => find.value === text)?.label
},
},
{ title: '销售', dataIndex: 'salesConsultantName' },
{ title: '电邀人', dataIndex: 'telemarketerName' },
// { width: 100, title: '跟进状态', dataIndex: 'followStatus',
// customRender: ({ text }) => {
// return followStatusList.find((find) => find.value === text)?.label
// },
// },
{ title: '电邀团队', dataIndex: 'teleInvitationOrgName' },
// { width: 100, title: '跟进结果', dataIndex: 'validStatus',
// customRender: ({ text }) => {
// return validStatusList.find((find) => find.value === text)?.label
// },
// },
// { width: 160, title: '录入时间', dataIndex: 'creatTime' },
] ]

100
src/views/clue/customer/index.vue

@ -113,7 +113,7 @@
</div> </div>
<div class="flex-row" style="width: 100%;flex: 1;margin-top: 16px;"> <div class="flex-row" style="width: 100%;flex: 1;margin-top: 16px;">
<div style="flex: 1;background: white;padding: 0px 10px 10px 10px;"> <div style="flex: 1;background: white;padding: 0px 10px 10px 10px;">
<Tabs v-model:activeKey="activeKey" :animated="false">
<Tabs v-model:activeKey="activeKey" :animated="false" @change="onTabChange">
<TabPane key="1" tab="客户资料"> <TabPane key="1" tab="客户资料">
<div class="flex-col" style="flex:1;padding-top: 16px;"> <div class="flex-col" style="flex:1;padding-top: 16px;">
<Tabs tab-position="left" v-model:activeKey="activeKey3" :animated="false" @change="onInfoChange"> <Tabs tab-position="left" v-model:activeKey="activeKey3" :animated="false" @change="onInfoChange">
@ -149,7 +149,38 @@
</div> </div>
</TabPane> </TabPane>
<TabPane key="2" tab="邀约进店"> <TabPane key="2" tab="邀约进店">
<Result subTitle="暂无数据"></Result>
<div style="height: 100%;width: 100%;position: relative;">
<!-- <Button shape="circle" type="primary" ghost style="position: absolute;right: 24rpx;bottom: 24rpx;">
<template #icon><Icon icon="ant-design:plus-outlined" size="16px" style="color: #0960bd;"/></template>
</Button> -->
<!-- <Table bordered :pagination="false" :columns="tableColumns" :dataSource="appointmentList">
</Table> -->
<BasicTable @register="registerTable">
<template #action="{ record }">
<TableAction
:actions="[
{
label: '取消',
color: 'error',
// onClick: handleCancel.bind(null, record['id']),
},
{
label: '编辑',
onClick: handleAppointment.bind(null, record),
},
{
label: '结算',
color: 'error',
ifShow: record['status'] === 5,
// onClick: handleSettle.bind(null, record['id']),
}
]"
/>
</template>
</BasicTable>
<!-- <Result subTitle="暂无数据"></Result> -->
</div>
</TabPane> </TabPane>
<TabPane key="3" tab="合同"> <TabPane key="3" tab="合同">
<Result subTitle="暂无数据"></Result> <Result subTitle="暂无数据"></Result>
@ -157,12 +188,20 @@
<TabPane key="4" tab="约见记录"> <TabPane key="4" tab="约见记录">
<Result subTitle="暂无数据"></Result> <Result subTitle="暂无数据"></Result>
</TabPane> </TabPane>
<template v-if="activeKey == '1'" #tabBarExtraContent>
<Button type="link" @click="handleSubmit"><template #icon><Icon icon="ant-design:edit-twotone" size="16px" style="margin-right: -4px;"/></template>保存资料</Button>
<template #tabBarExtraContent>
<Button type="link" @click="handleSubmit" v-if="activeKey == '1'">
<template #icon><Icon icon="ant-design:edit-twotone" size="16px" style="margin-right: -4px;"/></template>保存资料
</Button>
<Button type="link" @click="handleAppointment({datingClueId: details.id})" v-else-if="activeKey == '2'">
<template #icon>
<div style="display: inline;"><Icon icon="ant-design:plus-outlined" size="16px" style="margin-right: 2px;"/></div>
</template>
<span>邀约进店</span>
</Button>
</template> </template>
</Tabs> </Tabs>
</div> </div>
<div style="width: 480px;background: white;margin-left: 16px;padding: 0px 10px 10px 10px;" v-if="details.allocationStatus !== 1">
<div style="width: 400px;background: white;margin-left: 16px;padding: 0px 10px 10px 10px;" v-if="details.allocationStatus !== 1">
<Tabs v-model:activeKey="activeKey2" :animated="false" @change="onReportChange"> <Tabs v-model:activeKey="activeKey2" :animated="false" @change="onReportChange">
<TabPane key="1" tab="跟进小计"> <TabPane key="1" tab="跟进小计">
<div class="flex-col-center-start" style="flex:1;padding-top: 16px;"> <div class="flex-col-center-start" style="flex:1;padding-top: 16px;">
@ -197,22 +236,26 @@
</Tabs> </Tabs>
</div> </div>
</div> </div>
<AppointmentModal @register="registerModal" @success="handleSuccess" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { onMounted, ref, nextTick } from 'vue' import { onMounted, ref, nextTick } from 'vue'
import { Tabs, Input, Popconfirm, Button, TabPane, Tag, Timeline, TimelineItem, Result, Spin, InputNumber } from 'ant-design-vue'
import { Tabs, Input, Popconfirm, Button, TabPane, Tag, Timeline, TimelineItem, Result, Spin, InputNumber, Table } from 'ant-design-vue'
import { Icon } from '/@/components/Icon' import { Icon } from '/@/components/Icon'
import { useMessage } from '/@/hooks/web/useMessage' import { useMessage } from '/@/hooks/web/useMessage'
import { CropperAvatar } from '/@/components/Cropper'; import { CropperAvatar } from '/@/components/Cropper';
import BasicForm from '/@/components/Form/src/BasicForm.vue' import BasicForm from '/@/components/Form/src/BasicForm.vue'
import { BasicTable, useTable, TableAction } from '/@/components/Table'
import { useForm } from '/@/components/Form' import { useForm } from '/@/components/Form'
import { formatToDateTime } from '/@/utils/dateUtil' import { formatToDateTime } from '/@/utils/dateUtil'
import { basicSchema, modalFormSchema } from './data'
import { basicSchema, modalFormSchema, tableColumns } from './data'
import { useModal } from '/@/components/Modal'
import AppointmentModal from './modal.vue'
import { demandMarriageMoreData, demandMarriageSchema } from '/@/views/clue/components/data' import { demandMarriageMoreData, demandMarriageSchema } from '/@/views/clue/components/data'
import { getClueInfo, editClueRecord, recordClueing, getClueRecord } from '/@/api/clue'
import { getClueInfo, editClueRecord, recordClueing, getClueRecord, getAppointmentList } from '/@/api/clue'
import { genderList, channelList, clueStatusList, followTypeList, followStageList } from '/@/enums/customerEnum' import { genderList, channelList, clueStatusList, followTypeList, followStageList } from '/@/enums/customerEnum'
const details = ref<any>() const details = ref<any>()
@ -248,6 +291,17 @@
await setFieldsValue3({ ...details.value.datingClueDemand, domicilePlace, address }) await setFieldsValue3({ ...details.value.datingClueDemand, domicilePlace, address })
} }
} }
function onTabChange(){
if(activeKey.value == '2'){
reloadTable()
}
}
async function reloadTable(){
const dataSource= await getAppointmentList({datingClueId: details.value.id})
setTableData(dataSource)
}
const activeKey = ref<string>('1') const activeKey = ref<string>('1')
const activeKey2 = ref<string>('1') const activeKey2 = ref<string>('1')
@ -298,6 +352,7 @@
baseColProps: { span: 22 }, baseColProps: { span: 22 },
showActionButtonGroup: false, showActionButtonGroup: false,
}) })
async function handleSubmit() { async function handleSubmit() {
await validate1() await validate1()
const baseInfo: any = getFieldsValue1() const baseInfo: any = getFieldsValue1()
@ -351,6 +406,35 @@
spinning.value = false spinning.value = false
} }
} }
// const appointmentList = ref<any[]>([]);
const [registerTable, { setTableData }] = useTable({
bordered: true,
immediate: false,
canResize: false,
pagination: false,
useSearchForm: false,
showIndexColumn: false,
showTableSetting: false,
columns: tableColumns,
actionColumn: {
width: 120,
title: '操作',
fixed: 'right',
dataIndex: 'action',
slots: { customRender: 'action' },
},
})
const [registerModal, { openModal, closeModal }] = useModal()
function handleAppointment(record) {
openModal(true, {record})
}
//
function handleSuccess() {
closeModal()
reloadTable()
initFetch()
}
</script> </script>
<style scoped lang="less"> <style scoped lang="less">
::v-deep .ant-input-number { ::v-deep .ant-input-number {

64
src/views/clue/customer/modal.vue

@ -0,0 +1,64 @@
<template>
<BasicModal v-bind="$attrs" @ok="handleOk" @register="registerModal">
<BasicForm @register="registerForm" />
</BasicModal>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { appointmentFormSchema } from './data'
import { useMessage } from '/@/hooks/web/useMessage'
import { BasicForm, useForm } from '/@/components/Form'
import { BasicModal, useModalInner } from '/@/components/Modal'
import { createAppointment, editAppointment } from '/@/api/clue'
import { formatToDateTime } from '/@/utils/dateUtil'
const [registerForm, { resetFields, setFieldsValue, validate }] = useForm({
labelWidth: 100,
schemas: appointmentFormSchema,
baseColProps: { span: 22 },
showActionButtonGroup: false,
})
const id = ref<string>('')
const datingClueId = ref<string>('')
const ifUpdate = ref<boolean>(false)
const [registerModal, { setModalProps }] = useModalInner(async (data) => {
const { record } = data
await resetFields()
id.value = record?.id
datingClueId.value = record?.datingClueId
ifUpdate.value = !!id.value
setModalProps({
minHeight: 50,
title: `预约到店`,
confirmLoading: false,
})
if (!!ifUpdate.value) {
await setFieldsValue({ ...record })
}
})
const { createMessage } = useMessage()
const emits = defineEmits(['success'])
async function handleOk() {
try {
const values = await validate()
setModalProps({ confirmLoading: true })
const { appointmentTime } = values
values.appointmentTime = formatToDateTime(appointmentTime)
if(id.value){
values.id = id.value
await editAppointment(values)
createMessage.success(`编辑成功!`)
} else {
values.datingClueId = datingClueId.value
await createAppointment(values)
createMessage.success(`新增成功!`)
}
emits('success')
} finally {
setModalProps({ confirmLoading: false })
}
}
</script>
Loading…
Cancel
Save