Skip to content

Commit 4eb3c8a

Browse files
YunaiVgitee-org
authored andcommitted
!358 fix: 修复多文件上传一个一个选择上传第二个文件上传失效的问题
Merge pull request !358 from puhui999/dev-crm
2 parents a0f7775 + 17be1ab commit 4eb3c8a

File tree

8 files changed

+213
-177
lines changed

8 files changed

+213
-177
lines changed

src/api/crm/customer/index.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,23 @@ export const queryAllList = async () => {
6969
}
7070

7171
// 查询客户操作日志
72-
export const getOperateLogPage = async (params: any) => {
73-
return await request.get({ url: '/crm/customer/operate-log-page', params })
72+
export const getOperateLogPage = async (id: number) => {
73+
return await request.get({ url: '/crm/customer/operate-log-page?id=' + id })
7474
}
7575

76+
//======================= 业务操作 =======================
77+
7678
// 锁定/解锁客户
7779
export const lockCustomer = async (id: number, lockStatus: boolean) => {
7880
return await request.put({ url: `/crm/customer/lock`, data: { id, lockStatus } })
7981
}
82+
83+
// 领取公海客户
84+
export const receive = async (ids: any[]) => {
85+
return await request.put({ url: '/crm/customer/receive', params: { ids: ids.join(',') } })
86+
}
87+
88+
// 客户放入公海
89+
export const putPool = async (id: number) => {
90+
return await request.put({ url: `/crm/customer/put-pool?id=${id}` })
91+
}

src/api/crm/permission/index.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,3 @@ export const deletePermissionBatch = async (params) => {
5858
export const deleteSelfPermission = async (id) => {
5959
return await request.delete({ url: '/crm/permission/quit-team?id=' + id })
6060
}
61-
62-
// TODO @puhui999:调整下位置
63-
// 领取公海数据
64-
export const receive = async (data: { bizType: number; bizId: number }) => {
65-
return await request.put({ url: `/crm/permission/receive`, data })
66-
}
67-
68-
// TODO @puhui999:调整下位置
69-
// 数据放入公海
70-
export const putPool = async (data: { bizType: number; bizId: number }) => {
71-
return await request.put({ url: `/crm/permission/put-pool`, data })
72-
}

src/components/OperateLogV2/src/OperateLogV2.vue

Lines changed: 8 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -2,36 +2,14 @@
22
<div class="p-20px">
33
<el-timeline>
44
<el-timeline-item
5-
v-for="(log, index) in logDataList"
5+
v-for="(log, index) in logList"
66
:key="index"
77
:timestamp="formatDate(log.createTime)"
88
placement="top"
99
>
1010
<div class="el-timeline-right-content">
11-
<el-row>
12-
<el-col :span="24" class="mb-10px">
13-
=======================
14-
<el-tag class="mr-10px" type="success">{{ log.userName }}</el-tag>
15-
<span>{{ log.title }}</span>
16-
=======================
17-
</el-col>
18-
<!-- 先处理一下有几行-->
19-
<template v-for="colNum in log.colSize" :key="colNum + 'col'">
20-
<el-col :span="24" class="mb-10px">
21-
<!-- 处理每一行-->
22-
<template
23-
v-for="(tagVal, index2) in log.tagsContentList.slice(
24-
(colNum - 1) * 3,
25-
3 * colNum
26-
)"
27-
:key="index2"
28-
>
29-
<el-tag class="mx-10px"> {{ tagVal }}</el-tag>
30-
<span>{{ log.contentStrList[index2] }}</span>
31-
</template>
32-
</el-col>
33-
</template>
34-
</el-row>
11+
<el-tag class="mr-10px" type="success">{{ log.userName }}</el-tag>
12+
{{ log.action }}
3513
</div>
3614
<template #dot>
3715
<span :style="{ backgroundColor: getUserTypeColor(log.userType) }" class="dot-node-style">
@@ -51,11 +29,13 @@ import { ElTag } from 'element-plus'
5129
5230
defineOptions({ name: 'OperateLogV2' })
5331
54-
const props = defineProps<{
32+
interface Props {
5533
logList: OperateLogV2VO[] // 操作日志列表
56-
}>()
34+
}
5735
58-
const logDataList = ref<OperateLogV2VO[]>([]) // 操作日志列表
36+
withDefaults(defineProps<Props>(), {
37+
logList: () => []
38+
})
5939
6040
/** 获得 userType 颜色 */
6141
const getUserTypeColor = (type: number) => {
@@ -72,57 +52,6 @@ const getUserTypeColor = (type: number) => {
7252
}
7353
return '#409EFF'
7454
}
75-
76-
// 提取 tag 所需内容和位置
77-
const renderTags = (content: string) => {
78-
let newStr = unref(content).slice() // 去掉引用
79-
newStr = newStr.replaceAll('【】', '【空】').replaceAll('', '') // 处理掉分号 特殊:处理一下空的情况
80-
const regex = /【([^【】]+)】/g
81-
const fg = '|' // 原始位置替换符号
82-
let match: any[] | null
83-
let matchStr: string[] = []
84-
let oldStr: string[] = []
85-
while ((match = regex.exec(newStr)) !== null) {
86-
matchStr.push(match[1]) // 提取值
87-
oldStr.push(match[0]) // 原值
88-
}
89-
// 为什么重新循环不放在 while 中一起是因为替换重新赋值过后 match 值就不准确了
90-
oldStr.forEach((item) => {
91-
newStr = newStr.replace(item, fg)
92-
})
93-
return [newStr.split(fg), matchStr]
94-
}
95-
96-
const initLog = () => {
97-
logDataList.value = props.logList.map((logItem) => {
98-
const keyValue = renderTags(logItem.action)
99-
// 挂载数据
100-
logItem.contentStrList = keyValue[0]
101-
if (keyValue[0][0] === '') {
102-
logItem.title = logItem.subType
103-
} else {
104-
logItem.title = keyValue[0][0]
105-
logItem.contentStrList.splice(0, 1)
106-
}
107-
logItem.colSize = keyValue[0].length / 3 // 变更记录行数
108-
logItem.tagsContentList = keyValue[1]
109-
return logItem
110-
})
111-
}
112-
113-
watch(
114-
() => props.logList.length,
115-
(newObj) => {
116-
if (newObj) {
117-
initLog()
118-
console.log(logDataList.value)
119-
}
120-
},
121-
{
122-
immediate: true,
123-
deep: true
124-
}
125-
)
12655
</script>
12756

12857
<style lang="scss" scoped>

src/components/UploadFile/src/UploadFile.vue

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,9 @@ const beforeUpload: UploadProps['beforeUpload'] = (file: UploadRawFile) => {
100100
// 文件上传成功
101101
const handleFileSuccess: UploadProps['onSuccess'] = (res: any): void => {
102102
message.success('上传成功')
103-
fileList.value.shift()
103+
// 删除自身
104+
const index = fileList.value.findIndex((item) => item.response?.data === res.data)
105+
fileList.value.splice(index, 1)
104106
uploadList.value.push({ name: res.data, url: res.data })
105107
if (uploadList.value.length == uploadNumber.value) {
106108
fileList.value.push(...uploadList.value)
@@ -144,6 +146,7 @@ watch(
144146
fileList.value.push(
145147
...val.split(',').map((url) => ({ name: url.substring(url.lastIndexOf('/') + 1), url }))
146148
)
149+
return
147150
}
148151
// 情况2:数组
149152
fileList.value.push(

src/views/crm/customer/detail/CustomerDetailsHeader.vue

Lines changed: 2 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,7 @@
1111
</div>
1212
<div>
1313
<!-- 右上:按钮 -->
14-
<el-button
15-
type="primary"
16-
v-hasPermi="['crm:customer:update']"
17-
@click="openForm(customer.id)"
18-
>
19-
编辑
20-
</el-button>
21-
<!-- TODO @puhui999:转移的操作接入 -->
22-
<el-button type="primary" @click="transfer">转移</el-button>
23-
<!-- TODO @puhui999:修改成交状态的接入 -->
24-
<el-button>更改成交状态</el-button>
25-
<el-button v-if="customer.lockStatus" @click="handleUnlock(customer.id!)">解锁</el-button>
26-
<el-button v-else @click="handleLock(customer.id!)">锁定</el-button>
14+
<slot></slot>
2715
</div>
2816
</div>
2917
</div>
@@ -42,43 +30,14 @@
4230
<el-descriptions-item label="首要联系人电话">{{ customer.mobile }}</el-descriptions-item>
4331
</el-descriptions>
4432
</ContentWrap>
45-
46-
<!-- 表单弹窗:添加/修改 -->
47-
<CustomerForm ref="formRef" @success="emit('refresh')" />
4833
</template>
4934
<script lang="ts" setup>
5035
import { DICT_TYPE } from '@/utils/dict'
5136
import * as CustomerApi from '@/api/crm/customer'
52-
import CustomerForm from '../CustomerForm.vue'
5337
5438
defineOptions({ name: 'CustomerDetailsHeader' })
55-
56-
const { customer, loading } = defineProps<{
39+
defineProps<{
5740
customer: CustomerApi.CustomerVO // 客户信息
5841
loading: boolean // 加载中
5942
}>()
60-
const message = useMessage() // 消息弹窗
61-
62-
/** 修改操作 */
63-
const formRef = ref()
64-
const openForm = (id?: number) => {
65-
formRef.value.open('update', id)
66-
}
67-
68-
/** 锁定操作 */
69-
const handleLock = async (id: number) => {
70-
await CustomerApi.lockCustomer(id, true)
71-
message.success('锁定成功')
72-
emit('refresh')
73-
}
74-
75-
/** 解锁操作 */
76-
const handleUnlock = async (id: number) => {
77-
console.log(customer, '=======')
78-
await CustomerApi.lockCustomer(id, false)
79-
message.success('解锁成功')
80-
emit('refresh')
81-
}
82-
83-
const emit = defineEmits(['refresh']) // 定义 success 事件,用于操作成功后的回调
8443
</script>
Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,19 @@
11
<template>
2-
<CustomerDetailsHeader :customer="customer" :loading="loading" @refresh="getCustomer(id)" />
2+
<CustomerDetailsHeader :customer="customer" :loading="loading">
3+
<el-button @click="close">返回</el-button>
4+
<!-- TODO puhui999: 按钮数据权限收尾统一完善,需要按权限分级和客户状态来动态显示匹配的按钮 -->
5+
<el-button v-hasPermi="['crm:customer:update']" type="primary" @click="openForm">
6+
编辑
7+
</el-button>
8+
<!-- TODO @puhui999:转移的操作接入 -->
9+
<el-button type="primary" @click="transfer">转移</el-button>
10+
<!-- TODO @puhui999:修改成交状态的接入 -->
11+
<el-button>更改成交状态</el-button>
12+
<el-button v-if="customer.lockStatus" @click="handleUnlock">解锁</el-button>
13+
<el-button v-if="!customer.lockStatus" @click="handleLock">锁定</el-button>
14+
<el-button v-if="!customer.ownerUserId" type="primary" @click="receive">领取客户</el-button>
15+
<el-button v-if="customer.ownerUserId" type="primary" @click="putPool">客户放入公海</el-button>
16+
</CustomerDetailsHeader>
317
<el-col>
418
<el-tabs>
519
<el-tab-pane label="详细资料">
@@ -11,7 +25,7 @@
1125
<el-tab-pane label="联系人" lazy>
1226
<ContactList :biz-id="customer.id!" :biz-type="BizTypeEnum.CRM_CUSTOMER" />
1327
</el-tab-pane>
14-
<el-tab-pane label="团队成员" lazy>
28+
<el-tab-pane label="团队成员">
1529
<PermissionList :biz-id="customer.id!" :biz-type="BizTypeEnum.CRM_CUSTOMER" />
1630
</el-tab-pane>
1731
<el-tab-pane label="商机" lazy>
@@ -27,10 +41,14 @@
2741
<el-tab-pane label="回访" lazy>TODO 待开发</el-tab-pane>
2842
</el-tabs>
2943
</el-col>
44+
45+
<!-- 表单弹窗:添加/修改 -->
46+
<CustomerForm ref="formRef" @success="getCustomer" />
3047
</template>
3148
<script lang="ts" setup>
3249
import { useTagsViewStore } from '@/store/modules/tagsView'
3350
import * as CustomerApi from '@/api/crm/customer'
51+
import CustomerForm from '@/views/crm/customer/CustomerForm.vue'
3452
import CustomerDetailsInfo from './CustomerDetailsInfo.vue' // 客户明细 - 详细信息
3553
import CustomerDetailsHeader from './CustomerDetailsHeader.vue' // 客户明细 - 头部
3654
import ContactList from '@/views/crm/contact/components/ContactList.vue' // 联系人列表
@@ -40,48 +58,86 @@ import ReceivableList from '@/views/crm/receivable/components/ReceivableList.vue
4058
import ReceivablePlanList from '@/views/crm/receivable/plan/components/ReceivablePlanList.vue' // 回款计划列表
4159
import PermissionList from '@/views/crm/permission/components/PermissionList.vue' // 团队成员列表(权限)
4260
import { BizTypeEnum } from '@/api/crm/permission'
43-
import { OperateLogV2VO } from '@/api/system/operatelog'
61+
import type { OperateLogV2VO } from '@/api/system/operatelog'
4462
4563
defineOptions({ name: 'CrmCustomerDetail' })
4664
47-
const route = useRoute()
48-
const id = Number(route.params.id) // 客户编号
65+
const customerId = ref(0) // 客户编号
4966
const loading = ref(true) // 加载中
67+
const message = useMessage() // 消息弹窗
68+
const { delView } = useTagsViewStore() // 视图操作
69+
const { currentRoute, push } = useRouter() // 路由
5070
/** 获取详情 */
5171
const customer = ref<CustomerApi.CustomerVO>({} as CustomerApi.CustomerVO) // 客户详情
52-
const getCustomer = async (id: number) => {
72+
const getCustomer = async () => {
5373
loading.value = true
5474
try {
55-
customer.value = await CustomerApi.getCustomer(id)
56-
await getOperateLog(id)
75+
customer.value = await CustomerApi.getCustomer(customerId.value)
76+
await getOperateLog()
5777
} finally {
5878
loading.value = false
5979
}
6080
}
81+
const formRef = ref<InstanceType<typeof CustomerForm>>() // 客户表单 Ref
82+
// 编辑客户
83+
const openForm = () => {
84+
formRef.value?.open('update', customerId.value)
85+
}
86+
// 客户转移
87+
const transfer = () => {}
88+
// 锁定客户
89+
const handleLock = async () => {
90+
await message.confirm(`确定锁定客户【${customer.value.name}】 吗?`)
91+
await CustomerApi.lockCustomer(unref(customerId.value), true)
92+
message.success(`锁定客户【${customer.value.name}】成功`)
93+
await getCustomer()
94+
}
95+
// 解锁客户
96+
const handleUnlock = async () => {
97+
await message.confirm(`确定解锁客户【${customer.value.name}】 吗?`)
98+
await CustomerApi.lockCustomer(unref(customerId.value), false)
99+
message.success(`解锁客户【${customer.value.name}】成功`)
100+
await getCustomer()
101+
}
102+
// 领取客户
103+
const receive = async () => {
104+
await message.confirm(`确定领取客户【${customer.value.name}】 吗?`)
105+
await CustomerApi.receive([unref(customerId.value)])
106+
message.success(`领取客户【${customer.value.name}】成功`)
107+
await getCustomer()
108+
}
109+
// 客户放入公海
110+
const putPool = async () => {
111+
await message.confirm(`确定将客户【${customer.value.name}】放入公海吗?`)
112+
await CustomerApi.putPool(unref(customerId.value))
113+
message.success(`客户【${customer.value.name}】放入公海成功`)
114+
close()
115+
}
61116
const logList = ref<OperateLogV2VO[]>([]) // 操作日志列表
62117
/**
63118
* 获取操作日志
64119
*/
65-
const getOperateLog = async (customerId: number) => {
66-
if (!customerId) {
120+
const getOperateLog = async () => {
121+
if (!customerId.value) {
67122
return
68123
}
69-
const data = await CustomerApi.getOperateLogPage({
70-
pageNo: 1,
71-
pageSize: 10,
72-
bizId: customerId
73-
})
124+
const data = await CustomerApi.getOperateLogPage(customerId.value)
74125
logList.value = data.list
75126
}
127+
const close = () => {
128+
delView(unref(currentRoute))
129+
// TODO 先返回到客户列表
130+
push({ name: 'CrmCustomer' })
131+
}
76132
/** 初始化 */
77-
const { delView } = useTagsViewStore() // 视图操作
78-
const { currentRoute } = useRouter() // 路由
133+
const { params } = useRoute()
79134
onMounted(() => {
80-
if (!id) {
135+
if (!params.id) {
81136
ElMessage.warning('参数错误,客户不能为空!')
82-
delView(unref(currentRoute))
137+
close()
83138
return
84139
}
85-
getCustomer(id)
140+
customerId.value = params.id as unknown as number
141+
getCustomer()
86142
})
87143
</script>

0 commit comments

Comments
 (0)