优化modal不被空白区域关闭

master
doublekou 9 months ago
commit 423e8b5b60

@ -23,6 +23,13 @@ module.exports = {
'@typescript-eslint/no-empty-function': 'off',
// 允许非空断言
'@typescript-eslint/no-non-null-assertion': 'off',
'vue/no-template-shadow': 'off'
'vue/no-template-shadow': 'off',
"@typescript-eslint/no-this-alias": [
"error",
{
"allowDestructuring": false, // Disallow `const { props, state } = this`; true by default
"allowedNames": ["that"] // Allow `const self = this`; `[]` by default
}
]
}
}

@ -33,6 +33,7 @@
"cropperjs": "^1.5.13",
"crypto-js": "^4.1.1",
"dayjs": "^1.11.7",
"echarts": "^5.4.3",
"js-cookie": "^3.0.5",
"json-bigint": "^1.0.0",
"mitt": "^3.0.0",

@ -50,6 +50,9 @@ dependencies:
dayjs:
specifier: ^1.11.7
version: 1.11.7
echarts:
specifier: ^5.4.3
version: 5.4.3
js-cookie:
specifier: ^3.0.5
version: 3.0.5
@ -2702,6 +2705,13 @@ packages:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: true
/echarts@5.4.3:
resolution: {integrity: sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==}
dependencies:
tslib: 2.3.0
zrender: 5.4.4
dev: false
/ejs@3.1.9:
resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==}
engines: {node: '>=0.10.0'}
@ -5313,6 +5323,10 @@ packages:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
dev: true
/tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
dev: false
/tslib@2.5.0:
resolution: {integrity: sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==}
dev: true
@ -5850,3 +5864,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
dev: true
/zrender@5.4.4:
resolution: {integrity: sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==}
dependencies:
tslib: 2.3.0
dev: false

@ -43,6 +43,9 @@ export type CustomerListRecord = {
originName?: string
otherClue?: string
remark?: string
extraData?: Array<detailFormItem>
channelType?: number
channelIdentifying?: Array<string>
}
/**
*
@ -78,6 +81,7 @@ export interface CustomerListSearch {
startTime?: string
// 访问时间区间的结束值
endTime?: string
salesmanArray?: number[]
clueLabelName?: string
}
//修改资源(编辑接口用到)

@ -1,7 +1,6 @@
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
@ -12,6 +11,6 @@ export function upDistribute(data: distributeData[]) {
return httpClient.post<ApiResult>('/directClue/distribute', data)
}
export function getfFindDirectSalesman() {
return httpClient.get<ApiResult>('/system/user/findDirectSalesman', {})
export function getfFindDirectSalesman(id: number) {
return httpClient.get<ApiResult>('/system/user/findSalesman/' + id)
}

@ -1,16 +1,14 @@
import httpClient from '@/utils/axios'
import type { ApiResult } from '@/api/types'
import type {
DistributeTaskManagementPageParam,
distributeTaskId
} from '@/api/controlcenterstation/distributionTaskManagement/types'
import type { distributeTaskId } from '@/api/controlcenterstation/distributionTaskManagement/types'
import type {
GeopoliticalCustomersDTO,
CustomerDTO,
customId,
auditDTO,
GeopoliticalCustomersPageParam,
storePageParam
storePageParam,
toExamine
} from '@/api/geopoliticalCustomers/types'
// import type {
@ -126,18 +124,8 @@ export function getStoreData(pageParams: storePageParam) {
*
*
*/
export function updateCustomerAudit(
customId: number,
status: number,
salesmanType: number,
reviewUserId?: undefined | number
) {
return httpClient.post<ApiResult>('/custom/audit', {
customId,
status,
salesmanType,
reviewUserId
})
export function updateCustomerAudit(data: toExamine) {
return httpClient.post<ApiResult>('/custom/audit', data)
}
/**
* ID

@ -182,6 +182,12 @@ export interface CustomerDTO {
//备注
remark?: string | undefined
address?: Array<any>
// 简略地址
abbreviateAddress?: any[]
// 性别
sex: number
// 客户资料
customInformation: string
//省
economize?: string
//市
@ -200,6 +206,8 @@ export interface CustomerDTO {
customStoreEntities: Array<customStoreEntitiesItem>
description?: number | undefined
status?: number | undefined
salesmanUserId?: number[]
type?: number
}
export interface auditDTO {
customId?: number | undefined
@ -301,3 +309,11 @@ export type storeQO = {
// 结束时间
endTime?: string
}
// 分发 重审 参数
export type toExamine = {
customId: number
status: number
salesmanType: number
reviewUserId?: undefined | number
salesmanUserId?: number[]
}

@ -0,0 +1,28 @@
import httpClient from '@/utils/axios'
import type { ApiResult } from '@/api/types'
import type { searchData } from './types'
// 首页顶部统计
export function getHomePageBase() {
return httpClient.get<ApiResult>('/api/homePage/base')
}
// 线索录入明细查询
export function getHomePageEnter(data: searchData) {
return httpClient.post<ApiResult<void>>('/api/homePage/enter', data)
}
// 各终端分发明细查询
export function getHomePageAssigned(data: searchData) {
return httpClient.post<ApiResult<void>>('/api/homePage/assigned', data)
}
// 首页图表-公告导出方法
export function getHomePageExport(data: searchData) {
return httpClient.post<ApiResult<void>>('/api/homePage/export', data, { responseType: 'blob' })
}
// 首页图表-分发数量统计-分发员
export function getDistributors(data: searchData) {
return httpClient.post<ApiResult<void>>('/api/homePage/distributors', data)
}
// 首页图表-线索数量统计-分发员
export function getSalesman(data: searchData) {
return httpClient.post<ApiResult<void>>('/api/homePage/salesman', data)
}

@ -0,0 +1,14 @@
export type searchData = {
createStartTime?: string
createEndTime?: string
assignedIdList?: number[]
enterIdList?: number[]
channelType: number
type?: number
}
export type chartData = {
title?: string
xAxisArr: string[]
seriesArr: any[]
}

@ -66,7 +66,6 @@ export function updateUserAvatar(userId: Key | undefined, fileObj: FileObject) {
const formData = new FormData()
formData.append('file', fileObj.data, fileObj.name)
formData.append('userId', userId + '')
console.log("🚀 ~ file: index.ts:69 ~ updateUserAvatar ~ formData:", formData)
return httpClient.postForm<ApiResult<string>>('/system/user/avatar', formData)
}
@ -102,3 +101,7 @@ export function updateUserPassword(userId: number, data: SysUserPassDTO) {
export function chargeClue(chargeDto: SysUserChargeDTO) {
return httpClient.post<ApiResult<void>>('/system/user/recharge', chargeDto)
}
// 当前管理员角色-查询指定角色子用户:
export function getFindRoleSonUser(roleId: number) {
return httpClient.get<ApiResult<SysUserScope>>(`/system/user/findRoleSonUser/${roleId}`)
}

@ -213,6 +213,7 @@ export type SysUserScope = {
export type SysUserPassDTO = {
pass: string
confirmPass: string
oldPass: string
}
interface clueStageState {
// tags: tagsItem[]

@ -6,14 +6,14 @@ import { getLoginUserMenus } from '@/api/system/menu'
import type { SysMenuRouterVO } from '@/api/system/menu/types'
export interface UserInfo extends LoginUserInfo {
roleCodes: string[]
permissions: string[]
gender: number | undefined
roleCodes: string[]
}
const accessTokenKey = getStorageKey('access-token')
const userInfoKey = getStorageKey('user-info')
const roleCodesKey = getStorageKey('role-codes')
export const useUserStore = defineStore('userStore', {
// 其他配置...
state: () => ({
@ -24,7 +24,11 @@ export const useUserStore = defineStore('userStore', {
writeDefaults: false,
serializer: StorageSerializers.object
}),
userMenus: undefined as SysMenuRouterVO[] | undefined
userMenus: undefined as SysMenuRouterVO[] | undefined,
// 角色
roleCodes: useLocalStorage<string[] | undefined>(roleCodesKey, undefined, {
writeDefaults: false
})
}),
actions: {
async fetchUserMenus() {
@ -65,6 +69,7 @@ export const useUserStore = defineStore('userStore', {
this.accessToken = undefined
this.userInfo = undefined
this.userMenus = undefined
this.roleCodes = undefined
}
}
})

@ -7,3 +7,37 @@ export function hasClass(dom: HTMLElement, className: string) {
) >= 0
)
}
export function debounce(func: any, wait: any, immediate: any) {
let timeout: any, args: null, context: any, timestamp: number, result: any
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args: any) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}

@ -0,0 +1,106 @@
<template>
<div ref="chartDom" :style="{ height: height, width: width }"></div>
</template>
<script setup lang="ts">
import * as echarts from 'echarts'
import { toRefs, onMounted, watch } from 'vue'
import type { chartData } from '@/api/system/statistics/types'
type EChartsOption = echarts.EChartsOption
let mylineChart: any = null
const props = withDefaults(
defineProps<{
height: string
width: string
chartDatas: chartData | undefined
}>(),
{
height: '300px',
width: '100%'
}
)
const { height, width, chartDatas } = toRefs(props)
const chartDom = ref()
const debounce = (fun: any, delay: number) => {
let timer: any
return function () {
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
fun()
}, delay)
}
}
const resizeHandler = () => {
mylineChart.resize()
}
const cancalDebounce = debounce(resizeHandler, 500)
onMounted(() => {
initChart()
// window.addEventListener('resize', () => {
// mylineChart && mylineChart.resize()
// })
})
onBeforeUnmount(() => {
if (!mylineChart) {
return
}
window.removeEventListener('resize', cancalDebounce)
mylineChart.dispose()
mylineChart = null
})
// watch(
// () => props.chartDatas as chartData,
// (nval: chartData) => {
// console.log('🚀 ~ file: linChart.vue:40 ~ nval:', nval)
// setOptions(nval)
// },
// {
// deep: true
// }
// )
const initChart = () => {
mylineChart = echarts.init(chartDom.value)
setOptions(chartDatas as unknown as chartData)
window.addEventListener('resize', cancalDebounce)
}
const setOptions = ({ title, xAxisArr, seriesArr }: chartData) => {
const options = {
title: {
text: title
},
legend: {},
tooltip: {
trigger: 'axis'
},
grid: {
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
toolbox: {
feature: {
saveAsImage: {}
}
},
xAxis: {
type: 'category',
boundaryGap: false,
data: xAxisArr
},
yAxis: {
type: 'value'
},
series: seriesArr
}
options && mylineChart.setOption(options)
}
defineExpose({
setOptions
})
</script>
<style scoped></style>

@ -1,33 +1,306 @@
<template>
<!-- <a-spin
tip="Loading..."
size="large"
:spinning="iframeLoading"
wrapper-class-name="iframe-spin-wrapper"
>
<iframe :id="id" ref="iframeRef" :src="url" class="iframe" @load="hideLoading" />
</a-spin> -->
<!-- 工具栏 -->
<customer-list-search :loading="tableRef?.loading" @search="searchTable" />
<div class="homeContent">
<!-- <customer-list-search :loading="tableRef?.loading" @search="searchTable" /> -->
<div>
<!-- 业务主管 -->
<div v-if="roleCodes.length != 0 && roleCodes.includes('ROLE_STORE_EXECUTIVE')">
<a-card :bordered="false" style="margin-bottom: 16px">
<a-row>
<a-col :span="6" class="text-center">
<a-statistic title="进线数" :value="topStatistics.enterNum"></a-statistic>
</a-col>
<a-col :span="6" class="text-center">
<a-statistic title="分发数" :value="topStatistics.assignedNum"></a-statistic>
</a-col>
<a-col :span="6" class="text-center">
<a-statistic title="重审数" :value="topStatistics.reviewNum"></a-statistic>
</a-col>
<a-col :span="6" class="text-center">
<a-statistic title="分发率" :value="topStatistics.assignedRate * 100">
<template #suffix>
<span>%</span>
</template>
</a-statistic>
</a-col>
</a-row>
</a-card>
<a-row :gutter="16">
<a-col class="gutter-row" :span="24">
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<div class="u-flex u-flex-between top-currency-title">
<div class="charTitle">线索录入明细查询</div>
<div />
</div>
<div class="toolGroup">
<div class="screenArea">
<a-range-picker v-model:value="searchObj.searchDate1" format="YYYY-MM-DD" />
<a-select
v-model:value="searchObj.enterIdList"
style="min-width: 180px"
allow-clear
mode="multiple"
placeholder="选择录入员"
:field-names="{ label: 'userName', value: 'userId' }"
:max-tag-count="1"
:options="enterUserList"
class="ml-5"
></a-select>
<a-select
v-model:value="searchObj.channel1"
style="width: 180px"
allow-clear
placeholder="选择渠道"
:options="channelArr"
class="ml-5"
></a-select>
<a-button type="primary" class="ml-5" @click="searchGetHomePageEnter"
>搜索</a-button
>
<a-button class="ml-5" @click="exportChartData('enter', 'searchDate1', 'channel1')"
>下载</a-button
>
</div>
</div>
<lin-chart
v-if="enterDetailsChart"
ref="enterDetailsRef"
width="100%"
height="300px"
:chart-datas="enterDetailsChart"
></lin-chart>
<a-empty v-else description="暂无数据" style="height: 300px; line-height: 300px" />
</a-card>
</a-col>
</a-row>
<a-row :gutter="16">
<a-col class="gutter-row" :span="24">
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<div class="u-flex u-flex-between top-currency-title">
<div class="charTitle">各终端分发明细查询</div>
<div />
</div>
<div class="toolGroup">
<div class="screenArea">
<a-range-picker v-model:value="searchObj.searchDate2" />
<a-select
v-model:value="searchObj.assignedIdList"
style="min-width: 180px"
allow-clear
mode="multiple"
:field-names="{ label: 'userName', value: 'userId' }"
placeholder="选择发送终端客户"
:max-tag-count="1"
:options="salesmanList"
class="ml-5"
></a-select>
<a-select
v-model:value="searchObj.channel2"
style="width: 180px"
allow-clear
placeholder="选择渠道"
:options="channelArr"
class="ml-5"
></a-select>
<a-button type="primary" class="ml-5" @click="searchGetHomePageAssigned"
>搜索</a-button
>
<a-button
class="ml-5"
@click="exportChartData('distribute', 'searchDate2', 'channel2')"
>下载</a-button
>
</div>
</div>
<lin-chart
v-if="terminalSendingChart"
ref="terminalSendingRef"
width="100%"
height="300px"
:chart-datas="terminalSendingChart"
></lin-chart>
<a-empty v-else description="暂无数据" style="height: 300px; line-height: 300px" />
</a-card>
</a-col>
</a-row>
</div>
<!-- 分发员 -->
<div v-if="roleCodes.length != 0 && roleCodes.includes('ROLE_PRELIMINARY_EXAMINER')">
<a-row :gutter="16">
<a-col class="gutter-row" :span="24">
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<div class="u-flex u-flex-between top-currency-title">
<div class="charTitle">分发数据统计</div>
<div />
</div>
<div class="toolGroup">
<div class="screenArea">
<a-range-picker v-model:value="searchObj.searchDate1" format="YYYY-MM-DD" />
<a-select
v-model:value="searchObj.channel1"
style="width: 180px"
allow-clear
placeholder="选择渠道"
:options="channelArr"
class="ml-5"
></a-select>
<a-button type="primary" class="ml-5" @click="searchGetDistributors"></a-button>
<!-- <a-button class="ml-5" @click="exportChartData('enter', 'searchDate1', 'channel1')"
>下载</a-button
> -->
</div>
</div>
<lin-chart
v-if="sendingNumChart"
ref="sendingNumRef"
width="100%"
height="300px"
:chart-datas="sendingNumChart"
></lin-chart>
<a-empty v-else description="暂无数据" style="height: 300px; line-height: 300px" />
</a-card>
</a-col>
</a-row>
</div>
<!-- 业务员 -->
<div v-if="roleCodes.length != 0 && roleCodes.includes('ROLE_STORE_SALESMAN')">
<a-row :gutter="16">
<a-col class="gutter-row" :span="24">
<a-card :bordered="false" style="margin-bottom: 16px" :body-style="{ paddingBottom: 0 }">
<div class="u-flex u-flex-between top-currency-title">
<div class="charTitle">分配数据统计</div>
<div />
</div>
<div class="toolGroup">
<div class="screenArea">
<a-range-picker v-model:value="searchObj.searchDate1" format="YYYY-MM-DD" />
<a-select
v-model:value="searchObj.channel1"
style="width: 180px"
allow-clear
placeholder="选择渠道"
:options="channelArr"
class="ml-5"
></a-select>
<a-button type="primary" class="ml-5" @click="searchgetSalesman"></a-button>
<!-- <a-button class="ml-5" @click="exportChartData('enter', 'searchDate1', 'channel1')"
>下载</a-button
> -->
</div>
</div>
<lin-chart
v-if="clueNumChart"
ref="clueNumRef"
width="100%"
height="300px"
:chart-datas="clueNumChart"
></lin-chart>
<a-empty v-else description="暂无数据" style="height: 300px; line-height: 300px" />
</a-card>
</a-col>
</a-row>
</div>
</div>
<div
v-if="
(roleCodes.length != 0 && roleCodes.includes('ROLE_REVIEWER')) ||
roleCodes.includes('ROLE_ENTRY_CLERK')
"
class="homeContent"
>
<div class="bullshit">努力开发中敬请期待...</div>
</div>
</template>
<script setup lang="ts">
import CustomerListSearch from '@/views/basic/iframe/iframeSearch.vue'
import { useUserStore } from '@/stores/user-store'
import linChart from '../echarts/linChart.vue'
import { Dayjs } from 'dayjs'
import dayjs from 'dayjs'
import { doRequest } from '@/utils/axios/request'
import { getFindRoleSonUser } from '@/api/system/user/index'
import { message } from 'ant-design-vue'
import type { chartData } from '@/api/system/statistics/types'
import { nextTick } from 'vue'
import { remoteFileDownload } from '@/utils/file-utils'
import {
getHomePageBase,
getHomePageEnter,
getHomePageAssigned,
getDistributors,
getSalesman,
getHomePageExport
} from '@/api/system/statistics/index'
type RangeValue = [Dayjs, Dayjs]
//
defineOptions({ name: 'IframeView' })
const userStore = useUserStore()
const iframeRef = ref<HTMLIFrameElement>()
const route = useRoute()
const id = route.path
const url = route.meta.target
// const route = useRoute()
// const lineRef = ref<InstanceType<typeof linChart>>()
//
const roleCodes = ref<string[]>([])
watch(
() => userStore.roleCodes,
nval => {
console.log('🚀 ~ file: index.vue:154 ~ roleCodes:', nval)
roleCodes.value = nval || ([] as string[])
}
)
const iframeLoading = ref(true)
//
const topStatistics = ref<any>({})
type stringKey = Record<string, any>
const searchObj = reactive<stringKey>({
searchDate1: [],
searchDate2: [],
channel1: null,
channel2: null,
enterIdList: [],
assignedIdList: []
})
//
// const enterIdList = ref<number[]>()
// const assignedIdList = ref<number[]>()
// list
const enterUserList: any = ref([])
// list
const salesmanList: any = ref([])
//
const enterDetailsChart = ref<chartData>()
const enterDetailsRef = ref()
//
const terminalSendingChart = ref<chartData>()
const terminalSendingRef = ref()
// -
const sendingNumChart = ref<chartData>()
const sendingNumRef = ref()
// 线-
const clueNumChart = ref<chartData>()
const clueNumRef = ref()
const channelArr = [
{
label: '手动创建',
value: 1
},
{
label: '文件上传',
value: 2
},
{
label: '飞鱼回传',
value: 3
},
{
label: '话单回传',
value: 4
},
{
label: 'api回传',
value: 5
}
]
function iframeResize() {
const iframe = unref(iframeRef)
if (iframe) {
@ -36,25 +309,281 @@ function iframeResize() {
}
}
onMounted(() => window.addEventListener('resize', iframeResize))
onMounted(() => {
window.addEventListener('resize', iframeResize)
roleCodes.value = userStore.roleCodes || []
console.log('🚀 ~ file: index.vue:154 ~ roleCodes:', roleCodes.value)
initClueEnter()
initSalesman()
initGetHomePageBase()
})
onUnmounted(() => window.removeEventListener('resize', iframeResize))
const hideLoading = () => {
iframeLoading.value = false
iframeResize()
}
const initClueEnter = () => {
doRequest(getFindRoleSonUser(19), {
onSuccess: (res: any) => {
enterUserList.value = res.data
}
})
}
const initSalesman = () => {
doRequest(getFindRoleSonUser(23), {
onSuccess: (res: any) => {
salesmanList.value = res.data
}
})
}
const initGetHomePageBase = () => {
doRequest(getHomePageBase(), {
onSuccess: (res: any) => {
topStatistics.value = res.data
}
})
}
// 线
const searchGetHomePageEnter = () => {
if (searchObj.searchDate1.length == 0) {
message.warning('请选择日期')
return
}
if (searchObj.enterIdList.length == 0) {
message.warning('请选择录入人员')
return
}
if (!searchObj.channel1) {
message.warning('请选择渠道')
return
}
doRequest(
getHomePageEnter({
createStartTime: dayjs(searchObj.searchDate1[0]).format('YYYY-MM-DD'),
createEndTime: dayjs(searchObj.searchDate1[1]).format('YYYY-MM-DD'),
enterIdList: searchObj.enterIdList,
channelType: searchObj.channel1
}),
{
onSuccess: (res: any) => {
let xAxisArr = []
const arr: any = []
if (res.data) {
xAxisArr = Object.keys(res.data[Object.keys(res.data)[0]])
for (const i in res.data) {
const obj: any = {}
obj.data = Object.values(res.data[i])
obj.type = 'line'
obj.stack = 'Total'
obj.name = i
arr.push(obj)
}
const chatData: chartData = {
seriesArr: arr,
xAxisArr
}
enterDetailsChart.value = chatData
nextTick(() => {
enterDetailsRef.value.setOptions(chatData)
})
} else {
message.info('未查询到数据')
}
}
}
)
}
//
const searchGetHomePageAssigned = () => {
if (searchObj.searchDate2.length == 0) {
message.warning('请选择日期')
return
}
if (searchObj.assignedIdList.length == 0) {
message.warning('请选择终端客户')
return
}
if (!searchObj.channel2) {
message.warning('请选择渠道')
return
}
doRequest(
getHomePageAssigned({
createStartTime: dayjs(searchObj.searchDate2[0]).format('YYYY-MM-DD'),
createEndTime: dayjs(searchObj.searchDate2[1]).format('YYYY-MM-DD'),
assignedIdList: searchObj.assignedIdList,
channelType: searchObj.channel2
}),
{
onSuccess: (res: any) => {
let xAxisArr = []
const arr: any = []
if (res.data) {
xAxisArr = Object.keys(res.data[Object.keys(res.data)[0]])
for (const i in res.data) {
const obj: any = {}
obj.data = Object.values(res.data[i])
obj.type = 'line'
obj.stack = 'Total'
obj.name = i
arr.push(obj)
}
const chatData: chartData = {
seriesArr: arr,
xAxisArr
}
terminalSendingChart.value = chatData
nextTick(() => {
terminalSendingRef.value.setOptions(chatData)
})
} else {
message.info('未查询到数据')
}
}
}
)
}
// -
const searchGetDistributors = () => {
if (searchObj.searchDate1.length == 0) {
message.warning('请选择日期')
return
}
if (!searchObj.channel1) {
message.warning('请选择渠道')
return
}
doRequest(
getDistributors({
createStartTime: dayjs(searchObj.searchDate1[0]).format('YYYY-MM-DD'),
createEndTime: dayjs(searchObj.searchDate1[1]).format('YYYY-MM-DD'),
channelType: searchObj.channel1
}),
{
onSuccess: (res: any) => {
let xAxisArr = []
const arr: any = []
if (res.data) {
xAxisArr = Object.keys(res.data)
let obj: any = {}
obj.data = Object.values(res.data).map((item: any) => item.assigned)
obj.type = 'line'
obj.stack = 'Total'
obj.name = '分发数'
arr.push(obj)
obj = {}
obj.data = Object.values(res.data).map((item: any) => item.enter)
obj.type = 'line'
obj.stack = 'Total'
obj.name = '进线数'
arr.push(obj)
const chatData: chartData = {
seriesArr: arr,
xAxisArr
}
sendingNumChart.value = chatData
nextTick(() => {
sendingNumRef.value.setOptions(chatData)
})
} else {
message.info('未查询到数据')
}
}
}
)
}
// 线-
const searchgetSalesman = () => {
if (searchObj.searchDate1.length == 0) {
message.warning('请选择日期')
return
}
if (!searchObj.channel1) {
message.warning('请选择渠道')
return
}
doRequest(
getSalesman({
createStartTime: dayjs(searchObj.searchDate1[0]).format('YYYY-MM-DD'),
createEndTime: dayjs(searchObj.searchDate1[1]).format('YYYY-MM-DD'),
channelType: searchObj.channel1
}),
{
onSuccess: (res: any) => {
let xAxisArr = []
const arr: any = []
if (res.data) {
xAxisArr = Object.keys(res.data)
const obj: any = {}
obj.data = Object.values(res.data)
obj.type = 'line'
obj.stack = 'Total'
obj.name = '分配数'
arr.push(obj)
const chatData: chartData = {
seriesArr: arr,
xAxisArr
}
clueNumChart.value = chatData
nextTick(() => {
clueNumRef.value.setOptions(chatData)
})
} else {
message.info('未查询到数据')
}
}
}
)
}
//
const exportChartData = (type: string, dateCode: string, channelCode: string) => {
if (searchObj[dateCode].length == 0) {
message.warning('请选择日期')
return
}
if (searchObj.enterIdList.length == 0 && type == 'enter') {
message.warning('请选择录入人员')
return
}
if (searchObj.assignedIdList.length == 0 && type == 'distribute') {
message.warning('请选择终端客户')
return
}
if (!searchObj[channelCode]) {
message.warning('请选择渠道')
return
}
getHomePageExport({
createStartTime: dayjs(searchObj[dateCode][0]).format('YYYY-MM-DD'),
createEndTime: dayjs(searchObj[dateCode][1]).format('YYYY-MM-DD'),
enterIdList: type == 'enter' ? searchObj.enterIdList : undefined,
assignedIdList: type == 'distribute' ? searchObj.assignedIdList : undefined,
channelType: searchObj[channelCode],
type: type == 'enter' ? 1 : 2
}).then((res: any) => {
remoteFileDownload(res)
})
// doRequest(
// getHomePageExport({
// createStartTime: dayjs(searchObj[dateCode][0]).format('YYYY-MM-DD'),
// createEndTime: dayjs(searchObj[dateCode][1]).format('YYYY-MM-DD'),
// enterIdList: type == 'enter' ? searchObj.enterIdList : undefined,
// assignedIdList: type == 'distribute' ? searchObj.assignedIdList : undefined,
// channelType: searchObj[channelCode],
// type: type == 'enter' ? 1 : 2
// }),
// {
// onSuccess: (res: any) => {
// console.log('🚀 ~ file: index.vue:244 ~ searchGetHomePageEnter ~ res:', res)
// remoteFileDownload(res)
// }
// }
// )
}
</script>
<style scoped>
/* .iframe {
width: 100%;
height: 100%;
border: 0;
overflow: hidden;
box-sizing: border-box;
display: block;
} */
.homeContent {
/* background-color: #fff;
width: 100%;
@ -74,4 +603,37 @@ const hideLoading = () => {
color: #5066e1;
margin-left: 20px;
}
.ant-btn-primary {
border-color: #246fdc;
color: #fff;
background-color: #246fdc;
}
.top-currency-title {
padding: 0 20px 12px;
border-bottom: 1px solid #e9e9e9;
/* height: 56px; */
}
.toolGroup {
padding: 15px 0 8px 15px;
}
.charTitle {
font-size: 17px;
font-weight: 600;
color: #000000;
font-family: PingFangSC-Medium, PingFang SC;
}
.ml-5 {
margin-left: 5px;
}
.block {
display: block;
}
.text-center {
text-align: center;
}
::v-deep .selectdrop .ant-select-dropdown-menu .ant-select-dropdown-menu-item {
white-space: normal;
word-break: break-all;
}
</style>

@ -195,11 +195,7 @@
show-time
/>
</a-form-item>
<a-form-item
v-if="userInfoCurrent !== 'ROLE_SALES_EXECUTIVE'"
label="API推送链接"
v-bind="validateInfos.fileRulePrefix"
>
<a-form-item label="API推送链接" v-bind="validateInfos.fileRulePrefix">
<a-input
v-model:value="formModel.fileRulePrefix"
placeholder="prezzz"

@ -8,7 +8,7 @@
<a-input v-model:value="formModel.taskName" placeholder="请输入" />
</a-form-item>
</a-col>
<!-- <a-col v-if="userInfoCurrent === 'ROLE_SALES_EXECUTIVE'" :xl="8" :md="12" :sm="24">
<!-- <a-col v-if="userInfoCurrent === 'ROLE_STORE_EXECUTIVE'" :xl="8" :md="12" :sm="24">
<a-form-item label="坐席名称">
<a-input v-model:value="formModel.taskName" placeholder="请输入" />
</a-form-item>

@ -8,7 +8,7 @@
<!-- 批量操作更多操作 -->
<a-card :bordered="false" :body-style="{ paddingBottom: 0 }">
<div class="download">
<a-button v-if="salesmanType === 0" @click.stop="downloadTemplate"></a-button>
<a-button @click.stop="downloadTemplate">导出</a-button>
</div>
</a-card>
<!-- 底部表格 -->
@ -54,12 +54,12 @@
</a-tooltip>
<span v-else>--</span>
</template>
<template v-else-if="column.key === 'remark'">
<a-tooltip v-if="record.remark">
<template v-else-if="column.key === 'customInformation'">
<a-tooltip v-if="record.customInformation">
<template #title
><span>{{ record.remark }}</span></template
><span>{{ record.customInformation }}</span></template
>
<span>{{ record.remark }}</span>
<span>{{ record.customInformation }}</span>
</a-tooltip>
<span v-else>--</span>
</template>
@ -118,14 +118,15 @@ onMounted(() => {
searchTable({ clueId: savedUserData })
localStorage.setItem('clueId', '')
}
if (salesmanType.value === 4) {
columns.value.splice(4, 0, {
title: '有效开关',
dataIndex: 'isEffective',
ellipsis: true,
align: 'center'
})
}
// if (salesmanType.value === 4) {
// columns.value.splice(4, 0, {
// title: '',
// dataIndex: 'isEffective',
// ellipsis: true,
// align: 'center',
// width: 150
// })
// }
// const customerId = route.query.clueId as string // 使
// if (customerId) {
// searchTable({ clueId: customerId })
@ -177,7 +178,6 @@ const handleView = (record: CustomerListRecord, tabIndex: string) => {
//
const handleEdit = (record: CustomerListRecord, tabIndex: string) => {
console.log('222')
customerListEditModalRef.value?.open(FormAction.UPDATE, record, tabIndex)
}
//
@ -264,10 +264,11 @@ const columns = ref<any[]>([
}
},
{
title: '备注',
dataIndex: 'remark',
title: '客户资料',
dataIndex: 'customInformation',
ellipsis: true,
align: 'center'
align: 'center',
width: 200
},
{
title: '线索日期',
@ -283,6 +284,13 @@ const columns = ref<any[]>([
}
}
},
{
title: '跟进业务员',
dataIndex: 'assignedName',
ellipsis: true,
align: 'center',
width: 200
},
{
title: '创建日期',
dataIndex: 'createTime',

@ -9,11 +9,31 @@
:width="650"
@cancel="handleClose"
>
<a-form :model="formModel" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item v-for="(item, index) in formModel.extraData" :key="index" :label="item.key">
{{ item.value }}
</a-form-item>
</a-form>
<div v-if="formModel">
<a-form :model="formModel" :label-col="labelCol" :wrapper-col="wrapperCol">
<a-form-item label="渠道名称">
{{ formModel.originName }}
</a-form-item>
<a-form-item label="渠道类型">
{{ statusComparison('channelType', formModel.channelType) }}
</a-form-item>
<a-form-item v-if="formModel.channelIdentifying!.length" label="渠道标识">
<a-tag
v-for="(item, index) in formModel.channelIdentifying"
:key="index"
color="blue"
style="margin-right: 5px"
>{{ item }}</a-tag
>
</a-form-item>
<a-form-item label="跟进员">
{{ formModel.assignedName }}
</a-form-item>
<a-form-item v-for="(item, index) in formModel!.extraData" :key="index" :label="item.key">
{{ item.value }}
</a-form-item>
</a-form>
</div>
<template #footer>
<a-button key="submit" type="primary" @click="handleSubmit"></a-button>
</template>
@ -25,7 +45,7 @@ import { reactive, ref } from 'vue'
import { useModal } from '@/hooks/modal'
import { useFormAction, FormAction } from '@/hooks/form'
import type { ColProps } from 'ant-design-vue'
import type { CustomerListRecord, detailForm } from '@/api/customermanagement/customerList/types'
import type { CustomerListRecord } from '@/api/customermanagement/customerList/types'
// import { pageAccessLogs } from '@/api/salesmanagement/labelRule'
// const activeKey = ref('1')
@ -41,9 +61,7 @@ const { formAction } = useFormAction()
const submitLoading = ref(false)
//
const formModel = reactive<detailForm>({
extraData: []
})
const formModel = ref<CustomerListRecord>()
//
const handleSubmit = () => {
@ -64,9 +82,46 @@ interface clueStageItem {
// const labelGroupReloadTable = () => {
// pageAccessLogs({ size: 10, page: 1 })
// }
const stateGroup = {
channelType: [
{
label: '手动创建',
value: 1
},
{
label: '文件上传',
value: 2
},
{
label: '飞鱼回传',
value: 3
},
{
label: '外呼接入',
value: 4
},
{
label: 'API回传',
value: 5
}
],
sex: [
{
label: '男',
value: 0
},
{
label: '女',
value: 1
}
]
}
//id
const resourcesId = ref<number>()
const statusComparison = (name: string, val: any) => {
return (stateGroup as any)[name].filter((item: any) => item.value == val)[0]?.label
}
defineExpose({
open(newFormAction: FormAction, record: CustomerListRecord, tabIndex: string) {
// activeKey.value = tabIndex
@ -75,14 +130,14 @@ defineExpose({
title.value = '详情'
resourcesId.value = record.clueId
// labelGroupReloadTable()
const data = JSON.parse(JSON.stringify(record))
if (record.otherClue) {
JSON.parse(record.otherClue)
formModel.extraData = []
for (const key in JSON.parse(record.otherClue)) {
formModel.extraData.push({ key: key, value: JSON.parse(record.otherClue)[key] })
data.extraData = []
for (const key in JSON.parse(data.otherClue)) {
data.extraData.push({ key: key, value: JSON.parse(record.otherClue)[key] })
}
}
formModel.value = data
formAction.value = newFormAction
}
})

@ -7,16 +7,6 @@
<a-input v-model:value="formModel.clueLabelName" placeholder="请输入" />
</a-form-item>
</a-col>
<!-- <a-col :xl="8" :md="12" :sm="24">
<a-form-item label="线索阶段">
<dict-select
v-model:value="formModel.userId"
dict-code="clue_stage"
allow-clear
placeholder="请选择"
/>
</a-form-item>
</a-col> -->
<!-- <a-col :xl="8" :md="12" :sm="24" > -->
<!-- <a-form-item label="标签"> -->
<dict-select
@ -38,6 +28,21 @@
<a-input v-model:value="formModel.nid" placeholder="请输入" />
</a-form-item>
</a-col>
<a-col v-if="salesmanType === 0" :xl="8" :md="12" :sm="24">
<a-form-item label="业务员">
<a-select
v-model:value="formModel.salesmanArray"
style="min-width: 180px"
allow-clear
mode="multiple"
placeholder="选择业务员"
:field-names="{ label: 'userName', value: 'userId' }"
:max-tag-count="1"
:options="salesmanList"
class="ml-5"
></a-select>
</a-form-item>
</a-col>
<a-col :xl="8" :md="12" :sm="24">
<a-form-item label="创建时间">
<a-range-picker
@ -64,7 +69,11 @@ import { Form } from 'ant-design-vue'
import dayjs from 'dayjs'
import type { Dayjs } from 'dayjs'
import type { CustomerListSearch } from '@/api/customermanagement/customerList/types'
import { onMounted } from 'vue'
import { useUserStore } from '@/stores/user-store'
import { doRequest } from '@/utils/axios/request'
import { getFindRoleSonUser } from '@/api/system/user/index'
const { userInfo } = useUserStore()
const useForm = Form.useForm
// label
@ -80,12 +89,15 @@ const props = withDefaults(
const emits = defineEmits<{
(e: 'search', params: Record<string, any>): void
}>()
const salesmanType = ref<number | undefined>()
const searchTimeValue = ref<[Dayjs, Dayjs]>()
// list
const salesmanList: any = ref([])
const formModel = reactive<CustomerListSearch>({
clueLabelName: '',
//线
userId: undefined,
salesmanArray: [],
//
httpStatus: undefined,
//
@ -95,7 +107,10 @@ const formModel = reactive<CustomerListSearch>({
})
const { resetFields } = useForm(formModel)
onMounted(() => {
salesmanType.value = userInfo?.salesmanType
initSalesman()
})
const search = () => {
const param = toRaw(formModel)
if (searchTimeValue.value && searchTimeValue.value.length == 2) {
@ -107,7 +122,13 @@ const search = () => {
}
emits('search', param)
}
const initSalesman = () => {
doRequest(getFindRoleSonUser(23), {
onSuccess: (res: any) => {
salesmanList.value = res.data
}
})
}
const reset = () => {
//
resetFields()

@ -27,7 +27,7 @@
<operation-group>
<!-- <a v-if="record.enrollStatus !== 2" @click="handleAudit(record)"></a> -->
<a v-if="record.enrollStatus !== 2" @click="handleEdit(record)"></a>
<a v-if="record.enrollStatus !== 2" @click="handleDistribute(record)"></a>
<!-- <a v-if="record.enrollStatus !== 2" @click="handleDistribute(record)"></a> -->
<span v-else>-</span>
</operation-group>
</template>
@ -116,6 +116,18 @@ const columns: ProColumns[] = [
title: '客户名称',
dataIndex: 'customName'
},
{
title: '分发类型',
dataIndex: 'customType',
width: 80,
customRender: ({ record }: any) => {
if (record.customType == 0) {
return h('div', '地理分发')
} else if (record.customType == 1) {
return h('div', '基础分发')
}
}
},
{
title: '联系方式',
dataIndex: 'customNid'

@ -5,27 +5,26 @@
:visible="visible"
:mask-closable="false"
:centered="true"
:body-style="{ padding: '0px 40px 8px' }"
:body-style="{
padding: '0px 40px 8px',
minHeight: '65vh',
maxHeight: '85vh',
overflowY: 'scroll'
}"
:get-container="() => $refs.refModal"
:confirm-loading="submitLoading"
:width="850"
@cancel="handleClose"
>
<a-tabs
<!-- <a-tabs
v-if="title === '新建预约'"
v-model:activeKey="activeKey"
centered
@change="tabsChange"
>
<a-tab-pane key="1" tab="A类型客户"> </a-tab-pane>
<a-tab-pane key="2" tab="B类型客户" force-render> </a-tab-pane>
</a-tabs>
<a-tabs v-else v-model:activeKey="activeKey" centered>
<a-tab-pane v-if="formModel.customType === 0" key="1" tab="A类型客户"> </a-tab-pane>
<a-tab-pane v-if="formModel.customType === 1" key="2" tab="B类型客户" force-render>
</a-tab-pane>
</a-tabs>
<a-tab-pane key="1" tab="基础分发"> </a-tab-pane>
<a-tab-pane key="2" tab="地理分发" force-render> </a-tab-pane>
</a-tabs> -->
<a-form
ref="formRef"
:model="formModel"
@ -37,24 +36,6 @@
: { sm: { span: 24 }, md: { span: 19 } }
"
>
<a-form-item
label="称呼"
name="customName"
:rules="[{ required: true, message: '请输入称呼', trigger: 'blur' }]"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 9 } }
: { sm: { span: 24 }, md: { span: 11 } }
"
>
<a-input
v-model:value="formModel.customName"
placeholder="请输入称呼"
style="width: 65%"
:readonly="title === '详情' || title === '回单'"
/>
</a-form-item>
<a-form-item
label="联系方式"
name="customNid"
@ -67,41 +48,99 @@
}
]"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 11 } }"
>
<a-input
v-model:value="formModel.customNid"
placeholder="请输入联系方式"
style="width: 65%"
:readonly="title === '详情' || title === '回单'"
/>
</a-form-item>
<a-form-item
label="备注"
name="remark"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 19 } }"
>
<a-textarea
v-model:value="formModel.remark"
placeholder="请输入备注"
:style="{ width: '100%' }"
/>
</a-form-item>
<a-tabs v-model:activeKey="activeKey" centered>
<a-tab-pane v-if="formModel.customType === 1" :key="1" tab="基础分发"> </a-tab-pane>
<a-tab-pane v-if="formModel.customType === 0" :key="0" tab="地理分发" force-render>
</a-tab-pane>
</a-tabs>
<a-form-item
label="称呼"
name="customName"
:rules="[{ required: true, message: '请输入称呼', trigger: 'blur' }]"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
title === '详情'
? { sm: { span: 24 }, md: { span: 9 } }
: { sm: { span: 24 }, md: { span: 11 } }
"
>
<a-input
v-model:value="formModel.customNid"
placeholder="请输入联系方式"
v-model:value="formModel.customName"
placeholder="请输入称呼"
style="width: 65%"
:readonly="title === '详情' || title === '回单'"
:readonly="title === '详情'"
/>
</a-form-item>
<a-row>
<a-col :span="24">
<a-form-item
label="备注"
name="remark"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 19 } }
: { sm: { span: 24 }, md: { span: 19 } }
"
>
<a-textarea
v-model:value="formModel.remark"
placeholder="请输入备注"
:style="{ width: title === '详情' || title === '回单' ? '83%' : '100%' }"
:readonly="title === '详情' || title === '回单'"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-form-item
label="性别"
name="sex"
:rules="[{ required: true, message: '请选择性别', trigger: 'blur' }]"
>
<a-select v-model:value="formModel.sex" :style="{ width: '38%' }">
<a-select-option :value="0"></a-select-option>
<a-select-option :value="1"></a-select-option>
</a-select>
</a-form-item>
<a-form-item label="客户资料" name="customInformation">
<a-textarea
v-model:value="formModel.customInformation"
placeholder="请输入客户资料"
style="width: 65%"
/>
</a-form-item>
<a-form-item v-if="activeKey === 1" label="您的所在城市" name="abbreviateAddress">
<a-cascader
v-model:value="formModel.abbreviateAddress"
change-on-select
style="position: relative; z-index: 2; margin-right: 20px; width: 65%"
:options="provincesAndCities"
placeholder="请选择"
:show-search="{ filter }"
:disabled="isAddressDisabled"
:class="addressDynamicClass"
class="readonly-cascader"
allow-clear
@change="addressChange"
/>
</a-form-item>
<a-form-item
v-if="activeKey === 1"
label="客户选择"
name="salesmanUserId"
:rules="[{ required: true, message: '请选择客户', trigger: 'blur' }]"
>
<a-select
v-model:value="formModel.salesmanUserId"
allow-clear
mode="multiple"
:max-tag-count="1"
:options="userList"
:field-names="{ label: 'userName', value: 'userId' }"
style="width: 65%"
></a-select>
</a-form-item>
<a-row v-if="activeKey === 0" :gutter="16">
<a-col :xl="14" :md="14" :sm="14">
<a-form-item
label="请输入您的地址信息"
@ -109,10 +148,7 @@
:wrapper-col="{ sm: { span: 24 }, md: { span: 15 } }"
:rules="[
{
required:
activeKey === '1' ||
(activeKey === '2' && title === '编辑') ||
(activeKey === '2' && title === '回单'),
required: activeKey === 0,
message: '请选择地址信息',
trigger: ['blur', 'change']
}
@ -138,10 +174,7 @@
<a-form-item
:rules="[
{
required:
activeKey === '1' ||
(activeKey === '2' && title === '编辑') ||
(activeKey === '2' && title === '回单'),
required: activeKey === 0,
message: '请输入小区名称',
trigger: 'change'
}
@ -171,15 +204,13 @@
</a-col>
</a-row>
<a-form-item
v-if="activeKey === 0"
label="请输入区域半径"
class="radius"
name="radius"
:rules="[
{
required:
activeKey === '1' ||
(activeKey === '2' && title === '编辑') ||
(activeKey === '2' && title === '回单'),
required: activeKey === 0 && title === '编辑',
message: '请选择区域半径',
trigger: 'blur'
}
@ -208,7 +239,7 @@
</div>
</a-form-item>
<a-form-item
v-if="title === '新建预约' || title === '编辑预约' || title === '编辑'"
v-if="title === '新建预约' || title === '编辑预约' || title === '编辑' && activeKey === 0"
style="display: flex; justify-content: center"
>
<!-- 地图 -->
@ -298,7 +329,7 @@
</div>
</a-form-item>
<!-- 门店预约信息表单 -->
<div v-if="formModel.customStoreEntities.length > 0">
<div v-if="activeKey === 0 && formModel.customStoreEntities.length > 0">
<div
v-for="(item, index) in formModel.customStoreEntities"
:key="index"
@ -318,7 +349,7 @@
: { sm: { span: 24 }, md: { span: 16 } }
"
:rules="{
required: activeKey === '1',
required: activeKey === 0,
message: '请输入预约门店名称',
trigger: 'change'
}"
@ -398,7 +429,7 @@
</div>
</a-form>
<template #footer>
<div v-if="title === '新建预约' || title === '编辑预约'">
<!-- <div v-if="title === '新建预约' || title === '编辑预约'">
<a-button @click="storeResetForm"></a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="showModal"
>报名</a-button
@ -410,30 +441,35 @@
@click="temporaryStorage"
>暂存</a-button
>
</div>
<a-button v-if="title === ''" type="primary" html-type="submit" @click="handleClose"
</div> -->
<!-- <a-button v-if="title === ''" type="primary" html-type="submit" @click="handleClose"
>确定</a-button
>
> -->
<div v-if="title === '编辑'">
<a-button @click="storeResetForm"></a-button>
<a-button @click="handleClose"></a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="distribute"
<a-button
type="primary"
html-type="submit"
style="margin-left: 10px"
@click="submitValidation"
>确定</a-button
>
</div>
<div v-if="title === '回单'">
<!-- <div v-if="title === '回单'">
<a-button @click="handleClose"></a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="distribute"
>回单</a-button
>
</div>
</div> -->
</template>
<!-- 报名审核信息确认弹窗 -->
<a-modal v-model:visible="registerVisible" title="确认信息" @ok="handleOk">
<p>您提交的表单信息为</p>
<p>称呼{{ formModel.customName }}</p>
<p>联系方式{{ formModel.customNid }}</p>
<div style="overflow-y: auto; max-height: 100px">
<p>备注{{ formModel.remark }}</p>
<div v-if="formModel.customType === 0" style="overflow-y: auto; max-height: 100px">
<p v-for="(item, index) in formModel.customStoreEntities" :key="index">
<span>{{ `报名的门店${index + 1}` }}{{ item.storeName }}</span>
<span>&nbsp;{{ item.reservationDate?.toString().split(' ')[0] }}</span>
@ -466,6 +502,7 @@ import type { SelectValue } from 'ant-design-vue/es/select'
import type { SelectProps } from 'ant-design-vue'
import type { Dayjs } from 'dayjs'
import 'dayjs/locale/zh-cn'
import { getfFindDirectSalesman } from '@/api/directResources/index'
import {
addCustomer,
updateCustomer,
@ -488,40 +525,38 @@ const userInfoCurrent = ref<string | undefined>('')
// required: true,
// trigger: 'change'
// }
//
const provincesAndCitiesAndAutonomousOptions: any = ref([])
//
const provincesAndCities: any = ref([])
onMounted(() => {
//
provincesAndCitiesAndAutonomousOptions.value = window.globalProvincesAndCitiesAndAutonomousRegions
provincesAndCitiesAndAutonomousOptions.value = JSON.parse(
JSON.stringify(window.globalProvincesAndCitiesAndAutonomousRegions)
)
//
// if (provincesAndCitiesAndAutonomousRegions) {
// const addressArray = JSON.parse(JSON.stringify(provincesAndCitiesAndAutonomousRegions))
// const arr: any[] = []
// addressArray.forEach((item: any) => {
// item.children.forEach((it: any) => {
// if (it.children) {
// delete it.children
// }
// })
// arr.push(item)
// })
// provincesAndCitiesAndAutonomousOptions.value = arr
// }
const arr: any[] = []
const addressArray = window.globalProvincesAndCitiesAndAutonomousRegions
addressArray.forEach((item: any) => {
item.children.forEach((it: any) => {
it.children && delete it.children
})
arr.push(item)
})
provincesAndCities.value = arr
//
userInfoCurrent.value = userInfo?.roleCodes?.toLocaleString()
})
//
let userList: any = []
// tab key
const activeKey = ref('')
const activeKey = ref<number>()
//tabs change
const tabsChange = (val: string) => {
const tabsChange = (val: number) => {
handleMapInit()
// formRef.value?.resetFields()
formRef.value?.clearValidate()
if (val === '1') {
formModel.customType = 0
} else {
formModel.customType = 1
}
formModel.customType = val
}
///
@ -558,9 +593,6 @@ const formRef = ref<FormInstance>()
// const city = ref<string | undefined>('')
// const cityAnddistinguish = ref<string | undefined>('')
//
const provincesAndCitiesAndAutonomousOptions: any = ref([])
//change
const addressChange = async (value: any) => {
// if (infoWindows.value) {
@ -609,9 +641,75 @@ const radiusChange = (value: SelectValue) => {
formModel.radius = value
}
const emits = defineEmits<{
(e: 'submit-success', resetPageIndex?: boolean): void
}>()
const { title, visible, openModal, closeModal } = useModal()
const { formAction } = useFormAction()
//
const formModel = reactive<CustomerDTO>({
customType: undefined,
customId: undefined,
customName: '',
customNid: '',
remark: '',
address: [],
abbreviateAddress: [], //
sex: 0,
customInformation: '',
economize: '',
market: '',
distinguish: '',
detailAddress: '',
otherAddressesInfo: '',
radius: '',
enrollStatus: 1,
customStoreEntities: [],
salesmanUserId: []
})
const formRule = ref<any>({
customName: [{ required: true, message: '请输入称呼', trigger: ['blur', 'change'] }],
customNid: [
{
required: true,
message: '请输入正确的手机号码',
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
trigger: ['blur', 'change']
}
],
address: [{ required: true, message: '请选择地址信息', trigger: ['blur', 'change'] }],
detailAddress: [{ required: true, message: '请输入小区名称', trigger: 'change' }],
radius: [{ required: true, message: '请选择区域半径', trigger: 'change' }]
})
//
const formRequestMapping: FormRequestMapping<CustomerDTO> = {
[FormAction.CREATE]: addCustomer,
[FormAction.UPDATE]: auditCustomer
}
// useAdminForm
const adminForm = useAdminForm(formAction, formRequestMapping, formModel, formRule)
// 使 toRefs
const { submitLoading, validateAndSubmit, resetFields, validateInfos } = toRefs(adminForm)
//
const handleSubmit = () => {
handleClose()
emits('submit-success')
}
//
const listData: any = ref([])
const initUserList = () => {
doRequest(getfFindDirectSalesman(23), {
onSuccess: (res: any) => {
userList = res.data
}
})
}
//()
const generateTimeSlots = (tradeStartTime: string, tradeEndTime: string) => {
const startHour = Number(tradeStartTime.split(':')[0])
@ -849,10 +947,8 @@ const getCenterMarkerAddress = () => {
result.includes(formModel.detailAddress) ||
pois[0].address.includes(formModel.detailAddress)
) {
console.log('1111')
accordingStorenameGetCenter(pois)
} else {
console.log('2222')
accordingAddressGetCenter()
}
} else {
@ -860,10 +956,8 @@ const getCenterMarkerAddress = () => {
formModel.detailAddress.includes(result) ||
formModel.detailAddress.includes(pois[0].address)
) {
console.log('3333')
accordingStorenameGetCenter(pois)
} else {
console.log('4444')
accordingAddressGetCenter()
}
}
@ -876,10 +970,8 @@ const getCenterMarkerAddress = () => {
pois[0].name.includes(formModel.detailAddress) ||
pois[0].address.includes(formModel.detailAddress)
) {
console.log('1111')
accordingStorenameGetCenter(pois)
} else {
console.log('2222')
accordingAddressGetCenter()
}
} else {
@ -887,10 +979,8 @@ const getCenterMarkerAddress = () => {
formModel.detailAddress.includes(pois[0].name) ||
formModel.detailAddress.includes(pois[0].address)
) {
console.log('3333')
accordingStorenameGetCenter(pois)
} else {
console.log('4444')
accordingAddressGetCenter()
}
}
@ -1047,7 +1137,6 @@ const idThen = (detailAddress: string) => {
if (status === 'complete' && result.info === 'OK') {
//
const pois = result.poiList.pois
console.log(pois, 'pois')
//
if (pois[0].name.includes('小区')) {
const result = pois[0].name.replace('小区', '')
@ -1059,10 +1148,8 @@ const idThen = (detailAddress: string) => {
result.includes(formModel.detailAddress) ||
pois[0].address.includes(formModel.detailAddress)
) {
console.log('1111')
accordingStorenameMatch(pois)
} else {
console.log('2222')
accordingAddressMatch()
}
} else {
@ -1070,10 +1157,8 @@ const idThen = (detailAddress: string) => {
formModel.detailAddress.includes(result) ||
formModel.detailAddress.includes(pois[0].address)
) {
console.log('3333')
accordingStorenameMatch(pois)
} else {
console.log('4444')
accordingAddressMatch()
}
}
@ -1086,10 +1171,8 @@ const idThen = (detailAddress: string) => {
pois[0].name.includes(formModel.detailAddress) ||
pois[0].address.includes(formModel.detailAddress)
) {
console.log('1111')
accordingStorenameMatch(pois)
} else {
console.log('2222')
accordingAddressMatch()
}
} else {
@ -1097,10 +1180,8 @@ const idThen = (detailAddress: string) => {
formModel.detailAddress.includes(pois[0].name) ||
formModel.detailAddress.includes(pois[0].address)
) {
console.log('3333')
accordingStorenameMatch(pois)
} else {
console.log('4444')
accordingAddressMatch()
}
}
@ -1121,7 +1202,7 @@ const idThen = (detailAddress: string) => {
}
//
const match = async (detailAddress: string) => {
if (activeKey.value === '1') {
if (activeKey.value === 0) {
if (title.value === '新建预约' && formModel.customStoreEntities.length !== 0) {
matchregisterVisible.value = true
} else {
@ -1213,6 +1294,9 @@ const storeResetForm = () => {
formModel.customName = ''
formModel.customNid = ''
formModel.remark = ''
formModel.customInformation = ''
formModel.salesmanUserId = []
formModel.abbreviateAddress = []
if (title.value === '详情' || title.value === '回单' || title.value === '新建预约') {
formModel.address = []
formModel.detailAddress = ''
@ -1233,7 +1317,8 @@ const showModal = () => {
formRef.value
?.validate()
.then(() => {
if (activeKey.value === '1') {
console.log('activeKey==', activeKey.value)
if (activeKey.value === 0) {
if (formModel.customStoreEntities.length === 0) {
message.info('请先添加预约门店')
} else {
@ -1295,6 +1380,9 @@ const submitOperate = () => {
}
if (title.value === '新建预约' || title.value === '编辑预约' || title.value === '编辑') {
if (title.value === '编辑') {
filteredObj.type = 2
}
const requestFn = title.value === '新建预约' ? addCustomer : updateCustomer
doRequest(requestFn(filteredObj), {
onSuccess: handleSuccess
@ -1347,11 +1435,25 @@ const temporaryStorage = async () => {
}
//
const distribute = () => {
// const distribute = () => {
// formRef.value
// ?.validate()
// .then(() => {
// if (formModel.customStoreEntities.length === 0) {
// message.info('')
// } else {
// registerVisible.value = true
// }
// })
// .catch(err => {
// console.log('err', err)
// })
// }
const submitValidation = () => {
formRef.value
?.validate()
.then(() => {
if (formModel.customStoreEntities.length === 0) {
if (formModel.customStoreEntities.length === 0 && activeKey.value == 0) {
message.info('请先添加预约门店')
} else {
registerVisible.value = true
@ -1362,64 +1464,6 @@ const distribute = () => {
})
}
const emits = defineEmits<{
(e: 'submit-success', resetPageIndex?: boolean): void
}>()
const { title, visible, openModal, closeModal } = useModal()
const { formAction } = useFormAction()
//
const formModel = reactive<CustomerDTO>({
customType: undefined,
customId: undefined,
customName: '',
customNid: '',
remark: '',
address: [],
economize: '',
market: '',
distinguish: '',
detailAddress: '',
otherAddressesInfo: '',
radius: '',
enrollStatus: 1,
customStoreEntities: []
})
const formRule = ref<any>({
customName: [{ required: true, message: '请输入称呼', trigger: ['blur', 'change'] }],
customNid: [
{
required: true,
message: '请输入正确的手机号码',
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
trigger: ['blur', 'change']
}
],
address: [{ required: true, message: '请选择地址信息', trigger: ['blur', 'change'] }],
detailAddress: [{ required: true, message: '请输入小区名称', trigger: 'change' }],
radius: [{ required: true, message: '请选择区域半径', trigger: 'change' }]
})
//
const formRequestMapping: FormRequestMapping<CustomerDTO> = {
[FormAction.CREATE]: addCustomer,
[FormAction.UPDATE]: auditCustomer
}
// useAdminForm
const adminForm = useAdminForm(formAction, formRequestMapping, formModel, formRule)
// 使 toRefs
const { submitLoading, validateAndSubmit, resetFields, validateInfos } = toRefs(adminForm)
//
const handleSubmit = () => {
handleClose()
emits('submit-success')
}
//
const handleClose = () => {
// activeKey.value = '1'
@ -1491,15 +1535,22 @@ defineExpose({
otherAddressesInfo,
radius,
customStoreVOList,
customType
customType,
customInformation,
salesmanUserId
} = data
formModel.customId = customId
formModel.customName = customName
formModel.customNid = customNid
formModel.remark = remark
formModel.customInformation = customInformation || remark
if (economize) {
formModel.address = [economize, market, distinguish]
if (customType == 0) {
formModel.address = [economize, market, distinguish]
} else if (customType == 1) {
formModel.abbreviateAddress = [economize, market]
}
} else {
formModel.address = []
}
@ -1511,6 +1562,7 @@ defineExpose({
formModel.customType = customType
formModel.otherAddressesInfo = otherAddressesInfo
formModel.salesmanUserId = salesmanUserId
formModel.radius = radius
formModel.customStoreEntities.push(...customStoreVOList)
//
@ -1518,29 +1570,19 @@ defineExpose({
i.option = generateTimeSlots(i.tradeStartTime, i.tradeEndTime)
})
const getActiveKey = () => {
if (formModel.customType === 0) {
activeKey.value = '1'
} else {
activeKey.value = '2'
}
activeKey.value = formModel.customType
}
if (opendata.type === 'audit') {
getActiveKey()
title.value = '编辑'
// if (formModel.address.length !== 0) {
// isAddressDisabled.value = true
// }
// if (formModel.radius) {
// isRadiusDisabled.value = true
// }
// if (formModel.detailAddress) {
// isDetailAddressDisabled.value = true
// }
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
activeKey.value = formModel.customType || 0
if (activeKey.value == 0) {
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
}
} else if (opendata.type === 'edit') {
getActiveKey()
title.value = '编辑预约'
@ -1553,42 +1595,37 @@ defineExpose({
if (formModel.detailAddress) {
isDetailAddressDisabled.value = true
}
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
} else if (opendata.type === 'view') {
if (formModel.customType === 0) {
activeKey.value = '1'
} else {
activeKey.value = '2'
activeKey.value = formModel.customType || 0
if (activeKey.value == 0) {
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
}
} else if (opendata.type === 'view') {
activeKey.value = formModel.customType
title.value = '详情'
isAddressReadOnly.value = true
isRadiusReadOnly.value = true
isDetailAddressReadOnly.value = true
isReservationTimeisReadOnly.value = true
} else if (opendata.type === 'distribute') {
getActiveKey()
title.value = '回单'
isAddressReadOnly.value = true
isRadiusReadOnly.value = true
isDetailAddressReadOnly.value = true
isReservationTimeisReadOnly.value = true
formModel.description = 1
}
if (activeKey.value == 1) {
initUserList()
}
openModal()
}
if (opendata.newFormAction === FormAction.CREATE) {
activeKey.value = '1'
handleMapInit()
title.value = '新建预约'
formModel.customStoreEntities.length = 0
formModel.customType = 0
openModal()
} else if (opendata.newFormAction === FormAction.UPDATE) {
// if (opendata.newFormAction === FormAction.CREATE) {
// activeKey.value = '1'
// handleMapInit()
// title.value = ''
// formModel.customStoreEntities.length = 0
// formModel.customType = 0
// openModal()
// } else
if (opendata.newFormAction === FormAction.UPDATE) {
doRequest(getDetail({ id: opendata.record?.customId }), {
onSuccess: handleSuccess
})

@ -80,6 +80,7 @@ import { projectTitle, projectDesc, enableLoginCaptcha } from '@/config'
import { SliderCaptcha as LoginCaptcha } from '@/components/Captcha'
import { useI18n } from 'vue-i18n'
import { getCodeData } from '@/api/auth'
import { queryUserScope } from '@/api/system/user/index'
// import useAdminWebSocket from '@/hooks/websocket'
const { t } = useI18n()
@ -136,7 +137,10 @@ function store(res: LoginResult) {
roleCodes,
permissions
}
//
queryUserScope(info.userId).then(result => {
userStore.roleCodes = result.data.roleCodes
})
// TODO
// const ttl = res.expires_in * 1000
// const refreshToken = res.refresh_token
@ -172,7 +176,6 @@ function handleSubmit(captchaId?: string) {
store(res)
const nextPath = (router.currentRoute.value.query.redirect as string) || '/'
router.push(nextPath)
// WebSocket
// const webSocket =
// useAdminWebSocket()

@ -20,7 +20,11 @@
<template v-if="column.key === 'operate'">
<operation-group>
<a @click="handleView(record.customId)"></a>
<a v-if="record.enrollStatus == 1" @click="handleEditView(record)"></a>
<a
v-if="record.enrollStatus == 0 || record.enrollStatus == 1"
@click="handleEditView(record)"
>审核</a
>
</operation-group>
</template>
</template>
@ -110,14 +114,14 @@ const columns: ProColumns[] = [
dataIndex: 'customName'
},
{
title: '客户类型',
title: '分发类型',
dataIndex: 'customType',
width: 80,
customRender: ({ record }: any) => {
if (record.customType == 0) {
return h('div', 'A型')
return h('div', '地理分发')
} else if (record.customType == 1) {
return h('div', 'B型')
return h('div', '基础分发')
}
}
},

@ -5,56 +5,30 @@
:visible="visible"
:mask-closable="false"
:centered="true"
:body-style="{ padding: '0px 40px 8px' }"
:body-style="{
padding: '0px 40px 8px',
minHeight: '65vh',
maxHeight: '85vh',
overflowY: 'scroll'
}"
:get-container="() => $refs.refModal"
:confirm-loading="submitLoading"
:width="850"
@cancel="handleClose"
>
<a-tabs
v-if="title === '新建预约'"
v-model:activeKey="activeKey"
centered
@change="tabsChange"
>
<a-tab-pane key="1" tab="A类型客户"> </a-tab-pane>
<a-tab-pane key="2" tab="B类型客户" force-render> </a-tab-pane>
</a-tabs>
<a-tabs v-else v-model:activeKey="activeKey" centered>
<a-tab-pane v-if="formModel.customType === 0" key="1" tab="A类型客户"> </a-tab-pane>
<a-tab-pane v-if="formModel.customType === 1" key="2" tab="B类型客户" force-render>
</a-tab-pane>
</a-tabs>
<!-- <div class="u-flex">
<label class="a-label">手机号</label>
<div class="a-input">
<a-input v-model:value="customNid" placeholder="" />
</div>
</div> -->
<a-form
ref="formRef"
:model="formModel"
:rule="formRule"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 16 } }
: { sm: { span: 24 }, md: { span: 19 } }
"
:wrapper-col="{ sm: { span: 24 }, md: { span: 19 } }"
>
<a-form-item
label="称呼"
name="customName"
:rules="[{ required: true, message: '请输入称呼', trigger: 'blur' }]"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 9 } }
: { sm: { span: 24 }, md: { span: 11 } }
"
>
<a-input
v-model:value="formModel.customName"
placeholder="请输入称呼"
style="width: 65%"
:readonly="title === '详情' || title === '回单'"
/>
</a-form-item>
<a-form-item
label="联系方式"
name="customNid"
@ -67,52 +41,101 @@
}
]"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 9 } }
: { sm: { span: 24 }, md: { span: 11 } }
"
:wrapper-col="{ sm: { span: 24 }, md: { span: 11 } }"
>
<a-input
v-model:value="formModel.customNid"
placeholder="请输入联系方式"
style="width: 65%"
:readonly="title === '详情' || title === '回单'"
:readonly="title === '详情'"
/>
</a-form-item>
<a-row>
<a-col :span="24">
<a-form-item
label="备注"
name="remark"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 19 } }
: { sm: { span: 24 }, md: { span: 19 } }
"
>
<a-textarea
v-model:value="formModel.remark"
placeholder="请输入备注"
:style="{ width: title === '详情' || title === '回单' ? '83%' : '100%' }"
:readonly="title === '详情' || title === '回单'"
/>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="16">
<a-form-item
label="备注"
name="remark"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 19 } }"
>
<a-textarea
v-model:value="formModel.remark"
placeholder="请输入备注"
:style="{ width: '100%' }"
/>
</a-form-item>
<a-tabs v-model:activeKey="activeKey" centered @change="tabsChange">
<a-tab-pane :key="1" tab="基础分发"> </a-tab-pane>
<a-tab-pane :key="0" tab="地理分发" force-render> </a-tab-pane>
</a-tabs>
<a-form-item
label="称呼"
name="customName"
:rules="[{ required: true, message: '请输入称呼', trigger: 'blur' }]"
:label-col="{ sm: { span: 24 }, md: { span: 5 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 11 } }"
>
<a-input
v-model:value="formModel.customName"
placeholder="请输入称呼"
style="width: 65%"
/>
</a-form-item>
<a-form-item
label="性别"
name="sex"
:rules="[{ required: true, message: '请选择性别', trigger: 'blur' }]"
>
<a-select v-model:value="formModel.sex" :style="{ width: '38%' }">
<a-select-option :value="0"></a-select-option>
<a-select-option :value="1"></a-select-option>
</a-select>
</a-form-item>
<a-form-item label="客户资料" name="customInformation">
<a-textarea
v-model:value="formModel.customInformation"
placeholder="请输入客户资料"
style="width: 65%"
/>
</a-form-item>
<a-form-item v-if="activeKey === 1" label="您的所在城市">
<a-cascader
v-model:value="formModel.abbreviateAddress"
change-on-select
style="position: relative; z-index: 2; margin-right: 20px; width: 65%"
:options="provincesAndCities"
placeholder="请选择"
:show-search="{ filter }"
:disabled="isAddressDisabled"
:class="addressDynamicClass"
class="readonly-cascader"
allow-clear
@change="addressChange"
/>
</a-form-item>
<a-form-item
v-if="activeKey === 1"
label="客户选择"
name="salesmanUserId"
:rules="[{ required: true, message: '请选择客户', trigger: 'blur' }]"
>
<a-select
v-model:value="formModel.salesmanUserId"
allow-clear
mode="multiple"
:max-tag-count="1"
:options="userList"
:field-names="{ label: 'userName', value: 'userId' }"
style="width: 65%"
></a-select>
</a-form-item>
<a-row v-if="activeKey === 0" :gutter="16">
<a-col :xl="14" :md="14" :sm="14">
<a-form-item
label="请输入您的地址信息"
label="您的地址信息"
:label-col="{ sm: { span: 24 }, md: { span: 9 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 15 } }"
:rules="[
{
required:
activeKey === '1' ||
(activeKey === '2' && title === '编辑') ||
(activeKey === '2' && title === '回单'),
required: true,
message: '请选择地址信息',
trigger: ['blur', 'change']
}
@ -138,10 +161,7 @@
<a-form-item
:rules="[
{
required:
activeKey === '1' ||
(activeKey === '2' && title === '编辑') ||
(activeKey === '2' && title === '回单'),
required: true,
message: '请输入小区名称',
trigger: 'change'
}
@ -171,15 +191,13 @@
</a-col>
</a-row>
<a-form-item
v-if="activeKey === 0"
label="请输入区域半径"
class="radius"
name="radius"
:rules="[
{
required:
activeKey === '1' ||
(activeKey === '2' && title === '编辑') ||
(activeKey === '2' && title === '回单'),
required: true,
message: '请选择区域半径',
trigger: 'blur'
}
@ -188,7 +206,7 @@
<a-select
ref="select"
v-model:value="formModel.radius"
:style="{ width: title === '详情' || title === '回单' ? '37%' : '38%' }"
:style="{ width: title === '详情' ? '37%' : '38%' }"
:options="radiusOptions"
:field-names="{ label: 'name', value: 'id', options: 'children' }"
:disabled="isRadiusDisabled"
@ -207,10 +225,7 @@
>
</div>
</a-form-item>
<a-form-item
v-if="title === '新建预约' || title === '编辑预约' || title === '编辑'"
style="display: flex; justify-content: center"
>
<a-form-item v-if="activeKey === 0" style="display: flex; justify-content: center">
<!-- 地图 -->
<div class="clueImport-page">
<div class="drawStation">
@ -298,7 +313,7 @@
</div>
</a-form-item>
<!-- 门店预约信息表单 -->
<div v-if="formModel.customStoreEntities.length > 0">
<div v-if="activeKey === 0 && formModel.customStoreEntities.length > 0">
<div
v-for="(item, index) in formModel.customStoreEntities"
:key="index"
@ -308,17 +323,17 @@
style="width: 45%"
label="预约门店名称"
:label-col="
title === '详情' || title === '回单'
title === '详情'
? { sm: { span: 24 }, md: { span: 11 } }
: { sm: { span: 24 }, md: { span: 8 } }
"
:wrapper-col="
title === '详情' || title === '回单'
title === '详情'
? { sm: { span: 24 }, md: { span: 13 } }
: { sm: { span: 24 }, md: { span: 16 } }
"
:rules="{
required: activeKey === '1',
required: true,
message: '请输入预约门店名称',
trigger: 'change'
}"
@ -327,8 +342,8 @@
<a-input
v-model:value="item.storeName"
placeholder="请输入"
:readonly="title === '详情' || title === '回单'"
:style="{ width: title === '详情' || title === '回单' ? '103%' : '100%' }"
:readonly="title === '详情'"
:style="{ width: title === '详情' ? '103%' : '100%' }"
/>
</a-form-item>
<!-- :rules="{
@ -339,23 +354,15 @@
<a-form-item
style="width: 30%"
label="预约时间"
:label-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 9 } }
: { sm: { span: 24 }, md: { span: 9 } }
"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 15 } }
: { sm: { span: 24 }, md: { span: 15 } }
"
:label-col="{ sm: { span: 24 }, md: { span: 9 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 15 } }"
:name="['customStoreEntities', index, 'reservationDate']"
>
<a-space direction="vertical">
<a-date-picker
v-model:value="item.reservationDate"
value-format="YYYY-MM-DD HH:mm:ss"
:disabled="title === '详情' || title === '回单'"
:disabled="title === '详情'"
:class="reservationTimeClass"
/>
</a-space>
@ -367,16 +374,8 @@
}" -->
<a-form-item
style="width: 18%"
:label-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 0 } }
: { sm: { span: 24 }, md: { span: 0 } }
"
:wrapper-col="
title === '详情' || title === '回单'
? { sm: { span: 24 }, md: { span: 24 } }
: { sm: { span: 24 }, md: { span: 24 } }
"
:label-col="{ sm: { span: 24 }, md: { span: 0 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 24 } }"
:name="['customStoreEntities', index, 'reservationTime']"
>
<a-space style="width: 100%">
@ -386,7 +385,7 @@
:allow-clear="title === '新建预约' || title === '编辑预约' || title === '编辑'"
:options="item.option"
:class="reservationTimeClass"
:style="{ width: title === '详情' || title === '回单' ? '103%' : '100%' }"
:style="{ width: title === '详情' ? '103%' : '100%' }"
>
</a-select>
</a-space>
@ -398,42 +397,31 @@
</div>
</a-form>
<template #footer>
<div v-if="title === '新建预约' || title === '编辑预约'">
<a-button @click="storeResetForm"></a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="showModal"
>报名</a-button
>
<a-button
type="primary"
html-type="submit"
style="margin-left: 10px"
@click="temporaryStorage"
>暂存</a-button
>
</div>
<a-button v-if="title === ''" type="primary" html-type="submit" @click="handleClose"
>确定</a-button
>
<div v-if="title === '编辑'">
<a-button @click="storeResetForm"></a-button>
<a-button @click="handleClose"></a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="distribute"
<a-button
type="primary"
html-type="submit"
style="margin-left: 10px"
@click="temporaryStorage"
>暂存
</a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="showModal"
>分发</a-button
>
</div>
<div v-if="title === '回单'">
<a-button @click="handleClose"></a-button>
<a-button type="primary" html-type="submit" style="margin-left: 10px" @click="distribute"
>回单</a-button
>
</div>
</template>
<!-- 报名审核信息确认弹窗 -->
<a-modal v-model:visible="registerVisible" title="确认分发信息" ok-text="" @ok="handleOk">
<p>您提交的表单信息为</p>
<p>称呼{{ formModel.customName }}</p>
<p>联系方式{{ formModel.customNid }}</p>
<div style="overflow-y: auto; max-height: 100px">
<p>备注{{ formModel.remark }}</p>
<div v-if="formModel.customType === 0" style="overflow-y: auto; max-height: 100px">
<p v-for="(item, index) in formModel.customStoreEntities" :key="index">
<span>{{ `报名的门店${index + 1}` }}{{ item.storeName }}</span>
<span>&nbsp;{{ item.reservationDate?.toString().split(' ')[0] }}</span>
@ -475,53 +463,98 @@ import {
getStoreData
} from '@/api/geopoliticalCustomers'
import type { CustomerDTO, GeopoliticalCustomersRecord } from '@/api/geopoliticalCustomers/types'
import { getfFindDirectSalesman } from '@/api/directResources/index'
import axios from 'axios'
//
import { useUserStore } from '@/stores/user-store'
const { userInfo } = useUserStore()
const userInfoCurrent = ref<string | undefined>('')
//
// import { provincesAndCitiesAndAutonomousRegions } from '@/utils/geopolitical-customers'
interface customStoreEntitiesItem {
//id
customStoreId?: number
//id
storeId: number
//
storeName?: string
//
reservationDate?: Dayjs | string
//
reservationTime: string
}
//dom:rules = 'rulesData'
// const rulesData = {
// required: true,
// trigger: 'change'
// }
const emits = defineEmits<{
(e: 'submit-success', resetPageIndex?: boolean): void
}>()
const { title, visible, openModal, closeModal } = useModal()
onMounted(() => {
//
provincesAndCitiesAndAutonomousOptions.value = window.globalProvincesAndCitiesAndAutonomousRegions
//
// if (provincesAndCitiesAndAutonomousRegions) {
// const addressArray = JSON.parse(JSON.stringify(provincesAndCitiesAndAutonomousRegions))
// const arr: any[] = []
// addressArray.forEach((item: any) => {
// item.children.forEach((it: any) => {
// if (it.children) {
// delete it.children
// }
// })
// arr.push(item)
// })
// provincesAndCitiesAndAutonomousOptions.value = arr
// }
//
userInfoCurrent.value = userInfo?.roleCodes?.toLocaleString()
const { formAction } = useFormAction()
//
const formModel = reactive<CustomerDTO>({
customType: undefined,
customId: undefined,
customName: '',
customNid: '',
remark: '',
address: [], //
abbreviateAddress: [], //
sex: 0,
customInformation: '',
economize: '',
market: '',
distinguish: '',
detailAddress: '',
otherAddressesInfo: '',
radius: '',
enrollStatus: 1,
customStoreEntities: [],
salesmanUserId: []
})
const formRule = ref<any>({
customName: [{ required: true, message: '请输入称呼', trigger: ['blur', 'change'] }],
customNid: [
{
required: true,
message: '请输入正确的手机号码',
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
trigger: ['blur', 'change']
}
],
address: [{ required: true, message: '请选择地址信息', trigger: ['blur', 'change'] }],
detailAddress: [{ required: true, message: '请输入小区名称', trigger: 'change' }],
radius: [{ required: true, message: '请选择区域半径', trigger: 'change' }]
})
//
const formRequestMapping: FormRequestMapping<CustomerDTO> = {
[FormAction.CREATE]: addCustomer,
[FormAction.UPDATE]: auditCustomer
}
// useAdminForm
const adminForm = useAdminForm(formAction, formRequestMapping, formModel, formRule)
// 使 toRefs
const { submitLoading, validateAndSubmit, resetFields, validateInfos } = toRefs(adminForm)
//,
const isSubmit = ref(false)
// tab key
const activeKey = ref('')
const activeKey = ref<number | undefined>(1)
//tabs change
const tabsChange = (val: string) => {
handleMapInit()
const tabsChange = (val: number) => {
// formRef.value?.resetFields()
formRef.value?.clearValidate()
if (val === '1') {
formModel.customType = 0
} else {
formModel.customType = 1
formModel.customType = val
// formModel.address = []
// formModel.detailAddress = ''
if (val === 0) {
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
}
}
@ -562,6 +595,8 @@ const formRef = ref<FormInstance>()
//
const provincesAndCitiesAndAutonomousOptions: any = ref([])
//
const provincesAndCities: any = ref([])
//change
const addressChange = async (value: any) => {
// if (infoWindows.value) {
@ -609,10 +644,36 @@ const radiusOptions = ref<SelectProps['options']>([
const radiusChange = (value: SelectValue) => {
formModel.radius = value
}
//
let userList: any = []
//
const listData: any = ref([])
onMounted(() => {
//
provincesAndCitiesAndAutonomousOptions.value = window.globalProvincesAndCitiesAndAutonomousRegions
//
const arr: any[] = []
const addressArray = JSON.parse(
JSON.stringify(window.globalProvincesAndCitiesAndAutonomousRegions)
)
addressArray.forEach((item: any) => {
item.children.forEach((it: any) => {
it.children && delete it.children
})
arr.push(item)
})
provincesAndCities.value = arr
//
userInfoCurrent.value = userInfo?.roleCodes?.toLocaleString()
})
const initUserList = () => {
doRequest(getfFindDirectSalesman(23), {
onSuccess: (res: any) => {
userList = res.data
}
})
}
//()
const generateTimeSlots = (tradeStartTime: string, tradeEndTime: string) => {
const startHour = Number(tradeStartTime.split(':')[0])
@ -893,7 +954,6 @@ const getCenterMarkerAddress = () => {
}
})
}
//
const lng = ref<number | undefined>()
const lat = ref<number | undefined>()
@ -1105,7 +1165,7 @@ const idThen = (detailAddress: string) => {
}
//
const match = async (detailAddress: string) => {
if (activeKey.value === '1') {
if (activeKey.value === 0) {
if (title.value === '新建预约' && formModel.customStoreEntities.length !== 0) {
matchregisterVisible.value = true
} else {
@ -1121,9 +1181,7 @@ const match = async (detailAddress: string) => {
})
}
} else {
if (title.value === '新建预约' && formModel.customStoreEntities.length !== 0) {
matchregisterVisible.value = true
} else if (title.value === '编辑') {
if (title.value === '编辑') {
const fields = ['address', 'detailAddress', 'radius'] //
formRef.value
?.validateFields(fields)
@ -1197,7 +1255,10 @@ const storeResetForm = () => {
formModel.customName = ''
formModel.customNid = ''
formModel.remark = ''
if (title.value === '详情' || title.value === '回单' || title.value === '新建预约') {
formModel.customInformation = ''
formModel.salesmanUserId = []
formModel.abbreviateAddress = []
if (formModel.customType == 0) {
formModel.address = []
formModel.detailAddress = ''
formModel.radius = '5000'
@ -1217,7 +1278,7 @@ const showModal = () => {
formRef.value
?.validate()
.then(() => {
if (activeKey.value === '1') {
if (activeKey.value === 0) {
if (formModel.customStoreEntities.length === 0) {
message.info('请先添加预约门店')
} else {
@ -1233,20 +1294,7 @@ const showModal = () => {
console.log('校验失败err', err)
})
}
interface customStoreEntitiesItem {
//id
customStoreId?: number
//id
storeId: number
//
storeName?: string
//
reservationDate?: Dayjs | string
//
reservationTime: string
}
//,
const isSubmit = ref(false)
//
const submitOperate = () => {
//address
@ -1271,10 +1319,16 @@ const submitOperate = () => {
)
const handleSuccess = (res: any) => {
//
if (res.code === 200) {
console.log("🚀 ~ file: inspectionModal.vue:1323 ~ handleSuccess ~ formModel.enrollStatus:", formModel.enrollStatus)
if (res.code === 200 && formModel.enrollStatus != 0) {
message.success('保存成功')
isSubmit.value = true
updateCustomerAudit(formModel.customId as number, 1, userInfo!.salesmanType).then(res => {
updateCustomerAudit({
customId: formModel.customId as number,
status: formModel.customType as number,
salesmanType: userInfo!.salesmanType,
salesmanUserId: formModel.salesmanUserId
}).then(res => {
if (res.code == 200) {
handleSubmit()
registerVisible.value = false
@ -1285,6 +1339,9 @@ const submitOperate = () => {
})
}
})
} else {
handleSubmit()
message.success('操作成功')
}
}
@ -1294,11 +1351,6 @@ const submitOperate = () => {
onSuccess: handleSuccess
})
}
// else if (title.value === '') {
// doRequest(auditCustomer({ customId: formModel.customId, status: 1 }), {
// onSuccess: handleSuccess
// })
// }
}
//
@ -1342,74 +1394,6 @@ const temporaryStorage = async () => {
})
}
//
const distribute = () => {
formRef.value
?.validate()
.then(() => {
if (formModel.customStoreEntities.length === 0) {
message.info('请先添加预约门店')
} else {
registerVisible.value = true
}
})
.catch(err => {
console.log('校验失败err', err)
})
}
const emits = defineEmits<{
(e: 'submit-success', resetPageIndex?: boolean): void
}>()
const { title, visible, openModal, closeModal } = useModal()
const { formAction } = useFormAction()
//
const formModel = reactive<CustomerDTO>({
customType: undefined,
customId: undefined,
customName: '',
customNid: '',
remark: '',
address: [],
economize: '',
market: '',
distinguish: '',
detailAddress: '',
otherAddressesInfo: '',
radius: '',
enrollStatus: 1,
customStoreEntities: []
})
const formRule = ref<any>({
customName: [{ required: true, message: '请输入称呼', trigger: ['blur', 'change'] }],
customNid: [
{
required: true,
message: '请输入正确的手机号码',
pattern: /^1[3|4|5|6|7|8|9][0-9]\d{8}$/,
trigger: ['blur', 'change']
}
],
address: [{ required: true, message: '请选择地址信息', trigger: ['blur', 'change'] }],
detailAddress: [{ required: true, message: '请输入小区名称', trigger: 'change' }],
radius: [{ required: true, message: '请选择区域半径', trigger: 'change' }]
})
//
const formRequestMapping: FormRequestMapping<CustomerDTO> = {
[FormAction.CREATE]: addCustomer,
[FormAction.UPDATE]: auditCustomer
}
// useAdminForm
const adminForm = useAdminForm(formAction, formRequestMapping, formModel, formRule)
// 使 toRefs
const { submitLoading, validateAndSubmit, resetFields, validateInfos } = toRefs(adminForm)
//
const handleSubmit = () => {
handleClose()
@ -1462,17 +1446,7 @@ const handleMapInit = async () => {
defineExpose({
open(opendata: openObj) {
isSubmit.value = false
// console.log('formModel.customType resssssssss', formModel.customType)
//resetFields.value(),resetFields.value()formModel.customType0
// resetFields.value()
// formModel.customType = undefined
formModel.customStoreEntities = []
// console.log('formModel.customType ddddddddddd', formModel.customType)
// if (userInfoCurrent.value === 'ROLE_REVIEWER') {
// formModel.customType = 1
// } else if (userInfoCurrent.value === 'ROLE_PRELIMINARY_EXAMINER') {
// formModel.customType = 0
// }
const handleSuccess = (res: any) => {
const data = res.data || {}
const {
@ -1487,15 +1461,22 @@ defineExpose({
otherAddressesInfo,
radius,
customStoreVOList,
customType
customType,
salesmanUserId,
customInformation
} = data
formModel.customId = customId
formModel.customName = customName
formModel.customNid = customNid
formModel.remark = remark
formModel.customInformation = customInformation || remark
if (economize) {
formModel.address = [economize, market, distinguish]
if (customType == 0) {
formModel.address = [economize, market, distinguish]
} else if (customType == 1) {
formModel.abbreviateAddress = [economize, market]
}
} else {
formModel.address = []
}
@ -1505,7 +1486,7 @@ defineExpose({
formModel.distinguish = distinguish
formModel.detailAddress = detailAddress
formModel.customType = customType
formModel.salesmanUserId = salesmanUserId
formModel.otherAddressesInfo = otherAddressesInfo
formModel.radius = radius
formModel.customStoreEntities.push(...customStoreVOList)
@ -1513,67 +1494,36 @@ defineExpose({
formModel.customStoreEntities.forEach((i: any) => {
i.option = generateTimeSlots(i.tradeStartTime, i.tradeEndTime)
})
const getActiveKey = () => {
if (formModel.customType === 0) {
activeKey.value = '1'
} else {
activeKey.value = '2'
}
}
if (opendata.type === 'audit') {
getActiveKey()
title.value = '编辑'
// if (formModel.address.length !== 0) {
// isAddressDisabled.value = true
// }
// if (formModel.radius) {
// isRadiusDisabled.value = true
// }
// if (formModel.detailAddress) {
// isDetailAddressDisabled.value = true
// }
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
} else if (opendata.type === 'edit') {
getActiveKey()
title.value = '编辑预约'
if (formModel.address.length !== 0) {
isAddressDisabled.value = true
}
if (formModel.radius) {
isRadiusDisabled.value = true
}
if (formModel.detailAddress) {
isDetailAddressDisabled.value = true
}
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
} else if (opendata.type === 'view') {
if (formModel.customType === 0) {
activeKey.value = '1'
} else {
activeKey.value = '2'
activeKey.value = formModel.customType || 0
if (activeKey.value === 0) {
handleMapInit().then(() => {
if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
match(formModel.detailAddress)
}
})
}
title.value = '详情'
isAddressReadOnly.value = true
isRadiusReadOnly.value = true
isDetailAddressReadOnly.value = true
isReservationTimeisReadOnly.value = true
} else if (opendata.type === 'distribute') {
getActiveKey()
title.value = '回单'
isAddressReadOnly.value = true
isRadiusReadOnly.value = true
isDetailAddressReadOnly.value = true
isReservationTimeisReadOnly.value = true
formModel.description = 1
title.value = '编辑'
}
// else if (opendata.type === 'edit') {
// console.log('2222222222')
// getActiveKey()
// title.value = ''
// if (formModel.address.length !== 0) {
// isAddressDisabled.value = true
// }
// if (formModel.radius) {
// isRadiusDisabled.value = true
// }
// if (formModel.detailAddress) {
// isDetailAddressDisabled.value = true
// }
// handleMapInit().then(() => {
// if (formModel.address?.length !== 0 && formModel.detailAddress && formModel.radius) {
// match(formModel.detailAddress)
// }
// })
// }
openModal()
}
@ -1581,6 +1531,7 @@ defineExpose({
doRequest(getDetail({ id: opendata.record?.customId }), {
onSuccess: handleSuccess
})
initUserList()
}
formAction.value = opendata.newFormAction
}
@ -1786,7 +1737,22 @@ const storeItemClick = (item: any, index: number) => {
// ::v-deep .ant-form-item-explain-success {
// display: none !important;
// }
.a-label {
align-items: center;
max-width: 100%;
height: 32px;
line-height: 32px;
text-align: right;
color: #000000d9;
font-size: 14px;
width: 160px;
&::after {
content: ':';
position: relative;
top: -0.5px;
margin: 0 8px 0 2px;
}
}
//
.radius {
::v-deep .ant-form-item-control-input-content {

@ -12,8 +12,8 @@
@cancel="handleClose"
>
<a-tabs centered>
<a-tab-pane v-if="formModel.customType === 0" key="1" tab="A类型客户" />
<a-tab-pane v-if="formModel.customType === 1" key="2" tab="B类型客户" force-render />
<a-tab-pane v-if="formModel.customType === 1" :key="1" tab="基础分发" />
<a-tab-pane v-if="formModel.customType === 0" :key="0" tab="地理分发" force-render />
</a-tabs>
<a-form
ref="formRef"
@ -50,6 +50,24 @@
</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-select
v-model:value="formModel.salesmanUserIdList"
allow-clear
mode="multiple"
:max-tag-count="1"
:options="userList"
:field-names="{ label: 'userName', value: 'userId' }"
></a-select>
</a-form-item>
</a-col>
</a-row> -->
<a-row justify="start">
<a-col :span="24">
<a-form-item
@ -61,6 +79,22 @@
</a-form-item>
</a-col>
</a-row>
<a-row v-if="formModel.customType == 1" justify="start">
<a-col :span="24">
<a-form-item
label="客户资料"
name="customInformation"
:label-col="{ sm: { span: 24 }, md: { span: 4 } }"
:wrapper-col="{ sm: { span: 24 }, md: { span: 20 } }"
>
<a-textarea
v-model:value="formModel.customInformation"
readonly
placeholder="请输入客户资料"
/>
</a-form-item>
</a-col>
</a-row>
<template v-for="item in formModel.customStoreVOList" :key="item.storeId">
<a-row justify="start">
<a-col xs="24" :sm="24" :md="12">
@ -75,21 +109,19 @@
</a-col>
</a-row>
</template>
<a-row v-if="formModel.enrollStatus == 1 && formModel.customType == 1" justify="start">
<a-row v-if="formModel.enrollStatus == 1" justify="start">
<a-col :span="12">
<a-form-item
label="复审员选择"
:rules="[{ required: true, message: '请选择人员' }]"
name="reviewUserId"
>
<a-select ref="select" v-model:value="formModel.reviewUserId">
<a-select-option
v-for="(item, index) in selectedReviewerOptions"
:key="index"
:value="item.value"
>{{ item.label }}</a-select-option
>
</a-select>
<a-select
v-model:value="formModel.reviewUserId"
allow-clear
:options="selectedReviewerOptions"
:field-names="{ label: 'userName', value: 'userId' }"
/>
</a-form-item>
</a-col>
</a-row>
@ -98,21 +130,21 @@
<div v-if="title !== '详情'">
<a-button v-if="title !== '审核'" @click="visible = false"></a-button>
<a-button
v-if="formModel.enrollStatus == 1 && formModel.customType == 1"
v-if="formModel.enrollStatus == 1"
type="primary"
html-type="submit"
style="margin-left: 10px"
@click="toExamine(0)"
@click="toExamine(2)"
>重审</a-button
>
<a-button
<!-- <a-button
v-if="formModel.enrollStatus == 1 && formModel.customType == 0"
type="primary"
html-type="submit"
style="margin-left: 10px"
@click="toExamine(1)"
>分发</a-button
>
> -->
</div>
</template>
</a-modal>
@ -131,6 +163,7 @@ import { useUserStore } from '@/stores/user-store'
import { doRequest } from '@/utils/axios/request'
import { getCustomDetails } from '@/api/geopoliticalCustomers'
import type { SelectProps } from 'ant-design-vue'
import { getfFindDirectSalesman } from '@/api/directResources/index'
//
import 'dayjs/locale/zh-cn'
import { $ref } from 'vue/macros'
@ -160,6 +193,7 @@ interface SysUserPageVO {
customType: number
customStoreVOList: ReservationShop[]
reviewUserId: number | undefined
customInformation: string
}
const formModel = reactive<SysUserPageVO>({
@ -171,7 +205,8 @@ const formModel = reactive<SysUserPageVO>({
remark: '',
customStoreVOList: [],
enrollStatus: undefined,
reviewUserId: undefined
reviewUserId: undefined,
customInformation: ''
})
//
@ -205,12 +240,12 @@ const toExamine = (type: number) => {
formRef.value
.validate()
.then(() => {
updateCustomerAudit(
formModel.customId as number,
type,
userInfo!.salesmanType,
formModel.reviewUserId
).then(res => {
updateCustomerAudit({
customId: formModel.customId as number,
status: type,
salesmanType: userInfo!.salesmanType,
reviewUserId: formModel.reviewUserId
}).then(res => {
message.info({
content: h('span', { style: 'white-space: pre-wrap;' }, res.message)
})
@ -230,17 +265,22 @@ const selectedReviewerOptions = ref<SelectProps['options']>([])
defineExpose({
open(newFormAction: FormAction, id: number) {
selectedReviewerOptions.value = []
doRequest(selectedReviewerList(), {
// doRequest(selectedReviewerList(), {
// onSuccess: (res: any) => {
// const a = res.data.map((item: any) => {
// return { label: item.name, value: item.value }
// })
// a.forEach((item: any) => {
// selectedReviewerOptions.value?.push({
// label: item.label,
// value: item.value
// })
// })
// }
// })
doRequest(getfFindDirectSalesman(21), {
onSuccess: (res: any) => {
const a = res.data.map((item: any) => {
return { label: item.name, value: item.value }
})
a.forEach((item: any) => {
selectedReviewerOptions.value?.push({
label: item.label,
value: item.value
})
})
selectedReviewerOptions.value = res.data
}
})
openModal()
@ -252,6 +292,7 @@ defineExpose({
onSuccess: (res: any) => {
record = res.data
record.comprehensiveAddress = `${record?.economize}${record?.market}${record?.distinguish}${record?.detailAddress}`
record.customInformation = record.customInformation || record.remark
overrideProperties(formModel, record)
record.customStoreVOList.forEach((item: any) => {
const targetObj = formModel.customStoreVOList.find(

@ -152,7 +152,7 @@ defineExpose({
title.value = '编辑用户'
overrideProperties(formModel, record)
//
formModel.roleCodes = ['ROLE_SALES_EXECUTIVE']
formModel.roleCodes = ['ROLE_STORE_EXECUTIVE']
}
formAction.value = newFormAction
}

@ -12,11 +12,12 @@
<a-form-item label="用户名">
<a-input v-model:value="formModel.username" disabled placeholder="用户名" />
</a-form-item>
<a-form-item label="原密码" has-feedback v-bind="validateInfos.oldPass">
<a-input v-model:value="formModel.oldPass" type="password" placeholder="原密码" />
</a-form-item>
<a-form-item label="新密码" has-feedback v-bind="validateInfos.pass">
<a-input v-model:value="formModel.pass" type="password" placeholder="新密码" />
</a-form-item>
<a-form-item label="确认密码" has-feedback v-bind="validateInfos.confirmPass">
<a-input v-model:value="formModel.confirmPass" type="password" placeholder="确认密码" />
</a-form-item>
@ -79,11 +80,13 @@ const validateConfirmPass = async (_rule: Rule, value: string) => {
const formModel = reactive<ChangePasswordFormModel>({
username: '',
pass: '',
oldPass: '',
confirmPass: ''
})
//
const formRule = reactive({
oldPass: [{ required: true, message: '请输入原密码', trigger: 'change' }],
pass: [{ required: true, validator: validatePass, trigger: 'change' }],
confirmPass: [{ required: true, validator: validateConfirmPass, trigger: 'change' }]
})
@ -92,6 +95,7 @@ const formRule = reactive({
const formRequestMapping: FormRequestMapping<ChangePasswordFormModel> = {
[FormAction.OTHER]: () => {
return updateUserPassword(formModel.userId!, {
oldPass: passEncrypt(formModel.oldPass),
pass: passEncrypt(formModel.pass),
confirmPass: passEncrypt(formModel.confirmPass)
})
@ -109,10 +113,12 @@ const { submitLoading, validateAndSubmit, resetFields, validate, validateInfos }
/** 表单提交方法 */
const handleSubmit = () => {
console.log('111111111')
validateAndSubmit(
{ ...formModel },
{
onSuccess: () => {
console.log('111111111')
closeModal()
}
}

@ -20,7 +20,7 @@ import { projectTitle } from './src/config'
import { antdvStyleDeps } from './src/utils/resolvers'
//xy
// export const serverAddress = 'http://172.18.0.225:8000'
export const serverAddress = 'http://172.18.0.225:8000'
//jt
// export const serverAddress = 'http://172.18.1.8:8000'
//ts

Loading…
Cancel
Save