Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
c96902d6
authored
Apr 28, 2024
by
芋道源码
Committed by
Gitee
Apr 28, 2024
Browse files
Options
Browse Files
Download
Plain Diff
!433 CRM: 修复客户导入、销售漏斗。上传组件的文件列表给拓展一个下载 。
Merge pull request !433 from puhui999/dev-crm
parents
f55c9b72
00762362
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
79 additions
and
38 deletions
+79
-38
.env.local-dev
+0
-0
package.json
+3
-3
src/components/UploadFile/src/UploadFile.vue
+19
-0
src/plugins/echarts/index.ts
+11
-9
src/views/crm/customer/CustomerImportForm.vue
+39
-19
src/views/crm/customer/index.vue
+7
-7
No files found.
.env.local
→
.env.local
-dev
View file @
c96902d6
File moved
package.json
View file @
c96902d6
...
@@ -6,11 +6,11 @@
...
@@ -6,11 +6,11 @@
"private"
:
false
,
"private"
:
false
,
"scripts"
:
{
"scripts"
:
{
"i"
:
"pnpm install"
,
"i"
:
"pnpm install"
,
"dev"
:
"vite --mode local-dev"
,
"
local-
dev"
:
"vite --mode local-dev"
,
"dev
-server
"
:
"vite --mode dev"
,
"dev"
:
"vite --mode dev"
,
"ts:check"
:
"vue-tsc --noEmit"
,
"ts:check"
:
"vue-tsc --noEmit"
,
"build:local-dev"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev"
,
"build:local-dev"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode local-dev"
,
"build:dev"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode
local-
dev"
,
"build:dev"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode dev"
,
"build:test"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode test"
,
"build:test"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode test"
,
"build:stage"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode stage"
,
"build:stage"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode stage"
,
"build:prod"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode prod"
,
"build:prod"
:
"node --max_old_space_size=8192 ./node_modules/vite/bin/vite.js build --mode prod"
,
...
...
src/components/UploadFile/src/UploadFile.vue
View file @
c96902d6
...
@@ -32,6 +32,25 @@
...
@@ -32,6 +32,25 @@
格式为
<b
style=
"color: #f56c6c"
>
{{
fileType
.
join
(
'/'
)
}}
</b>
的文件
格式为
<b
style=
"color: #f56c6c"
>
{{
fileType
.
join
(
'/'
)
}}
</b>
的文件
</div>
</div>
</
template
>
</
template
>
<
template
#
file=
"row"
>
<div
class=
"flex items-center"
>
<span>
{{
row
.
file
.
name
}}
</span>
<div
class=
"ml-10px"
>
<el-link
:href=
"row.file.url"
:underline=
"false"
download
target=
"_blank"
type=
"primary"
>
下载
</el-link>
</div>
<div
class=
"ml-10px"
>
<el-button
link
type=
"danger"
@
click=
"handleRemove(row.file)"
>
删除
</el-button>
</div>
</div>
</
template
>
</el-upload>
</el-upload>
</div>
</div>
</template>
</template>
...
...
src/plugins/echarts/index.ts
View file @
c96902d6
...
@@ -2,23 +2,24 @@ import * as echarts from 'echarts/core'
...
@@ -2,23 +2,24 @@ import * as echarts from 'echarts/core'
import
{
import
{
BarChart
,
BarChart
,
FunnelChart
,
GaugeChart
,
LineChart
,
LineChart
,
PieChart
,
MapChart
,
MapChart
,
PictorialBarChart
,
PictorialBarChart
,
Radar
Chart
,
Pie
Chart
,
Gauge
Chart
Radar
Chart
}
from
'echarts/charts'
}
from
'echarts/charts'
import
{
import
{
TitleComponent
,
TooltipComponent
,
GridComponent
,
PolarComponent
,
AriaComponent
,
AriaComponent
,
Parallel
Component
,
Grid
Component
,
LegendComponent
,
LegendComponent
,
ParallelComponent
,
PolarComponent
,
TitleComponent
,
ToolboxComponent
,
ToolboxComponent
,
TooltipComponent
,
VisualMapComponent
VisualMapComponent
}
from
'echarts/components'
}
from
'echarts/components'
...
@@ -41,7 +42,8 @@ echarts.use([
...
@@ -41,7 +42,8 @@ echarts.use([
CanvasRenderer
,
CanvasRenderer
,
PictorialBarChart
,
PictorialBarChart
,
RadarChart
,
RadarChart
,
GaugeChart
GaugeChart
,
FunnelChart
])
])
export
default
echarts
export
default
echarts
src/views/crm/customer/CustomerImportForm.vue
View file @
c96902d6
<!-- 客户导入窗口 -->
<!-- 客户导入窗口 -->
<
template
>
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"客户导入"
width=
"400"
>
<Dialog
v-model=
"dialogVisible"
title=
"客户导入"
width=
"400"
>
<div
class=
"flex items-center my-10px"
>
<span
class=
"mr-10px"
>
负责人
</span>
<el-select
v-model=
"ownerUserId"
class=
"!w-240px"
clearable
>
<el-option
v-for=
"item in userOptions"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</div>
<el-upload
<el-upload
ref=
"uploadRef"
ref=
"uploadRef"
v-model:file-list=
"fileList"
v-model:file-list=
"fileList"
:auto-upload=
"false"
:auto-upload=
"false"
:disabled=
"formLoading"
:disabled=
"formLoading"
:headers=
"uploadHeaders"
:limit=
"1"
:limit=
"1"
:on-error=
"submitFormError"
:on-exceed=
"handleExceed"
:on-exceed=
"handleExceed"
:on-success=
"submitFormSuccess"
accept=
".xlsx, .xls"
accept=
".xlsx, .xls"
action=
"none"
action=
"none"
drag
drag
...
@@ -43,9 +51,10 @@
...
@@ -43,9 +51,10 @@
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
*
as
CustomerApi
from
'@/api/crm/customer'
import
{
getAccessToken
,
getTenantId
}
from
'@/utils/auth'
import
download
from
'@/utils/download'
import
download
from
'@/utils/download'
import
type
{
UploadUserFile
}
from
'element-plus'
import
type
{
UploadUserFile
}
from
'element-plus'
import
*
as
UserApi
from
'@/api/system/user'
import
{
useUserStore
}
from
'@/store/modules/user'
defineOptions
({
name
:
'SystemUserImportForm'
})
defineOptions
({
name
:
'SystemUserImportForm'
})
...
@@ -54,15 +63,18 @@ const message = useMessage() // 消息弹窗
...
@@ -54,15 +63,18 @@ const message = useMessage() // 消息弹窗
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
uploadRef
=
ref
()
const
uploadRef
=
ref
()
const
uploadHeaders
=
ref
()
// 上传 Header 头
const
fileList
=
ref
<
UploadUserFile
[]
>
([])
// 文件列表
const
fileList
=
ref
<
UploadUserFile
[]
>
([])
// 文件列表
const
updateSupport
=
ref
(
false
)
// 是否更新已经存在的客户数据
const
updateSupport
=
ref
(
false
)
// 是否更新已经存在的客户数据
const
ownerUserId
=
ref
<
undefined
|
number
>
()
// 负责人编号
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
/** 打开弹窗 */
/** 打开弹窗 */
const
open
=
()
=>
{
const
open
=
async
()
=>
{
dialogVisible
.
value
=
true
dialogVisible
.
value
=
true
fileList
.
value
=
[]
await
resetForm
()
resetForm
()
// 获得用户列表
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
ownerUserId
.
value
=
useUserStore
().
getUser
.
id
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
...
@@ -72,17 +84,20 @@ const submitForm = async () => {
...
@@ -72,17 +84,20 @@ const submitForm = async () => {
message
.
error
(
'请上传文件'
)
message
.
error
(
'请上传文件'
)
return
return
}
}
// 提交请求
uploadHeaders
.
value
=
{
Authorization
:
'Bearer '
+
getAccessToken
(),
'tenant-id'
:
getTenantId
()
}
formLoading
.
value
=
true
formLoading
.
value
=
true
try
{
const
formData
=
new
FormData
()
const
formData
=
new
FormData
()
formData
.
append
(
'updateSupport'
,
updateSupport
.
value
)
formData
.
append
(
'updateSupport'
,
String
(
updateSupport
.
value
))
formData
.
append
(
'file'
,
fileList
.
value
[
0
].
raw
)
formData
.
append
(
'file'
,
fileList
.
value
[
0
].
raw
as
Blob
)
// TODO @芋艿:后面是不是可以采用这种形式,去掉 uploadHeaders
formData
.
append
(
'ownerUserId'
,
String
(
ownerUserId
.
value
))
await
CustomerApi
.
handleImport
(
formData
)
const
res
=
await
CustomerApi
.
handleImport
(
formData
)
submitFormSuccess
(
res
)
}
catch
{
submitFormError
()
}
finally
{
formLoading
.
value
=
false
}
}
}
/** 文件上传成功 */
/** 文件上传成功 */
...
@@ -108,6 +123,8 @@ const submitFormSuccess = (response: any) => {
...
@@ -108,6 +123,8 @@ const submitFormSuccess = (response: any) => {
text += '
<
' + customerName + '
:
' + data.failureCustomerNames[customerName] + '
>
'
text += '
<
' + customerName + '
:
' + data.failureCustomerNames[customerName] + '
>
'
}
}
message.alert(text)
message.alert(text)
formLoading.value = false
dialogVisible.value = false
// 发送操作成功的事件
// 发送操作成功的事件
emits('
success
')
emits('
success
')
}
}
...
@@ -119,9 +136,12 @@ const submitFormError = (): void => {
...
@@ -119,9 +136,12 @@ const submitFormError = (): void => {
}
}
/** 重置表单 */
/** 重置表单 */
const resetForm = () => {
const resetForm =
async
() => {
// 重置上传状态和文件
// 重置上传状态和文件
formLoading.value = false
fileList.value = []
updateSupport.value = false
ownerUserId.value = undefined
await nextTick()
uploadRef.value?.clearFiles()
uploadRef.value?.clearFiles()
}
}
...
...
src/views/crm/customer/index.vue
View file @
c96902d6
...
@@ -79,7 +79,7 @@
...
@@ -79,7 +79,7 @@
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
<Icon
class=
"mr-5px"
icon=
"ep:search"
/>
搜索
搜索
</el-button>
</el-button>
<el-button
@
click=
"resetQuery
(undefined)
"
>
<el-button
@
click=
"resetQuery"
>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
<Icon
class=
"mr-5px"
icon=
"ep:refresh"
/>
重置
重置
</el-button>
</el-button>
...
@@ -113,7 +113,7 @@
...
@@ -113,7 +113,7 @@
<el-tab-pane
label=
"下属负责的"
name=
"3"
/>
<el-tab-pane
label=
"下属负责的"
name=
"3"
/>
</el-tabs>
</el-tabs>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table
v-loading=
"loading"
:data=
"list"
:show-overflow-tooltip=
"true"
:stripe=
"true"
>
<el-table-column
align=
"center"
label=
"客户名称"
fixed=
"left
"
prop=
"name"
width=
"160"
>
<el-table-column
align=
"center"
fixed=
"left"
label=
"客户名称
"
prop=
"name"
width=
"160"
>
<template
#
default=
"scope"
>
<template
#
default=
"scope"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
<el-link
:underline=
"false"
type=
"primary"
@
click=
"openDetail(scope.row.id)"
>
{{
scope
.
row
.
name
}}
{{
scope
.
row
.
name
}}
...
@@ -125,9 +125,9 @@
...
@@ -125,9 +125,9 @@
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_SOURCE"
:value=
"scope.row.source"
/>
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_SOURCE"
:value=
"scope.row.source"
/>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
<el-table-column
label=
"手机"
align=
"center
"
prop=
"mobile"
width=
"120"
/>
<el-table-column
align=
"center"
label=
"手机
"
prop=
"mobile"
width=
"120"
/>
<el-table-column
label=
"电话"
align=
"center
"
prop=
"telephone"
width=
"130"
/>
<el-table-column
align=
"center"
label=
"电话
"
prop=
"telephone"
width=
"130"
/>
<el-table-column
label=
"邮箱"
align=
"center
"
prop=
"email"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"邮箱
"
prop=
"email"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"客户级别"
prop=
"level"
width=
"135"
>
<el-table-column
align=
"center"
label=
"客户级别"
prop=
"level"
width=
"135"
>
<
template
#
default=
"scope"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_LEVEL"
:value=
"scope.row.level"
/>
<dict-tag
:type=
"DICT_TYPE.CRM_CUSTOMER_LEVEL"
:value=
"scope.row.level"
/>
...
@@ -164,7 +164,7 @@
...
@@ -164,7 +164,7 @@
width=
"180px"
width=
"180px"
/>
/>
<el-table-column
align=
"center"
label=
"最后跟进记录"
prop=
"contactLastContent"
width=
"200"
/>
<el-table-column
align=
"center"
label=
"最后跟进记录"
prop=
"contactLastContent"
width=
"200"
/>
<el-table-column
label=
"地址"
align=
"center
"
prop=
"detailAddress"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"地址
"
prop=
"detailAddress"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"距离进入公海天数"
prop=
"poolDay"
width=
"140"
>
<el-table-column
align=
"center"
label=
"距离进入公海天数"
prop=
"poolDay"
width=
"140"
>
<
template
#
default=
"scope"
>
{{
scope
.
row
.
poolDay
}}
天
</
template
>
<
template
#
default=
"scope"
>
{{
scope
.
row
.
poolDay
}}
天
</
template
>
</el-table-column>
</el-table-column>
...
@@ -254,7 +254,7 @@ const activeName = ref('1') // 列表 tab
...
@@ -254,7 +254,7 @@ const activeName = ref('1') // 列表 tab
/** tab 切换 */
/** tab 切换 */
const
handleTabClick
=
(
tab
:
TabsPaneContext
)
=>
{
const
handleTabClick
=
(
tab
:
TabsPaneContext
)
=>
{
queryParams
.
sceneType
=
tab
.
paneName
queryParams
.
sceneType
=
tab
.
paneName
as
string
handleQuery
()
handleQuery
()
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment