对接询单接口
This commit is contained in:
@@ -0,0 +1,63 @@
|
|||||||
|
import request from '@/utils/http'
|
||||||
|
|
||||||
|
export class manageService {
|
||||||
|
//询单列表
|
||||||
|
static getinquiryList(params: Api.Common.PaginatingParams) {
|
||||||
|
return request.get<Api.Common.CommonListData>({
|
||||||
|
url: '/admin/inquiry/list',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获取详情
|
||||||
|
static inquirydetail(params: any) {
|
||||||
|
return request.get<any>({
|
||||||
|
url: '/admin/inquiry/show',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//添加询单
|
||||||
|
static inquiryAdd(params: any) {
|
||||||
|
return request.post<Api.Common.AddResponse>({
|
||||||
|
url: '/admin/inquiry/store',
|
||||||
|
params
|
||||||
|
// showErrorMessage: false // 不显示错误消息
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//修改询单
|
||||||
|
static inquiryedit(params: any) {
|
||||||
|
return request.post<Api.Common.AddResponse>({
|
||||||
|
url: '/admin/inquiry/update',
|
||||||
|
params
|
||||||
|
// showErrorMessage: false // 不显示错误消息
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//删除询单
|
||||||
|
static inquirydelete(params: any) {
|
||||||
|
return request.get<Api.Common.AddResponse>({
|
||||||
|
url: '/admin/inquiry/destroy',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//分配询单
|
||||||
|
static inquiryallocation(params: any) {
|
||||||
|
return request.post<Api.Work.AddResponse>({
|
||||||
|
url: '/admin/inquiry/allocation',
|
||||||
|
params
|
||||||
|
// showErrorMessage: false // 不显示错误消息
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//发布询单
|
||||||
|
static inquiryrelease(params: any) {
|
||||||
|
return request.post<Api.Work.AddResponse>({
|
||||||
|
url: '/admin/inquiry/release',
|
||||||
|
params
|
||||||
|
// showErrorMessage: false // 不显示错误消息
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//获取用户下拉框
|
||||||
|
static presetusers() {
|
||||||
|
return request.get<any>({
|
||||||
|
url: '/common/preset/users'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
-15
@@ -67,52 +67,77 @@ export const useUserStore = defineStore(
|
|||||||
refreshToken.value = newRefreshToken
|
refreshToken.value = newRefreshToken
|
||||||
}
|
}
|
||||||
if (expiresIn) {
|
if (expiresIn) {
|
||||||
// 记录绝对过期时间
|
|
||||||
const expireAt = Date.now() + expiresIn * 1000
|
const expireAt = Date.now() + expiresIn * 1000
|
||||||
tokenExpireAt.value = expireAt
|
tokenExpireAt.value = expireAt
|
||||||
localStorage.setItem('token_expire_at', String(expireAt))
|
localStorage.setItem('token_expire_at', String(expireAt))
|
||||||
scheduleTokenRefresh(expiresIn)
|
// 检查是否需要重新设置定时器
|
||||||
|
const currentLeftSeconds = Math.floor((expireAt - Date.now()) / 1000)
|
||||||
|
if (currentLeftSeconds > 0) {
|
||||||
|
scheduleTokenRefresh(currentLeftSeconds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const setCompany= (id: string, abbr: string) => {
|
const setCompany = (id: string, abbr: string) => {
|
||||||
companyid.value = id
|
companyid.value = id
|
||||||
companyabbr.value = abbr
|
companyabbr.value = abbr
|
||||||
}
|
}
|
||||||
const setSystems= (id: string, abbr: string) => {
|
const setSystems = (id: string, abbr: string) => {
|
||||||
systemsid.value = id
|
systemsid.value = id
|
||||||
systemsabbr.value = abbr
|
systemsabbr.value = abbr
|
||||||
}
|
}
|
||||||
|
|
||||||
function restoreTokenTimer() {
|
function restoreTokenTimer() {
|
||||||
const expireAt = Number(localStorage.getItem('token_expire_at') || '0')
|
const expireAt = Number(localStorage.getItem('token_expire_at') || '0')
|
||||||
if (accessToken.value && expireAt > Date.now()) {
|
if (accessToken.value && expireAt > Date.now()) {
|
||||||
const leftSeconds = Math.floor((expireAt - Date.now()) / 1000)
|
const leftSeconds = Math.floor((expireAt - Date.now()) / 1000)
|
||||||
scheduleTokenRefresh(leftSeconds)
|
scheduleTokenRefresh(leftSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isScheduled = false
|
||||||
|
|
||||||
function scheduleTokenRefresh(expiresIn: number) {
|
function scheduleTokenRefresh(expiresIn: number) {
|
||||||
if (refreshTimeout) clearTimeout(refreshTimeout)
|
if (refreshTimeout) {
|
||||||
|
clearTimeout(refreshTimeout)
|
||||||
|
refreshTimeout = null
|
||||||
|
}
|
||||||
|
|
||||||
// 提前1分钟刷新
|
// 提前1分钟刷新
|
||||||
const refreshTime = (expiresIn - 100) * 1000
|
const refreshTime = (expiresIn - 100) * 1000
|
||||||
|
|
||||||
if (refreshTime > 0) {
|
if (refreshTime > 0) {
|
||||||
refreshTimeout = setTimeout(refreshTokenAction, refreshTime)
|
if (!isScheduled) {
|
||||||
|
isScheduled = true
|
||||||
|
refreshTimeout = setTimeout(() => {
|
||||||
|
refreshTokenAction().finally(() => {
|
||||||
|
isScheduled = false // 重置标志位
|
||||||
|
})
|
||||||
|
}, refreshTime)
|
||||||
|
} else {
|
||||||
|
console.log('scheduleTokenRefresh is already scheduled, skipping...')
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error('Invalid refreshTime:', refreshTime)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function refreshTokenAction() {
|
async function refreshTokenAction() {
|
||||||
try {
|
try {
|
||||||
const { data } = await UserService.refreshToken({ refresh_token: refreshToken.value })
|
const { data } = await UserService.refreshToken({ refresh_token: refreshToken.value })
|
||||||
setToken(data.access_token, data.refresh_token, data.expires_in)
|
// 动态计算剩余时间
|
||||||
|
const currentTime = Date.now()
|
||||||
|
const expireAt = currentTime + data.expires_in * 1000
|
||||||
|
const leftSeconds = Math.floor((expireAt - currentTime) / 1000)
|
||||||
|
setToken(data.access_token, data.refresh_token, leftSeconds)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
console.error('Token refresh failed:', e)
|
||||||
logOut()
|
logOut()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const logOut = () => {
|
const logOut = () => {
|
||||||
// 清空所有本地缓存
|
// 清空所有本地缓存
|
||||||
localStorage.clear();
|
localStorage.clear()
|
||||||
sessionStorage.clear();
|
sessionStorage.clear()
|
||||||
|
|
||||||
companyabbr.value = ''
|
companyabbr.value = ''
|
||||||
companyid.value = ''
|
companyid.value = ''
|
||||||
@@ -123,17 +148,13 @@ export const useUserStore = defineStore(
|
|||||||
accessToken.value = ''
|
accessToken.value = ''
|
||||||
refreshToken.value = ''
|
refreshToken.value = ''
|
||||||
if (refreshTimeout) clearTimeout(refreshTimeout) // 清理定时器
|
if (refreshTimeout) clearTimeout(refreshTimeout) // 清理定时器
|
||||||
|
|
||||||
// 清理工作台标签页
|
// 清理工作台标签页
|
||||||
useWorktabStore().clearAll()
|
useWorktabStore().clearAll()
|
||||||
|
|
||||||
// 清理sessionStorage中的用户信息缓存
|
// 清理sessionStorage中的用户信息缓存
|
||||||
sessionStorage.removeItem('lastUserInfo')
|
sessionStorage.removeItem('lastUserInfo')
|
||||||
sessionStorage.removeItem('iframeRoutes')
|
sessionStorage.removeItem('iframeRoutes')
|
||||||
|
|
||||||
// 重置路由状态
|
// 重置路由状态
|
||||||
resetRouterState(router)
|
resetRouterState(router)
|
||||||
|
|
||||||
// 跳转到登录页
|
// 跳转到登录页
|
||||||
router.push(RoutesAlias.Login)
|
router.push(RoutesAlias.Login)
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+19
-2
@@ -29,6 +29,23 @@ declare namespace Api {
|
|||||||
|
|
||||||
/** 启用状态 */
|
/** 启用状态 */
|
||||||
type EnableStatus = '1' | '2'
|
type EnableStatus = '1' | '2'
|
||||||
|
|
||||||
|
interface CommonInfo {
|
||||||
|
data: never[]
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 列表数据 */
|
||||||
|
interface CommonListData {
|
||||||
|
records: CommonInfo[]
|
||||||
|
current: number
|
||||||
|
size: number
|
||||||
|
total: number
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AddResponse {
|
||||||
|
code: string
|
||||||
|
message: string
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 认证类型 */
|
/** 认证类型 */
|
||||||
@@ -116,7 +133,7 @@ declare namespace Api {
|
|||||||
interface AddParams {
|
interface AddParams {
|
||||||
categorie_id: any
|
categorie_id: any
|
||||||
content: any
|
content: any
|
||||||
attachment:any
|
attachment: any
|
||||||
}
|
}
|
||||||
interface AddResponse {
|
interface AddResponse {
|
||||||
code: string
|
code: string
|
||||||
@@ -126,7 +143,7 @@ declare namespace Api {
|
|||||||
interface StatusParams {
|
interface StatusParams {
|
||||||
id: any
|
id: any
|
||||||
msg: any
|
msg: any
|
||||||
status:any
|
status: any
|
||||||
}
|
}
|
||||||
//分类
|
//分类
|
||||||
interface CategorieInfo {
|
interface CategorieInfo {
|
||||||
|
|||||||
@@ -10,15 +10,15 @@
|
|||||||
<el-form-item label="状态" label-width="70px">
|
<el-form-item label="状态" label-width="70px">
|
||||||
<el-select v-model="filter.status">
|
<el-select v-model="filter.status">
|
||||||
<el-option label="全部" value="" />
|
<el-option label="全部" value="" />
|
||||||
<el-option label="当天" value="0" />
|
<el-option label="待发布" value="0" />
|
||||||
<el-option label="近三天" value="1" />
|
<el-option label="待跟踪" value="1" />
|
||||||
<el-option label="近七天" value="2" />
|
<el-option label="已跟踪" value="2" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
<el-col :xs="24" :sm="12" :md="6" :lg="6" :xl="6">
|
||||||
<el-form-item label="渠道" label-width="70px">
|
<el-form-item label="渠道" label-width="70px">
|
||||||
<el-select v-model="filter.channel_id">
|
<el-select v-model="filter.channel">
|
||||||
<el-option v-for="v in channelOptions" :key="v.id" :label="v.name" :value="v.id">
|
<el-option v-for="v in channelOptions" :key="v.id" :label="v.name" :value="v.id">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
@@ -80,23 +80,61 @@
|
|||||||
>
|
>
|
||||||
<template #default>
|
<template #default>
|
||||||
<el-table-column prop="contacts" label="客户名称"></el-table-column>
|
<el-table-column prop="contacts" label="客户名称"></el-table-column>
|
||||||
<el-table-column prop="phone" label="电话"></el-table-column>
|
<el-table-column prop="tel" label="电话"></el-table-column>
|
||||||
<el-table-column prop="phone" label="国家"></el-table-column>
|
<el-table-column prop="phone" label="国家">
|
||||||
<el-table-column prop="phone" label="渠道"></el-table-column>
|
|
||||||
<el-table-column prop="magnitude" label="客户商机"></el-table-column>
|
|
||||||
<el-table-column prop="magnitude" label="发布人"></el-table-column>
|
|
||||||
<el-table-column prop="magnitude" label="跟单人"></el-table-column>
|
|
||||||
<el-table-column label="状态" min-width="140">
|
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span :class="getCountdownClass(scope.row.deleted_at)">
|
<span>
|
||||||
<span class="custom-clock-icon" style="margin-right: 4px; vertical-align: middle"
|
{{scope.row.country? scope.row.country.cn_addr : ''}}
|
||||||
><i class="iconfont-sys"></i></span
|
</span>
|
||||||
>
|
<span class="steer" v-if="scope.row.country">{{ scope.row.country.steering }}</span>
|
||||||
{{ getCountdown(scope.row.deleted_at) }}
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="phone" label="渠道">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>
|
||||||
|
{{scope.row.channel? scope.row.channel.name : ''}}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column fixed="right" label="操作" min-width="260px">
|
<el-table-column prop="quality" label="客户商机">
|
||||||
|
<template #default="scope">
|
||||||
|
<span :style="scope.row.quality==0 ? { color: '#F5AB00' } : scope.row.quality==1 ? { color: '#8495B8' }: { color: '#9B7200' }">
|
||||||
|
{{scope.row.quality==0 ? '金牌商机' : scope.row.quality==1 ? '银牌商机' : '铜牌商机'}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="magnitude" label="发布人">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>
|
||||||
|
{{scope.row.enter? scope.row.enter.name : ''}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="recipient" label="跟单人">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>
|
||||||
|
{{scope.row.recipient? scope.row.recipient.name : ''}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="状态">
|
||||||
|
<template #default="scope">
|
||||||
|
<span :style="scope.row.status== 0 ? { color: '#ccc' } :scope.row.status== 1 ? { color: '#00A43F' }: { color: '#3471FF' }">
|
||||||
|
{{ scope.row.status== 0 ? '未发布' : scope.row.status== 1 ? '待跟踪' : '已跟踪' }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="倒计时" min-width="140">
|
||||||
|
<template #default="scope">
|
||||||
|
<span :class="getCountdownClass(scope.row.countdown)" v-if="scope.row.status==1">
|
||||||
|
<span class="custom-clock-icon" style="margin-right: 4px; vertical-align: middle"
|
||||||
|
><i class="iconfont-sys"></i></span
|
||||||
|
>
|
||||||
|
{{ getCountdown(scope.row.countdown) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column fixed="right" label="操作" width="260px">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<div class="follow-action fenpei" @click="onFenpei(scope.row)">
|
<div class="follow-action fenpei" @click="onFenpei(scope.row)">
|
||||||
<span class="custom-clock-icon" style="margin-right: 2px; vertical-align: middle"
|
<span class="custom-clock-icon" style="margin-right: 2px; vertical-align: middle"
|
||||||
@@ -110,13 +148,13 @@
|
|||||||
>
|
>
|
||||||
详情
|
详情
|
||||||
</div>
|
</div>
|
||||||
<div class="follow-action" @click="onFollow(scope.row)">
|
<div class="follow-action" @click="onFollow(scope.row)" v-if="scope.row.status==0">
|
||||||
<span class="custom-clock-icon" style="margin-right: 2px; vertical-align: middle"
|
<span class="custom-clock-icon" style="margin-right: 2px; vertical-align: middle"
|
||||||
><i class="iconfont-sys"></i></span
|
><i class="iconfont-sys"></i></span
|
||||||
>
|
>
|
||||||
领单
|
发布
|
||||||
</div>
|
</div>
|
||||||
<div class="follow-action edit" @click="onEdit()">
|
<div class="follow-action edit" @click="onEdit(scope.row)" >
|
||||||
<span class="custom-clock-icon" style="margin-right: 2px; vertical-align: middle"
|
<span class="custom-clock-icon" style="margin-right: 2px; vertical-align: middle"
|
||||||
><i class="iconfont-sys"></i></span
|
><i class="iconfont-sys"></i></span
|
||||||
>
|
>
|
||||||
@@ -164,12 +202,17 @@
|
|||||||
</div>
|
</div>
|
||||||
<div v-if="detailRow" v-html="detailRow.desc_collect"> </div>
|
<div v-if="detailRow" v-html="detailRow.desc_collect"> </div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<el-dialog v-model="AddDialogVisible" title="录单" width="800px">
|
<el-dialog
|
||||||
|
:title="dialogType === 'add' ? '录单' : '编辑'"
|
||||||
|
v-model="AddDialogVisible"
|
||||||
|
width="800px"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
>
|
||||||
<el-form :model="addForm" ref="addFormRef" label-width="80px" class="add-form">
|
<el-form :model="addForm" ref="addFormRef" label-width="80px" class="add-form">
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="渠道" prop="channel_id">
|
<el-form-item label="渠道" prop="channel">
|
||||||
<el-select v-model="addForm.channel_id" placeholder="请选择渠道">
|
<el-select v-model="addForm.channel" placeholder="请选择渠道">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in channelOptions"
|
v-for="item in channelOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -180,8 +223,8 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="等级" prop="level">
|
<el-form-item label="等级" prop="quality">
|
||||||
<el-select v-model="addForm.level" placeholder="请选择等级">
|
<el-select v-model="addForm.quality" placeholder="请选择等级">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in opportunityOptions"
|
v-for="item in opportunityOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
@@ -213,8 +256,8 @@
|
|||||||
</el-row>
|
</el-row>
|
||||||
<el-row :gutter="16">
|
<el-row :gutter="16">
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="联系方式" prop="contact">
|
<el-form-item label="联系方式" prop="tel">
|
||||||
<el-input v-model="addForm.contact" placeholder="请输入联系方式" />
|
<el-input v-model="addForm.tel" placeholder="请输入联系方式" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
@@ -230,7 +273,7 @@
|
|||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
<el-form-item label="详情内容" prop="desc_collect">
|
<el-form-item label="详情内容" prop="content">
|
||||||
<ArtWangEditor class="el-top" v-model="editorHtml" />
|
<ArtWangEditor class="el-top" v-model="editorHtml" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<div class="form-submit-row">
|
<div class="form-submit-row">
|
||||||
@@ -244,9 +287,9 @@
|
|||||||
<el-dialog v-model="fenpeiDialogVisible" title="分配跟单" width="360px">
|
<el-dialog v-model="fenpeiDialogVisible" title="分配跟单" width="360px">
|
||||||
<el-form :model="fenpeiForm" label-width="0">
|
<el-form :model="fenpeiForm" label-width="0">
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-select v-model="fenpeiForm.follower_id" placeholder="请选择" style="width: 100%">
|
<el-select v-model="fenpeiForm.recipient" placeholder="请选择" style="width: 100%">
|
||||||
<el-option
|
<el-option
|
||||||
v-for="item in followerOptions"
|
v-for="item in userOptions"
|
||||||
:key="item.id"
|
:key="item.id"
|
||||||
:label="item.name"
|
:label="item.name"
|
||||||
:value="item.id"
|
:value="item.id"
|
||||||
@@ -266,13 +309,15 @@
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { ElMessageBox } from 'element-plus'
|
import { ElMessageBox } from 'element-plus'
|
||||||
import { CrmService } from '@/api/crmApi'
|
import { CrmService } from '@/api/crmApi'
|
||||||
|
import { manageService } from '@/api/adminApi'
|
||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
|
const dialogType = ref('add')
|
||||||
const { width } = useWindowSize()
|
const { width } = useWindowSize()
|
||||||
const isMobile = computed(() => width.value < 500)
|
const isMobile = computed(() => width.value < 500)
|
||||||
const filter = ref({
|
const filter = ref({
|
||||||
status: '',
|
status: '',
|
||||||
time: '',
|
time: '',
|
||||||
channel_id: ''
|
channel: ''
|
||||||
})
|
})
|
||||||
const pagination = reactive({
|
const pagination = reactive({
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
@@ -287,23 +332,27 @@
|
|||||||
const AddDialogVisible = ref(false)
|
const AddDialogVisible = ref(false)
|
||||||
const detailRow = ref<any>(null)
|
const detailRow = ref<any>(null)
|
||||||
const countryOptions = ref<any>()
|
const countryOptions = ref<any>()
|
||||||
const remindRange = ref('')
|
|
||||||
const tableData = ref<any[]>([])
|
const tableData = ref<any[]>([])
|
||||||
const addFormRef = ref()
|
const addFormRef = ref()
|
||||||
const addForm = reactive({
|
let addForm = reactive({
|
||||||
channel_id: '',
|
channel: '',
|
||||||
level: '',
|
quality: '',
|
||||||
country: '',
|
country: '',
|
||||||
email: '',
|
email: '',
|
||||||
contact: '',
|
tel: '',
|
||||||
contacts: '',
|
contacts: '',
|
||||||
whatsapp: '',
|
whatsapp: '',
|
||||||
desc_collect: ''
|
content: ''
|
||||||
})
|
})
|
||||||
// 响应式表单数据
|
// 响应式表单数据
|
||||||
const formFilters = reactive({ ...filter })
|
const formFilters = reactive({ ...filter })
|
||||||
// 重置表单
|
// 重置表单
|
||||||
const handleReset = () => {
|
const handleReset = () => {
|
||||||
|
filter.value = {
|
||||||
|
status: '',
|
||||||
|
time: '',
|
||||||
|
channel: ''
|
||||||
|
}
|
||||||
Object.assign(formFilters, { ...filter })
|
Object.assign(formFilters, { ...filter })
|
||||||
pagination.currentPage = 1 // 重置到第一页
|
pagination.currentPage = 1 // 重置到第一页
|
||||||
gettableList()
|
gettableList()
|
||||||
@@ -315,10 +364,6 @@
|
|||||||
pagination.currentPage = 1 // 搜索时重置到第一页
|
pagination.currentPage = 1 // 搜索时重置到第一页
|
||||||
gettableList()
|
gettableList()
|
||||||
}
|
}
|
||||||
watch([remindRange], () => {
|
|
||||||
pagination.currentPage = 1
|
|
||||||
gettableList()
|
|
||||||
})
|
|
||||||
const opportunityOptions = ref<any>()
|
const opportunityOptions = ref<any>()
|
||||||
//商机
|
//商机
|
||||||
const getMagnitude = async () => {
|
const getMagnitude = async () => {
|
||||||
@@ -337,6 +382,14 @@
|
|||||||
const res = await CrmService.getCountry()
|
const res = await CrmService.getCountry()
|
||||||
countryOptions.value = res || []
|
countryOptions.value = res || []
|
||||||
}
|
}
|
||||||
|
// 计算属性:将时间格式化为 "开始日期 - 结束日期"
|
||||||
|
const formattedTimeRange = () => {
|
||||||
|
if (!filter.value.time || filter.value.time.length !== 2) {
|
||||||
|
return '' // 如果时间范围无效,返回空字符串
|
||||||
|
}
|
||||||
|
const [startDate, endDate] = filter.value.time
|
||||||
|
return `${startDate} - ${endDate}`
|
||||||
|
}
|
||||||
// 获取列表数据
|
// 获取列表数据
|
||||||
const gettableList = async () => {
|
const gettableList = async () => {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
@@ -344,11 +397,13 @@
|
|||||||
const { currentPage, pageSize } = pagination
|
const { currentPage, pageSize } = pagination
|
||||||
const params: any = {
|
const params: any = {
|
||||||
current: currentPage,
|
current: currentPage,
|
||||||
size: pageSize
|
size: pageSize,
|
||||||
|
channel: filter.value.channel,
|
||||||
|
status: filter.value.status,
|
||||||
|
time: formattedTimeRange()
|
||||||
}
|
}
|
||||||
if (remindRange.value) params.follow_last = remindRange.value
|
const { records, current, size, total } = await manageService.getinquiryList(params)
|
||||||
const { data, current, size, total } = await CrmService.getcustomerList(params)
|
tableData.value = records.map((item: any) => ({
|
||||||
tableData.value = data.map((item: any) => ({
|
|
||||||
...item
|
...item
|
||||||
}))
|
}))
|
||||||
Object.assign(pagination, { currentPage: current, pageSize: size, total })
|
Object.assign(pagination, { currentPage: current, pageSize: size, total })
|
||||||
@@ -387,13 +442,12 @@
|
|||||||
clearInterval(timer.value)
|
clearInterval(timer.value)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
function getCountdown(targetTimestamp: number) {
|
||||||
function getCountdown(targetDate: string) {
|
|
||||||
// 让 refreshKey 成为依赖,确保每秒刷新
|
// 让 refreshKey 成为依赖,确保每秒刷新
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||||
refreshKey.value
|
refreshKey.value
|
||||||
const now = dayjs()
|
const now = dayjs()
|
||||||
const target = dayjs(targetDate, 'YYYY-MM-DD HH:mm:ss')
|
const target = dayjs.unix(targetTimestamp) // 使用时间戳创建 dayjs 对象
|
||||||
if (!target.isValid()) return '时间格式错误'
|
if (!target.isValid()) return '时间格式错误'
|
||||||
const diff = target.diff(now)
|
const diff = target.diff(now)
|
||||||
if (diff <= 0) return '已超时'
|
if (diff <= 0) return '已超时'
|
||||||
@@ -403,30 +457,60 @@
|
|||||||
const seconds = Math.floor((diff / 1000) % 60)
|
const seconds = Math.floor((diff / 1000) % 60)
|
||||||
return `${days > 0 ? days + '天' : ''}${hours}小时${minutes}分${seconds}秒`
|
return `${days > 0 ? days + '天' : ''}${hours}小时${minutes}分${seconds}秒`
|
||||||
}
|
}
|
||||||
|
// function getCountdown(targetDate: string) {
|
||||||
|
// // 让 refreshKey 成为依赖,确保每秒刷新
|
||||||
|
// // eslint-disable-next-line @typescript-eslint/no-unused-expressions
|
||||||
|
// refreshKey.value
|
||||||
|
// const now = dayjs()
|
||||||
|
// const target = dayjs(targetDate, 'YYYY-MM-DD HH:mm:ss')
|
||||||
|
// if (!target.isValid()) return '时间格式错误'
|
||||||
|
// const diff = target.diff(now)
|
||||||
|
// if (diff <= 0) return '已超时'
|
||||||
|
// const days = Math.floor(diff / (1000 * 60 * 60 * 24))
|
||||||
|
// const hours = Math.floor((diff / (1000 * 60 * 60)) % 24)
|
||||||
|
// const minutes = Math.floor((diff / (1000 * 60)) % 60)
|
||||||
|
// const seconds = Math.floor((diff / 1000) % 60)
|
||||||
|
// return `${days > 0 ? days + '天' : ''}${hours}小时${minutes}分${seconds}秒`
|
||||||
|
// }
|
||||||
|
|
||||||
function getCountdownClass(targetDate: string) {
|
function getCountdownClass(targetDate: number) {
|
||||||
const now = dayjs()
|
const now = dayjs()
|
||||||
const target = dayjs(targetDate, 'YYYY-MM-DD HH:mm:ss')
|
// const target = dayjs(targetDate, 'YYYY-MM-DD HH:mm:ss')
|
||||||
|
const target = dayjs.unix(targetDate)
|
||||||
if (!target.isValid() || target.diff(now) <= 0) {
|
if (!target.isValid() || target.diff(now) <= 0) {
|
||||||
return 'countdown-danger'
|
return 'countdown-danger'
|
||||||
}
|
}
|
||||||
return 'countdown-success'
|
return 'countdown-success'
|
||||||
}
|
}
|
||||||
|
function reactiveForm() {
|
||||||
|
Object.assign(addForm, {
|
||||||
|
channel: '',
|
||||||
|
quality: '',
|
||||||
|
country: '',
|
||||||
|
email: '',
|
||||||
|
tel: '',
|
||||||
|
contacts: '',
|
||||||
|
whatsapp: '',
|
||||||
|
content: ''
|
||||||
|
})
|
||||||
|
}
|
||||||
const addfn = () => {
|
const addfn = () => {
|
||||||
|
dialogType.value = 'add'
|
||||||
|
reactiveForm()
|
||||||
getgetChannel()
|
getgetChannel()
|
||||||
getMagnitude()
|
getMagnitude()
|
||||||
getarea()
|
getarea()
|
||||||
AddDialogVisible.value = true
|
AddDialogVisible.value = true
|
||||||
}
|
}
|
||||||
const onFollow = async (row: any) => {
|
const onFollow = async (row: any) => {
|
||||||
ElMessageBox.confirm('确定要领取此客户吗?', '提示', {
|
ElMessageBox.confirm('确定要发布此询单吗?', '提示', {
|
||||||
confirmButtonText: '确定',
|
confirmButtonText: '确定',
|
||||||
cancelButtonText: '取消',
|
cancelButtonText: '取消',
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
const res = await CrmService.customerclaim({ customer_id: row.id })
|
const res = await manageService.inquiryrelease({ id: row.id, status: 1 })
|
||||||
ElMessage.success(res?.message || '提交成功!')
|
ElMessage.success(res?.message || '请求成功!')
|
||||||
gettableList()
|
gettableList()
|
||||||
// 你可以在这里调用接口或做后续处理
|
// 你可以在这里调用接口或做后续处理
|
||||||
})
|
})
|
||||||
@@ -439,13 +523,49 @@
|
|||||||
detailRow.value = row
|
detailRow.value = row
|
||||||
detailDialogVisible.value = true
|
detailDialogVisible.value = true
|
||||||
}
|
}
|
||||||
//分配
|
|
||||||
const onFenpei = (row: any) => {
|
|
||||||
fenpeiForm.customer_id = row.id
|
|
||||||
fenpeiDialogVisible.value = true
|
|
||||||
}
|
|
||||||
//编辑
|
//编辑
|
||||||
const onEdit = () => {}
|
const carrid = ref('')
|
||||||
|
const onEdit = async (row: any) => {
|
||||||
|
dialogType.value = 'edit'
|
||||||
|
getgetChannel()
|
||||||
|
getMagnitude()
|
||||||
|
getarea()
|
||||||
|
AddDialogVisible.value = true
|
||||||
|
carrid.value = row.id
|
||||||
|
addForm = reactive({
|
||||||
|
channel: row.channel ? row.channel.id : '',
|
||||||
|
quality: row.quality,
|
||||||
|
country: row.country ? row.country.id : '',
|
||||||
|
email: row.email,
|
||||||
|
tel: row.tel,
|
||||||
|
contacts: row.contacts,
|
||||||
|
whatsapp: row.whatsapp,
|
||||||
|
content: row.content
|
||||||
|
})
|
||||||
|
// 这里可以添加编辑逻辑
|
||||||
|
// 例如打开编辑对话框或跳转到编辑页面
|
||||||
|
}
|
||||||
|
const delCodeTrim = (content: string): string => {
|
||||||
|
return content.replace(/(\s*)<\/code>/g, '</code>')
|
||||||
|
}
|
||||||
|
const handleAddSubmit = async () => {
|
||||||
|
// 提交表单逻辑
|
||||||
|
// 这里可以调用 API 提交 addForm 数据
|
||||||
|
if (dialogType.value === 'add') {
|
||||||
|
editorHtml.value = delCodeTrim(editorHtml.value)
|
||||||
|
addForm.content = editorHtml.value
|
||||||
|
const res = await manageService.inquiryAdd(addForm)
|
||||||
|
ElMessage.success(res?.message || '录单成功!')
|
||||||
|
} else {
|
||||||
|
editorHtml.value = delCodeTrim(editorHtml.value)
|
||||||
|
addForm.content = editorHtml.value
|
||||||
|
const forms = { ...addForm, id: carrid.value }
|
||||||
|
const res = await manageService.inquiryedit(forms)
|
||||||
|
ElMessage.success(res?.message || '录单成功!')
|
||||||
|
}
|
||||||
|
AddDialogVisible.value = false
|
||||||
|
gettableList()
|
||||||
|
}
|
||||||
//删除
|
//删除
|
||||||
const onDelete = (row: any) => {
|
const onDelete = (row: any) => {
|
||||||
ElMessageBox.confirm('确定要删除此条询单吗?', '提示', {
|
ElMessageBox.confirm('确定要删除此条询单吗?', '提示', {
|
||||||
@@ -454,9 +574,8 @@
|
|||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
// const res = await CrmService.customerclaim({ customer_id: row.id })
|
const res = await manageService.inquirydelete({ id: row.id })
|
||||||
// ElMessage.success(res?.message || '提交成功!')
|
ElMessage.success(res?.message || '提交成功!')
|
||||||
console.log(row.id)
|
|
||||||
gettableList()
|
gettableList()
|
||||||
// 你可以在这里调用接口或做后续处理
|
// 你可以在这里调用接口或做后续处理
|
||||||
})
|
})
|
||||||
@@ -466,44 +585,36 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const fenpeiForm = reactive({
|
const fenpeiForm = reactive({
|
||||||
customer_id: '',
|
id: '',
|
||||||
follower_id: ''
|
recipient: ''
|
||||||
})
|
})
|
||||||
|
const userOptions = ref<any>()
|
||||||
const followerOptions = ref<any[]>([])
|
const getuserList = async () => {
|
||||||
|
// 这里调用获取用户列表的接口
|
||||||
const getFollowerOptions = async () => {
|
const res = await manageService.presetusers()
|
||||||
// try {
|
userOptions.value = res || []
|
||||||
// const res = await CrmService.getFollowers();
|
// return res || []
|
||||||
// followerOptions.value = res || [];
|
}
|
||||||
// } catch (error) {
|
//分配
|
||||||
// console.error('获取跟单人列表失败:', error);
|
const onFenpei = (row: any) => {
|
||||||
// followerOptions.value = [];
|
getuserList()
|
||||||
// }
|
fenpeiForm.id = row.id
|
||||||
|
fenpeiDialogVisible.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleFenpeiSubmit = async () => {
|
const handleFenpeiSubmit = async () => {
|
||||||
if (!fenpeiForm.follower_id) {
|
if (!fenpeiForm.recipient) {
|
||||||
ElMessage.warning('请选择跟单人')
|
ElMessage.warning('请选择跟单人')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// try {
|
const res = await manageService.inquiryallocation({
|
||||||
// const res = await CrmService.assignFollow({
|
id: fenpeiForm.id,
|
||||||
// customer_id: fenpeiForm.customer_id,
|
recipient: fenpeiForm.recipient,
|
||||||
// follower_id: fenpeiForm.follower_id,
|
status: 2
|
||||||
// });
|
})
|
||||||
// ElMessage.success(res?.message || '分配成功!');
|
ElMessage.success(res?.message || '分配成功!')
|
||||||
// fenpeiDialogVisible.value = false;
|
fenpeiDialogVisible.value = false
|
||||||
// gettableList();
|
gettableList()
|
||||||
// } catch (error) {
|
|
||||||
// console.error('分配跟单失败:', error);
|
|
||||||
// ElMessage.error('分配跟单失败!');
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
const handleAddSubmit = () => {}
|
|
||||||
onMounted(() => {
|
|
||||||
getFollowerOptions()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
@@ -676,4 +787,11 @@
|
|||||||
.form-submit-row {
|
.form-submit-row {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
.steer {
|
||||||
|
margin-left: 5px;
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid #00a43f;
|
||||||
|
padding: 0px 4px;
|
||||||
|
color: #00a43f;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -34,10 +34,10 @@
|
|||||||
<el-table-column prop="magnitude" label="客户商机" min-width="140"></el-table-column>
|
<el-table-column prop="magnitude" label="客户商机" min-width="140"></el-table-column>
|
||||||
<el-table-column label="状态" min-width="140">
|
<el-table-column label="状态" min-width="140">
|
||||||
<template #default="scope">
|
<template #default="scope">
|
||||||
<span :class="getCountdownClass(scope.row.deleted_at)">
|
<span :class="getCountdownClass(scope.row.follow_next)">
|
||||||
|
|
||||||
<span class="custom-clock-icon" style="vertical-align: middle; margin-right: 4px;"><i class="iconfont-sys"></i></span>
|
<span class="custom-clock-icon" style="vertical-align: middle; margin-right: 4px;"><i class="iconfont-sys"></i></span>
|
||||||
{{ getCountdown(scope.row.deleted_at) }}
|
{{ getCountdown(scope.row.follow_next) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|||||||
Reference in New Issue
Block a user