新增直达信息管理-初始版

master
飘泊客 11 months ago
parent e9a1c85e7a
commit f5e952279b

@ -246,7 +246,7 @@ export default defineComponent({
localSelectedKeys.value = route.matched.filter(x => x.path !== '/').map(x => x.path)
})
console.log(props.menuData)
// console.log(props.menuData)
// 选中菜单的时候进行路由切换
const router = useRouter()

@ -380,7 +380,6 @@ const ProTable = defineComponent({
const fetchData = () => {
if (!props.request) return undefined
return async (pageParams?: Record<string, any>) => {
console.log(pageParams, 'pageParams')
const actionParams = {
...(pageParams || {}),
...formSearch,

@ -0,0 +1,17 @@
import httpClient from '@/utils/axios'
import type { ApiResult } from '@/api/types'
import type { directPageParam, distributeData } from './types'
export function pageQueryPage(pageParams: directPageParam) {
return httpClient.get<ApiResult>('/directClue/page', {
params: pageParams
})
}
export function upDistribute(data: distributeData[]) {
return httpClient.post<ApiResult>('/directClue/distribute', data)
}
export function getfFindDirectSalesman() {
return httpClient.get<ApiResult>('/system/user/findDirectSalesman', {})
}

@ -0,0 +1,32 @@
import type { PageParam } from '@/api/types'
import type { Dayjs } from 'dayjs'
export type directParam = {
customName?: string
originType?: number | null
attribute?: string
distributeDate?: [Dayjs, Dayjs]
}
interface otherObj {
[name: string]: any
}
export type directDTO = {
directClueId?: number
batchNo?: string
nid?: string | undefined
customName?: string
originType: number
effectiveStatus: number
otherClueObj: otherObj
clueLabelName?: string
distributeType: number
distributeDate?: Dayjs | null
distributeUserId?: number | null
userId?: number[]
}
export type directPageParam = directParam & PageParam
export type distributeData = {
clueId: number
userId: number
userName: string
}

@ -145,7 +145,6 @@ const tableRequest: TableRequest = (params, sorter, filter) => {
res.data.records.forEach(item => {
item[props.dataKey] = String(item[props.dataKey])
})
console.log(res)
return Promise.resolve(res)
})
}

@ -134,7 +134,6 @@ const menuState = reactive<{
watchEffect(() => {
const matchedRoutes = route.matched
console.log(matchedRoutes, 'matchedRoutes')
menuState.selectedKeys = matchedRoutes.filter(x => x.path !== '/').map(x => x.path)
menuState.matchMenuKeys = matchedRoutes.filter(x => x.path !== '/').map(x => x.path)
})

@ -8,6 +8,9 @@
display: flex;
align-items: center;
}
.flex-between {
justify-content: space-between;
}
// 滚动条
.sim-cont{
max-height: 100%;
@ -30,3 +33,9 @@
.flex-1 {
flex: 1;
}
.c-red {
color: red;
}
.text-center {
text-align: center;
}

@ -0,0 +1,168 @@
<template>
<!-- 头部 -->
<a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="geopoliticalCustomers-title">线索看板</div>
</a-card>
<!-- 搜索 -->
<clue-search :loading="tableRef?.loading" @search="searchTable" />
<!-- 工具栏 -->
<!-- <a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="operationButtonArea">
<a-button type="primary" @click="addShop"></a-button>
</div>
</a-card> -->
<!-- 底部表格 -->
<pro-table
ref="tableRef"
row-key="customId"
:request="tableRequest"
:columns="columns"
:scroll="{ x: 1100 }"
:options="{ density: false }"
class="protable"
:pagination="{ showQuickJumper: true }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'batchNo'">
<a>{{ record.id }}</a>
</template>
<template v-else-if="column.key === 'operate'">
<operation-group>
<a @click="selectReservation(record)"></a>
</operation-group>
</template>
</template>
</pro-table>
<!-- 预约详情 -->
<clue-modal ref="clueModalRef" @submit-success="reloadTable" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
// import { message } from 'ant-design-vue'
import { doRequest } from '@/utils/axios/request'
//
import ProTable from '#/table'
import type { ProTableInstanceExpose, TableRequest, ProColumns } from '#/table'
import { mergePageParam } from '@/utils/page-utils'
import { FormAction } from '@/hooks/form'
import clueModal from './clueModal.vue'
import clueSearch from './clueSearch.vue'
import { pageQueryPage } from '@/api/directResources'
import type { directDTO, directPageParam } from '@/api/directResources/types'
defineOptions({ name: 'ClueIndex' })
//
//
const tableRef = ref<ProTableInstanceExpose>()
// add ref
const clueModalRef = ref<InstanceType<typeof clueModal>>()
// const reservationModalRef = ref<InstanceType<typeof reservationModal>>()
//
let searchParams: directPageParam = {}
const columns = ref<any[]>([
{
title: '编号',
width: 80,
dataIndex: 'batchNo'
},
{
title: '客户名称',
dataIndex: 'customName'
},
{
title: '手机号码',
dataIndex: 'nid'
},
{
title: '分发日期',
dataIndex: 'distributeDate',
width: 150,
align: 'center',
customRender: function ({ record }: any) {
if (record.distributeDate) {
return record.distributeDate
} else if (record.distributeDate == null) {
return '--'
}
}
},
{
title: '跟进员',
dataIndex: 'userNameList',
customRender: ({ record }: any) => {
if (record.userNameList.length > 0) {
return h('div', record.userNameList.join(','))
} else {
return h('div', '')
}
}
},
{
title: '来源',
dataIndex: 'originType',
customRender: ({ record }: any) => {
if (record.originType === 0) {
return h('div', '巨量')
}
}
},
{
title: '地址',
dataIndex: 'address',
customRender: function ({ record }: any) {
return h('div', record.otherClueObj.address)
}
},
{
title: '微信',
dataIndex: 'wx',
customRender: function ({ record }: any) {
return h('div', record.otherClueObj.wx)
}
},
{
key: 'operate',
title: '操作',
align: 'center',
width: 70,
fixed: 'right'
}
])
//
const tableRequest: TableRequest = (params, sorter, filter) => {
const pageParam = mergePageParam(params, sorter, filter)
return pageQueryPage({ ...pageParam, ...searchParams }).then(result => {
return Promise.resolve(result)
})
}
//
const reloadTable = (resetPageIndex?: boolean) => {
tableRef.value?.actionRef?.reload(resetPageIndex)
}
//
const searchTable = (params: directPageParam) => {
searchParams = params
reloadTable(true) // tableRequest
}
const selectReservation = (record: directDTO) => {
clueModalRef.value?.open(FormAction.OTHER, record)
}
</script>
<style lang="less" scoped>
.geopoliticalCustomers-title {
font-size: 17px;
font-weight: 600;
color: #000;
}
//
.operationButtonArea {
padding-bottom: 20px;
}
.editable-row-operations a {
margin-right: 8px;
}
</style>

@ -0,0 +1,172 @@
<template>
<a-modal
:title="title"
:visible="visible"
:mask-closable="false"
:centered="true"
:body-style="{ paddingBottom: '8px' }"
:confirm-loading="submitLoading"
:width="700"
@cancel="handleClose"
>
<div class="model-body sim-cont">
<a-form
ref="formRef"
:model="formModel"
:label-col="{ sm: { span: 24 }, md: { span: 8 } }"
:wrapper-col="wrapperCol"
>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="客户名称" name="customName">
<a-input v-model:value="formModel.customName" readonly placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="手机号码" name="nid">
<a-input v-model:value="formModel.nid" readonly placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="分发日期" name="distributeDate">
<a-time-picker
v-model:value="formModel.distributeDate"
disabled
format="YYYY-MM-DD HH:mm:ss"
show-time
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="来源" name="originType">
<a-select v-model:value="formModel.originType" disabled placeholder="请选择来源">
<a-select-option :value="0">巨量</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="地址" name="address">
<a-input
v-model:value="formModel.otherClueObj.address"
readonly
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="微信" name="wx">
<a-input v-model:value="formModel.otherClueObj.wx" readonly />
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="24">
<a-form-item
label="留资"
:label-col="{ sm: { span: 24 }, md: { span: 4 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 20 } }"
>
<a-list item-layout="horizontal" :data-source="formModel.otherClueObj.remarkArr">
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta :description="item[0]">
<template #title>
<a href="#">{{ item[1] }}</a>
</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</a-form-item>
</a-col>
</a-row>
</a-form>
</div>
<template #footer>
<a-button key="back" @click="handleClose"></a-button>
</template>
</a-modal>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, toRefs } from 'vue'
import { useModal } from '@/hooks/modal'
import { overrideProperties } from '@/utils/bean-utils'
import type { FormRequestMapping } from '@/hooks/form'
// import type { shopDTO } from '@/api/geopoliticalCustomers/types'
import { useAdminForm, useFormAction, FormAction, wrapperCol } from '@/hooks/form'
import type { directDTO } from '@/api/directResources/types'
import type { FormInstance } from 'ant-design-vue/es/form/Form'
//
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
const emits = defineEmits<{
(e: 'submit-success'): void
}>()
const formModel = reactive<directDTO>({
directClueId: undefined,
batchNo: '',
nid: '',
customName: '',
originType: 0,
effectiveStatus: 0,
distributeType: 0,
otherClueObj: {},
distributeDate: null,
distributeUserId: undefined
})
const formRef = ref<FormInstance>()
//
const formRule = ref({})
const { title, visible, openModal, closeModal } = useModal()
const { formAction } = useFormAction()
//
const formRequestMapping: FormRequestMapping<directDTO> = {}
const { submitLoading, resetFields } = useAdminForm(
formAction,
formRequestMapping,
formModel,
formRule
)
onMounted(() => {})
const handleClose = () => {
closeModal()
submitLoading.value = false
}
defineExpose({
async open(newFormAction: FormAction, record: directDTO) {
openModal()
resetFields()
if (newFormAction === FormAction.OTHER) {
title.value = '详情'
record.distributeDate = dayjs(record?.distributeDate, 'YYYY-MM-DD HH:mm:ss')
record.otherClueObj.remarkArr = Object.entries(JSON.parse(record.otherClueObj.remarkDict))
overrideProperties(formModel, record)
}
formAction.value = newFormAction
}
})
</script>
<style lang="less" scoped>
//
::v-deep .ant-picker {
width: 100%;
}
.model-body {
max-height: 70vh;
overflow-y: auto;
}
</style>

@ -0,0 +1,137 @@
<template>
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<a-form :model="formModel" :label-col="labelCol">
<a-row :gutter="16">
<!-- v-if="userInfoCurrent === 'ROLE_ADMIN'" -->
<div class="top-panel u-flex flex-between">
<a-row>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="客户名称">
<a-input v-model:value="formModel.customName" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="分发日期">
<a-range-picker
v-model:value="formModel.distributeDate"
format="YYYY-MM-DD"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="来源">
<a-select v-model:value="formModel.originType">
<a-select-option :value="0">巨量</a-select-option>
</a-select>
</a-form-item>
</a-col>
<!-- <a-col :xl="8" :md="12" :sm="24">
<a-form-item label="是否有效">
<a-select v-model:value="formModel.effectiveStatus">
<a-select-option :value="0">无效</a-select-option>
<a-select-option :value="1">有效</a-select-option>
</a-select>
</a-form-item>
</a-col> -->
<a-col :xl="24" :md="24" :sm="24">
<search-actions :loading="props.loading" @search="search" @reset="reset" />
</a-col>
</a-row>
<div class="bulletin">
<p class="title text-center">分发统计</p>
<div>
<a-row>
<a-col :span="12">
<a-statistic title="总成交数" :value="112893" style="margin-right: 50px" />
</a-col>
<a-col :span="12">
<a-statistic title="总分发数" :precision="2" :value="112893" />
</a-col>
</a-row>
</div>
<div class="text-center c-red">转化成交比例 80%</div>
</div>
</div>
</a-row>
</a-form>
</a-card>
</template>
<script setup lang="ts">
import { Form } from 'ant-design-vue'
import type { directPageParam } from '@/api/directResources/types'
import dayjs from 'dayjs'
import type { Dayjs } from 'dayjs'
//
import { useUserStore } from '@/stores/user-store'
const { userInfo } = useUserStore()
const userInfoCurrent = ref<string | undefined>('')
onMounted(() => {
})
const useForm = Form.useForm
// label
const labelCol = { md: { span: 6 } }
const props = withDefaults(
defineProps<{
loading?: boolean
}>(),
{ loading: false }
)
const emits = defineEmits<{
(e: 'search', params: Record<string, any>): void
}>()
const formModel = reactive<directPageParam>({
customName: '',
distributeDate: undefined,
originType: null,
effectiveStatus: null
})
watch(
() => formModel.distributeDate,
nval => {
if (nval && nval.length == 2) {
formModel.startTime = dayjs(nval[0]).format('YYYY-MM-DD')
formModel.endTime = dayjs(nval[1]).format('YYYY-MM-DD')
} else {
formModel.distributeDate = undefined
formModel.startTime = undefined
formModel.endTime = undefined
}
}
)
const { resetFields } = useForm(formModel)
const search = () => {
const param = toRaw(formModel)
if (param.distributeDate && param.distributeDate.length == 2) {
delete param.distributeDate
}
emits('search', param)
}
const reset = () => {
//
resetFields()
search()
}
</script>
<style lang="less">
.bulletin {
border: 1px solid #d9d9d9;
border-radius: 2px;
padding: 10px;
margin: 0 0 24px 10px;
.title {
font-weight: bold;
}
}
.top-panel {
width: 100%;
align-items: flex-start;
}
</style>

@ -0,0 +1,172 @@
<template>
<!-- 头部 -->
<a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="geopoliticalCustomers-title">客户看板</div>
</a-card>
<!-- 搜索 -->
<customer-search :loading="tableRef?.loading" @search="searchTable" />
<!-- 工具栏 -->
<!-- <a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="operationButtonArea">
<a-button type="primary" @click="addShop"></a-button>
</div>
</a-card> -->
<!-- 底部表格 -->
<pro-table
ref="tableRef"
row-key="customId"
:request="tableRequest"
:columns="columns"
:scroll="{ x: 1100 }"
:options="{ density: false }"
class="protable"
:pagination="{ showQuickJumper: true }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'batchNo'">
<a>{{ record.id }}</a>
</template>
<template v-else-if="column.key === 'operate'">
<operation-group>
<a @click="selectReservation(record)"></a>
</operation-group>
</template>
</template>
</pro-table>
<!-- 预约详情 -->
<customer-modal ref="customerModalRef" @submit-success="reloadTable" />
</template>
<script setup lang="ts">
import { ref } from 'vue'
// import { message } from 'ant-design-vue'
import { doRequest } from '@/utils/axios/request'
//
import ProTable from '#/table'
import type { ProTableInstanceExpose, TableRequest, ProColumns } from '#/table'
import { mergePageParam } from '@/utils/page-utils'
import { FormAction } from '@/hooks/form'
import customerModal from './customerModal.vue'
import customerSearch from './customerSearch.vue'
import { pageQueryPage } from '@/api/directResources'
import type { directDTO, directPageParam } from '@/api/directResources/types'
import { useUserStore } from '@/stores/user-store'
defineOptions({ name: 'ClueIndex' })
const { userInfo } = useUserStore()
//
//
const tableRef = ref<ProTableInstanceExpose>()
// add ref
const customerModalRef = ref<InstanceType<typeof customerModal>>()
// const reservationModalRef = ref<InstanceType<typeof reservationModal>>()
//
let searchParams: directPageParam = {
salesmanUserId: userInfo && userInfo.userId
}
const columns = ref<any[]>([
{
title: '编号',
width: 80,
dataIndex: 'batchNo'
},
{
title: '客户名称',
dataIndex: 'customName'
},
{
title: '手机号码',
dataIndex: 'nid'
},
{
title: '跟进员',
dataIndex: 'userNameList',
customRender: ({ record }: any) => {
if (record.userNameList.length > 0) {
return h('div', record.userNameList.join(','))
} else {
return h('div', '')
}
}
},
{
title: '来源',
dataIndex: 'originType',
customRender: ({ record }: any) => {
if (record.originType === 0) {
return h('div', '巨量')
}
}
},
{
title: '地址',
dataIndex: 'address',
customRender: function ({ record }: any) {
return h('div', record.otherClueObj.address)
}
},
{
title: '微信',
dataIndex: 'wx',
customRender: function ({ record }: any) {
return h('div', record.otherClueObj.wx)
}
},
{
title: '创建日期',
dataIndex: 'distributeDate',
width: 150,
align: 'center',
customRender: function ({ record }: any) {
if (record.distributeDate) {
return record.distributeDate
} else if (record.distributeDate == null) {
return '--'
}
}
},
{
key: 'operate',
title: '操作',
align: 'center',
width: 70,
fixed: 'right'
}
])
//
const tableRequest: TableRequest = (params, sorter, filter) => {
const pageParam = mergePageParam(params, sorter, filter)
return pageQueryPage({ ...pageParam, ...searchParams }).then(result => {
return Promise.resolve(result)
})
}
//
const reloadTable = (resetPageIndex?: boolean) => {
tableRef.value?.actionRef?.reload(resetPageIndex)
}
//
const searchTable = (params: directPageParam) => {
searchParams = params
reloadTable(true) // tableRequest
}
const selectReservation = (record: directDTO) => {
customerModalRef.value?.open(FormAction.OTHER, record)
}
</script>
<style lang="less" scoped>
.geopoliticalCustomers-title {
font-size: 17px;
font-weight: 600;
color: #000;
}
//
.operationButtonArea {
padding-bottom: 20px;
}
.editable-row-operations a {
margin-right: 8px;
}
</style>

@ -0,0 +1,171 @@
<template>
<a-modal
:title="title"
:visible="visible"
:mask-closable="false"
:centered="true"
:body-style="{ paddingBottom: '8px' }"
:confirm-loading="submitLoading"
:width="700"
@cancel="handleClose"
>
<div class="model-body sim-cont">
<a-form
ref="formRef"
:model="formModel"
:label-col="{ sm: { span: 24 }, md: { span: 8 } }"
:wrapper-col="wrapperCol"
>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="客户名称" name="customName">
<a-input v-model:value="formModel.customName" readonly placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="手机号码" name="nid">
<a-input v-model:value="formModel.nid" readonly placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="分发日期" name="distributeDate">
<a-time-picker
v-model:value="formModel.distributeDate"
disabled
format="YYYY-MM-DD HH:mm:ss"
show-time
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="来源" name="originType">
<a-select v-model:value="formModel.originType" disabled placeholder="请选择来源">
<a-select-option :value="0">巨量</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="地址" name="address">
<a-input
v-model:value="formModel.otherClueObj.address"
readonly
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="微信" name="wx">
<a-input v-model:value="formModel.otherClueObj.wx" readonly />
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="24">
<a-form-item
label="留资"
:label-col="{ sm: { span: 24 }, md: { span: 4 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 20 } }"
>
<a-list item-layout="horizontal" :data-source="formModel.otherClueObj.remarkArr">
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta :description="item[0]">
<template #title>
<a href="#">{{ item[1] }}</a>
</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</a-form-item>
</a-col>
</a-row>
</a-form>
</div>
<template #footer>
<a-button key="back" @click="handleClose"></a-button>
</template>
</a-modal>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, toRefs } from 'vue'
import { useModal } from '@/hooks/modal'
import { overrideProperties } from '@/utils/bean-utils'
import type { FormRequestMapping } from '@/hooks/form'
// import type { shopDTO } from '@/api/geopoliticalCustomers/types'
import { useAdminForm, useFormAction, FormAction, wrapperCol } from '@/hooks/form'
import type { directDTO } from '@/api/directResources/types'
import type { FormInstance } from 'ant-design-vue/es/form/Form'
//
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
const emits = defineEmits<{
(e: 'submit-success'): void
}>()
const formModel = reactive<directDTO>({
batchNo: '',
nid: '',
customName: '',
originType: 0,
effectiveStatus: 0,
distributeType: 0,
otherClueObj: {},
distributeDate: null,
distributeUserId: undefined
})
const formRef = ref<FormInstance>()
//
const formRule = ref({})
const { title, visible, openModal, closeModal } = useModal()
const { formAction } = useFormAction()
//
const formRequestMapping: FormRequestMapping<directDTO> = {}
const { submitLoading, resetFields } = useAdminForm(
formAction,
formRequestMapping,
formModel,
formRule
)
onMounted(() => {})
const handleClose = () => {
closeModal()
submitLoading.value = false
}
defineExpose({
async open(newFormAction: FormAction, record: directDTO) {
openModal()
resetFields()
if (newFormAction === FormAction.OTHER) {
title.value = '详情'
record.distributeDate = dayjs(record?.distributeDate, 'YYYY-MM-DD HH:mm:ss')
// JSON.parse(record.otherClueObj.remarkDict)
record.otherClueObj.remarkArr = Object.entries(JSON.parse(record.otherClueObj.remarkDict))
overrideProperties(formModel, record)
}
formAction.value = newFormAction
}
})
</script>
<style lang="less" scoped>
//
::v-deep .ant-picker {
width: 100%;
}
.model-body {
max-height: 70vh;
overflow-y: auto;
}
</style>

@ -0,0 +1,92 @@
<!--
* @Author: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
* @Date: 2023-11-01 10:36:18
* @LastEditors: error: error: git config user.name & please set dead value or install git && error: git config user.email & please set dead value or install git & please set dead value or install git
* @LastEditTime: 2023-11-06 15:06:05
* @FilePath: \byhl-zt\src\views\directResources\customerPanel\customerSearch.vue
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<a-form :model="formModel" :label-col="labelCol">
<a-row :gutter="16">
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="客户名称">
<a-input v-model:value="formModel.customName" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="来源">
<a-select v-model:value="formModel.originType">
<a-select-option :value="0">巨量</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :xl="24" :md="24" :sm="24">
<search-actions :loading="props.loading" @search="search" @reset="reset" />
</a-col>
</a-row>
</a-form>
</a-card>
</template>
<script setup lang="ts">
import { Form } from 'ant-design-vue'
import type { directPageParam } from '@/api/directResources/types'
import dayjs from 'dayjs'
import { useUserStore } from '@/stores/user-store'
//
onMounted(() => {
})
const { userInfo } = useUserStore()
const useForm = Form.useForm
// label
const labelCol = { md: { span: 6 } }
const props = withDefaults(
defineProps<{
loading?: boolean
}>(),
{ loading: false }
)
const emits = defineEmits<{
(e: 'search', params: Record<string, any>): void
}>()
const formModel = reactive<directPageParam>({
customName: '',
distributeDate: undefined,
distributeType: null,
originType: null,
effectiveStatus: null
})
watch(
() => formModel.distributeDate,
nval => {
if (nval && nval.length == 2) {
formModel.startTime = dayjs(nval[0]).format('YYYY-MM-DD')
formModel.endTime = dayjs(nval[1]).format('YYYY-MM-DD')
} else {
formModel.distributeDate = undefined
formModel.startTime = undefined
formModel.endTime = undefined
}
}
)
const { resetFields } = useForm(formModel)
const search = () => {
const param = toRaw(formModel)
if (param.distributeDate && param.distributeDate.length == 2) {
delete param.distributeDate
}
param.salesmanUserId = userInfo && userInfo.userId
emits('search', param)
}
const reset = () => {
//
resetFields()
search()
}
</script>

@ -0,0 +1,188 @@
<template>
<!-- 头部 -->
<a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="geopoliticalCustomers-title">检后分发</div>
</a-card>
<!-- 搜索 -->
<distribute-search :loading="tableRef?.loading" @search="searchTable" />
<!-- 工具栏 -->
<!-- <a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="operationButtonArea">
<a-button type="primary" @click="addShop"></a-button>
</div>
</a-card> -->
<!-- 底部表格 -->
<!-- <resize-observer></resize-observer> -->
<pro-table
ref="tableRef"
row-key="customId"
header-title="分发线索"
:request="tableRequest"
:columns="columns"
:scroll="{ x: 1100 }"
class="protable"
:options="{ density: false }"
:pagination="{ showQuickJumper: true }"
>
<template #bodyCell="{ column, record }">
<template v-if="column.key === 'id'">
<a>{{ record.id }}</a>
</template>
<template v-else-if="column.key === 'operate'">
<operation-group>
<a :class="{ 'forbid-click': record.distributeType == 1 }" @click="editShop(record)"
>分发</a
>
</operation-group>
</template>
</template>
</pro-table>
<!-- 新建/编辑弹窗 -->
<distribute-modal ref="distributeModalRef" @submit-success="reloadTable" />
<!-- 预约详情 -->
<!-- <reservation-modal ref="reservationModalRef"></reservation-modal> -->
</template>
<script setup lang="ts">
import { ref } from 'vue'
// import { message } from 'ant-design-vue'
import { doRequest } from '@/utils/axios/request'
//
import ProTable from '#/table'
import type { ProTableInstanceExpose, TableRequest, ProColumns } from '#/table'
import { mergePageParam } from '@/utils/page-utils'
import { FormAction } from '@/hooks/form'
import distributeModal from './distributeModal.vue'
import distributeSearch from './distributeSearch.vue'
import { pageQueryPage } from '@/api/directResources'
import type { directDTO, directPageParam } from '@/api/directResources/types'
import { useUserStore } from '@/stores/user-store'
import ResizeObserver from 'ant-design-vue/es/vc-resize-observer'
defineOptions({ name: 'DistributeIndex' })
const { userInfo } = useUserStore()
//
//
const tableRef = ref<ProTableInstanceExpose>()
// add ref
const distributeModalRef = ref<InstanceType<typeof distributeModal>>()
//
let searchParams: directPageParam = {
distributeUserId: userInfo && userInfo.userId
}
const columns = ref<any[]>([
{
title: '编号',
width: 80,
dataIndex: 'batchNo'
},
{
title: '客户名称',
dataIndex: 'customName'
},
{
title: '手机号码',
dataIndex: 'nid'
},
{
title: '分发日期',
dataIndex: 'distributeDate',
width: 150,
align: 'center',
customRender: function ({ record }: any) {
if (record.distributeDate) {
return record.distributeDate
} else if (record.distributeDate == null) {
return '--'
}
}
},
{
title: '跟进员',
dataIndex: 'userNameList',
customRender: ({ record }: any) => {
if (record.userNameList.length > 0) {
return h('div', record.userNameList.join(','))
} else {
return h('div', '')
}
}
},
{
title: '来源',
dataIndex: 'originType',
customRender: ({ record }: any) => {
if (record.originType === 0) {
return h('div', '巨量')
}
}
},
{
title: '地址',
dataIndex: 'address',
customRender: function ({ record }: any) {
return h('div', record.otherClueObj.address)
}
},
{
title: '微信',
dataIndex: 'wx',
customRender: function ({ record }: any) {
return h('div', record.otherClueObj.wx)
}
},
{
key: 'operate',
title: '操作',
align: 'center',
width: 70,
fixed: 'right'
}
])
//
const tableRequest: TableRequest = (params, sorter, filter) => {
const pageParam = mergePageParam(params, sorter, filter)
return pageQueryPage({ ...pageParam, ...searchParams }).then(result => {
return Promise.resolve(result)
})
}
//
const reloadTable = (resetPageIndex?: boolean) => {
tableRef.value?.actionRef?.reload(resetPageIndex)
}
//
const searchTable = (params: directPageParam) => {
searchParams = params
reloadTable(true) // tableRequest
}
const editShop = (record: directDTO) => {
if (record.distributeType == 1) {
return false
}
distributeModalRef.value?.open(FormAction.UPDATE, record)
}
</script>
<style lang="less" scoped>
.geopoliticalCustomers-title {
font-size: 17px;
font-weight: 600;
color: #000;
}
//
.operationButtonArea {
padding-bottom: 20px;
}
.editable-row-operations a {
margin-right: 8px;
}
.forbid-click {
pointer-events: none;
// filter: alpha(opacity=50);
// -moz-opacity: 0.5;
// opacity: 0.5;
color: rgba(0, 0, 0, 0.25);
}
</style>

@ -0,0 +1,216 @@
<template>
<a-modal
:title="title"
:visible="visible"
:mask-closable="false"
:centered="true"
:body-style="{ paddingBottom: '8px' }"
:confirm-loading="submitLoading"
ok-text="分发"
:width="700"
@ok="handleSubmit"
@cancel="handleClose"
>
<div class="model-body sim-cont">
<a-form
ref="formRef"
:model="formModel"
:label-col="{ sm: { span: 24 }, md: { span: 8 } }"
:wrapper-col="wrapperCol"
>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="客户名称" name="customName">
<a-input v-model:value="formModel.customName" readonly placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="手机号码" name="nid">
<a-input v-model:value="formModel.nid" readonly placeholder="请输入" />
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="分发日期" name="distributeDate">
<a-time-picker
v-model:value="formModel.distributeDate"
disabled
format="YYYY-MM-DD HH:mm:ss"
show-time
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="来源" name="originType">
<a-select v-model:value="formModel.originType" disabled placeholder="请选择来源">
<a-select-option :value="0">巨量</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item label="地址" name="address">
<a-input
v-model:value="formModel.otherClueObj.address"
readonly
placeholder="请输入"
/>
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="微信" name="wx">
<a-input v-model:value="formModel.otherClueObj.wx" readonly />
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="12">
<a-form-item
label="业务员"
name="userId"
:rules="[{ required: true, message: '请选择业务员' }]"
>
<a-select v-model:value="formModel.userId" mode="multiple" placeholder="请选择业务员">
<a-select-option v-for="item in userList" :key="item.userId" :value="item.userId">{{
item.userName
}}</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row justify="start">
<a-col :span="24">
<a-form-item
label="留资"
:label-col="{ sm: { span: 24 }, md: { span: 4 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 20 } }"
>
<a-list item-layout="horizontal" :data-source="formModel.otherClueObj.remarkArr">
<template #renderItem="{ item }">
<a-list-item>
<a-list-item-meta :description="item[0]">
<template #title>
<a href="#">{{ item[1] }}</a>
</template>
</a-list-item-meta>
</a-list-item>
</template>
</a-list>
</a-form-item>
</a-col>
</a-row>
</a-form>
</div>
</a-modal>
</template>
<script setup lang="ts">
import { reactive, ref, onMounted, toRefs } from 'vue'
import { useModal } from '@/hooks/modal'
import { overrideProperties } from '@/utils/bean-utils'
import type { FormRequestMapping } from '@/hooks/form'
import { doRequest } from '@/utils/axios/request'
import { useAdminForm, useFormAction, FormAction, wrapperCol } from '@/hooks/form'
import type { directDTO, distributeData } from '@/api/directResources/types'
import { upDistribute, getfFindDirectSalesman } from '@/api/directResources/index'
import type { FormInstance } from 'ant-design-vue/es/form/Form'
//
import 'dayjs/locale/zh-cn'
import dayjs from 'dayjs'
const emits = defineEmits<{
(e: 'submit-success'): void
}>()
const formModel = reactive<directDTO>({
directClueId: undefined,
batchNo: '',
nid: '',
customName: '',
originType: 0,
effectiveStatus: 0,
distributeType: 0,
otherClueObj: {},
distributeDate: null,
distributeUserId: undefined
})
const formRef = ref<FormInstance>()
let userList: any = []
//
const formRule = ref({})
const { title, visible, openModal, closeModal } = useModal()
const { formAction } = useFormAction()
//
const formRequestMapping: FormRequestMapping<directDTO> = {}
const { submitLoading, resetFields } = useAdminForm(
formAction,
formRequestMapping,
formModel,
formRule
)
onMounted(() => {
initUserList()
})
const handleClose = () => {
closeModal()
submitLoading.value = false
}
const initUserList = () => {
doRequest(getfFindDirectSalesman(), {
onSuccess: (res: any) => {
userList = res.data
}
})
}
/* 表单提交处理 */
const handleSubmit = () => {
formRef.value?.validate().then(() => {
const data: distributeData[] = []
formModel.userId?.forEach((item: number) => {
data.push({
clueId: formModel.directClueId as number,
userId: item,
userName: userList.filter((it: any) => it.userId == item)[0].userName
})
})
console.log('data===', data)
doRequest(upDistribute(data), {
successMessage: '分发成功',
onSuccess: () => {
closeModal()
emits('submit-success')
}
})
})
}
defineExpose({
async open(newFormAction: FormAction, record: directDTO) {
openModal()
resetFields()
if (newFormAction === FormAction.UPDATE) {
title.value = '分发'
record.distributeDate = dayjs(record?.distributeDate, 'YYYY-MM-DD HH:mm:ss')
record.otherClueObj.remarkArr = Object.entries(JSON.parse(record.otherClueObj.remarkDict))
overrideProperties(formModel, record)
}
formAction.value = newFormAction
}
})
</script>
<style lang="less" scoped>
//
::v-deep .ant-picker {
width: 100%;
}
.model-body {
max-height: 70vh;
overflow-y: auto;
}
</style>

@ -0,0 +1,101 @@
<template>
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<a-form :model="formModel" :label-col="labelCol">
<a-row :gutter="16">
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="客户名称">
<a-input v-model:value="formModel.customName" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="分发日期">
<a-range-picker
v-model:value="formModel.distributeDate"
format="YYYY-MM-DD"
style="width: 100%"
/>
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="分发状态">
<a-select v-model:value="formModel.distributeType">
<a-select-option :value="0">未分发</a-select-option>
<a-select-option :value="1">已分发</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="来源">
<a-select v-model:value="formModel.originType">
<a-select-option :value="0">巨量</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col :xl="24" :md="24" :sm="24">
<search-actions :loading="props.loading" @search="search" @reset="reset" />
</a-col>
</a-row>
</a-form>
</a-card>
</template>
<script setup lang="ts">
import { Form } from 'ant-design-vue'
import type { directPageParam } from '@/api/directResources/types'
import dayjs from 'dayjs'
import { useUserStore } from '@/stores/user-store'
//
onMounted(() => {
})
const { userInfo } = useUserStore()
const useForm = Form.useForm
// label
const labelCol = { md: { span: 6 } }
const props = withDefaults(
defineProps<{
loading?: boolean
}>(),
{ loading: false }
)
const emits = defineEmits<{
(e: 'search', params: Record<string, any>): void
}>()
const formModel = reactive<directPageParam>({
customName: '',
distributeDate: undefined,
originType: null,
distributeType: null,
effectiveStatus: null
})
watch(
() => formModel.distributeDate,
nval => {
if (nval && nval.length == 2) {
formModel.startTime = dayjs(nval[0]).format('YYYY-MM-DD')
formModel.endTime = dayjs(nval[1]).format('YYYY-MM-DD')
} else {
formModel.distributeDate = undefined
formModel.startTime = undefined
formModel.endTime = undefined
}
}
)
const { resetFields } = useForm(formModel)
const search = () => {
const param = toRaw(formModel)
if (param.distributeDate && param.distributeDate.length == 2) {
delete param.distributeDate
}
param.distributeUserId = userInfo && userInfo.userId
emits('search', param)
}
const reset = () => {
//
resetFields()
search()
}
</script>

@ -57,7 +57,7 @@ import shopSearch from './shopSearch.vue'
import { pageQueryPage, deleteShop } from '@/api/shopManage'
import type { shopDetailVO, shopParam } from '@/api/shopManage/types'
defineOptions({ name: 'GeopoliticalCustomers' })
defineOptions({ name: 'ShopIndex' })
//
//

@ -59,6 +59,7 @@ declare module '@vue/runtime-core' {
ASelectOption: typeof import('ant-design-vue/es')['SelectOption']
ASpace: typeof import('ant-design-vue/es')['Space']
ASpin: typeof import('ant-design-vue/es')['Spin']
AStatistic: typeof import('ant-design-vue/es')['Statistic']
AStep: typeof import('ant-design-vue/es')['Step']
ASteps: typeof import('ant-design-vue/es')['Steps']
ASwitch: typeof import('ant-design-vue/es')['Switch']

Loading…
Cancel
Save