Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
H
horse
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
向伟
horse
Commits
c0b88b7e
Commit
c0b88b7e
authored
Nov 25, 2021
by
罗超
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
1
parent
4c99e7ee
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1333 additions
and
737 deletions
+1333
-737
customRight.vue
src/components/common/customRight.vue
+770
-547
fileUpload.vue
src/components/common/fileUpload.vue
+156
-69
customerSetup.vue
src/pages/customer/customerSetup.vue
+22
-6
getters.ts
src/store/modules/user/getters.ts
+3
-0
state.ts
src/store/modules/user/state.ts
+1
-0
common.ts
src/utils/common.ts
+0
-115
upload.ts
src/utils/upload.ts
+381
-0
No files found.
src/components/common/customRight.vue
View file @
c0b88b7e
<
template
>
<q-dialog
v-model=
"persistent"
full-height
maximized
position=
"right"
persistent
@
hide=
"closeCutomer"
transition-show=
"slide-left"
>
<q-dialog
v-model=
"persistent"
full-height
maximized
position=
"right"
persistent
@
hide=
"closeCutomer"
transition-show=
"slide-left"
>
<div
class=
"customMain"
>
<div
class=
"custom_Top"
>
<div
class=
"custom_HLeft"
>
<div
class=
"nameplate_avatar"
>
<img
style=
"width:100%;height:100%;"
:src=
"data.dataList.WeChatPhoto"
alt
=
""
/>
<img
style=
"width:100%;height:100%;"
:src=
"data.dataList.WeChatPhoto"
alt
/>
</div>
<div
class=
"Name_List"
>
<div
class=
"F_16"
>
{{
data
.
dataList
.
CustomerName
}}
</div>
<div
class=
"wechat_Name"
>
{{
data
.
dataList
.
WeChatName
}}
</div>
<div
class=
"F_16"
>
{{
data
.
dataList
.
CustomerName
}}
</div>
<div
class=
"wechat_Name"
>
{{
data
.
dataList
.
WeChatName
}}
</div>
</div>
</div>
<div
class=
"custom_HRight"
>
...
...
@@ -21,41 +28,84 @@
<div
class=
"info_title"
>
客户画像
</div>
<div
class=
"info_content"
style=
"margin-bottom:0;"
>
<div
class=
"customer_info_component"
>
<div
class=
"customer_info_Stage"
v-if=
"!data.isShowEdit"
@
click=
"getCustomEdit(1,data.isShowEdit)"
>
<div
class=
"customer_info_Stage"
v-if=
"!data.isShowEdit"
@
click=
"getCustomEdit(1, data.isShowEdit)"
>
<div
class=
"stage_label"
>
客户阶段
</div>
<div
class=
"stage_value"
>
{{
data
.
dataList
.
StageName
}}
</div>
<div
class=
"stage_value"
>
{{
data
.
dataList
.
StageName
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
客户阶段
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomEdit(1,data.isShowEdit)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomGate"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomEdit(1, data.isShowEdit)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomGate"
/>
</div>
</div>
<div
class=
"edit_content"
>
<div
class=
"edit_info_wrap"
>
<q-select
filled
option-value=
"Id"
size=
"sm"
v-model=
"cutomMsg.Value"
option-label=
"Name"
:options=
"data.customData"
emit-value
map-options
label=
"请选择客户阶段"
/>
</div>
</div>
</div>
</div>
<div
class=
"customer_info_component"
v-for=
"(item,index) in data.FiledDetailList"
:key=
"index"
>
<q-select
filled
option-value=
"Id"
size=
"sm"
v-model=
"cutomMsg.Value"
option-label=
"Name"
:options=
"data.customData"
emit-value
map-options
label=
"请选择客户阶段"
/>
</div>
</div>
</div>
</div>
<div
class=
"customer_info_component"
v-for=
"(item,index) in data.FiledDetailList"
:key=
"index"
>
<!-- 1单行文本 2多行文本 3单选 4多选 5日期 6日期时间 7数值 -->
<template
v-if=
"item.Type==1"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
<template
v-if=
"item.Type == 1"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
...
...
@@ -65,18 +115,33 @@
</div>
</div>
</
template
>
<
template
v-if=
"item.Type==2"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
<
template
v-if=
"item.Type == 2"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
...
...
@@ -86,63 +151,128 @@
</div>
</div>
</
template
>
<
template
v-if=
"item.Type==3"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
getSingle
(
item
)
}}
</div>
<
template
v-if=
"item.Type == 3"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
getSingle
(
item
)
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
<div
class=
"edit_info_wrap"
>
<q-select
filled
option-value=
"Id"
size=
"sm"
v-model=
"item.Value"
option-label=
"Name"
:options=
"item.OptionsList"
emit-value
map-options
label=
"请选择"
/>
<q-select
filled
option-value=
"Id"
size=
"sm"
v-model=
"item.Value"
option-label=
"Name"
:options=
"item.OptionsList"
emit-value
map-options
label=
"请选择"
/>
</div>
</div>
</div>
</
template
>
<
template
v-if=
"item.Type==4"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
getMutipleCk
(
item
)
}}
</div>
<
template
v-if=
"item.Type == 4"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
getMutipleCk
(
item
)
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
<div
class=
"edit_info_wrap"
>
<q-select
filled
multiple
use-chips
option-value=
"Id"
size=
"sm"
v-model=
"data.multiArr"
option-label=
"Name"
:options=
"item.OptionsList"
emit-value
map-options
label=
"请选择"
/>
<q-select
filled
multiple
use-chips
option-value=
"Id"
size=
"sm"
v-model=
"data.multiArr"
option-label=
"Name"
:options=
"item.OptionsList"
emit-value
map-options
label=
"请选择"
/>
</div>
</div>
</div>
</
template
>
<
template
v-if=
"item.Type==5"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
<
template
v-if=
"item.Type == 5"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class
=
""
></div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class
></div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
...
...
@@ -150,7 +280,12 @@
<q-input
filled
v-model=
"item.Value"
mask=
"date"
:rules=
"['date']"
>
<template
v-slot:append
>
<q-icon
name=
"event"
class=
"cursor-pointer"
>
<q-popup-proxy
ref=
"qDateProxy"
cover
transition-show=
"scale"
transition-hide=
"scale"
>
<q-popup-proxy
ref=
"qDateProxy"
cover
transition-show=
"scale"
transition-hide=
"scale"
>
<q-date
v-model=
"item.Value"
>
<div
class=
"row items-center justify-end"
>
<q-btn
v-close-popup
label=
"Close"
color=
"primary"
flat
/>
...
...
@@ -164,18 +299,33 @@
</div>
</div>
</template>
<
template
v-if=
"item.Type==6"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
<
template
v-if=
"item.Type == 6"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
...
...
@@ -183,7 +333,12 @@
<q-input
filled
v-model=
"item.Value"
mask=
"date"
:rules=
"['date']"
>
<template
v-slot:append
>
<q-icon
name=
"event"
class=
"cursor-pointer"
>
<q-popup-proxy
ref=
"qDateProxy"
cover
transition-show=
"scale"
transition-hide=
"scale"
>
<q-popup-proxy
ref=
"qDateProxy"
cover
transition-show=
"scale"
transition-hide=
"scale"
>
<q-date
v-model=
"item.Value"
>
<div
class=
"row items-center justify-end"
>
<q-btn
v-close-popup
label=
"Close"
color=
"primary"
flat
/>
...
...
@@ -197,18 +352,33 @@
</div>
</div>
</template>
<
template
v-if=
"item.Type==7"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2,item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
<
template
v-if=
"item.Type == 7"
>
<div
class=
"customer_info_Stage"
v-if=
"!item.isShowEdit"
@
click=
"getCustomEdit(2, item)"
>
<div
class=
"stage_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"stage_value"
>
{{
item
.
Value
}}
</div>
</div>
<div
class=
"customer_info_edit"
v-else
>
<div
class=
"edit_bar"
>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div
class=
"item_label"
>
{{
item
.
Name
}}
</div>
<div>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
<q-btn
color=
"white"
size=
"sm"
text-color=
"black"
label=
"取消"
@
click=
"getCustomCancel(item)"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
@
click=
"saveCustomInfo(item)"
/>
</div>
</div>
<div
class=
"edit_content"
>
...
...
@@ -225,32 +395,32 @@
<div
class=
"item_label"
>
客户标签
</div>
</div>
<div
class=
"customTag_component"
>
<div
class=
"custom_Edit"
@
click=
"isshowlabel
=
true"
>
编辑
</div>
<div
class=
"custom_Edit"
@
click=
"isshowlabel
=
true"
>
编辑
</div>
<div
v-for=
"(tItem,tIndex) in data.dataList.LableList"
:key=
"tIndex"
>
<q-chip
square
color=
"primary"
text-color=
"white"
>
{{
tItem.Name
}}
</q-chip>
<q-chip
square
color=
"primary"
text-color=
"white"
>
{{
tItem.Name
}}
</q-chip>
</div>
</div>
<div
class=
"info_title"
>
客户跟进
</div>
<div
class=
"info_content"
>
<div
class=
"info_item"
>
<div
class=
"item_label"
>
上次跟进
</div>
<div
class=
"item_value"
>
{{
data.dataList.LastFollowUpTime
}}
</div>
<div
class=
"item_value"
>
{{
data.dataList.LastFollowUpTime
}}
</div>
</div>
<div
class=
"info_item"
>
<div
class=
"item_label"
>
创建时间
</div>
<div
class=
"item_value"
>
{{
data.dataList.CreateTime
}}
</div>
<div
class=
"item_value"
>
{{
data.dataList.CreateTime
}}
</div>
</div>
<div
class=
"info_item"
>
<div
class=
"item_label"
>
添加好友
</div>
<div
class=
"item_value"
>
{{
data.dataList.FriendTime
}}
</div>
<div
class=
"item_value"
>
{{
data.dataList.FriendTime
}}
</div>
</div>
<div
class=
"info_item"
>
<div
class=
"item_label"
>
负责人
</div>
<div
class=
"item_value"
>
{{
data.dataList.EmpName
}}
</div>
<div
class=
"item_value"
>
{{
data.dataList.EmpName
}}
</div>
</div>
<div
class=
"info_item"
>
<div
class=
"item_label"
>
客户ID
</div>
<div
class=
"item_value"
>
{{
data.dataList.ExternalUserId
}}
</div>
<div
class=
"item_value"
>
{{
data.dataList.ExternalUserId
}}
</div>
</div>
</div>
</div>
...
...
@@ -267,38 +437,56 @@
<div
style=
"flex:1;overflow:hidden;"
>
<div
class=
"detail_Main"
>
<div
class=
"tripTypeContent"
style=
"flex-shrink:0"
>
<div
v-for=
"(qItem,qIndex) in data.tripTypeArr"
:key=
"qIndex"
:class=
"{'ckedClass':qIndex==customTripMsg.Type}"
@
click=
"getckedType(qItem)"
>
{{qItem.Name}}
</div>
<div
v-for=
"(qItem,qIndex) in data.tripTypeArr"
:key=
"qIndex"
:class=
"{ 'ckedClass': qIndex == customTripMsg.Type }"
@
click=
"getckedType(qItem)"
>
{{ qItem.Name }}
</div>
</div>
<div
class=
"follow_Component"
style=
"flex-shrink:0"
>
<fileUpload></fileUpload>
<fileUpload
@
success=
"getCustomerPage()"
></fileUpload>
<!-- <div class="editer_input">
<q-input v-model="text" style="50px" maxlength="1000" type="textarea" placeholder="请填写跟进记录" />
</div>
-->
</div>-->
</div>
<div
style=
"display:flex;flex:1;flex-direction: column;overflow:hidden;"
>
<div
class=
"TimeLineDiv"
>
<q-timeline
color=
"primary"
>
<q-timeline-entry
v-for=
"(tItem,tIndex) in data.tripDataList"
:key=
"tIndex"
>
<
template
v-slot:title
>
<div
style=
"font-size:14px;"
>
{{
tItem
.
Description
}}
</div>
<div
style=
"font-size:14px;"
>
{{
tItem
.
Description
}}
</div>
</
template
>
<
template
v-slot:subtitle
>
<div
class=
"customUpdateTime"
>
<div>
{{
tItem
.
UpdateTime
}}
</div>
<div>
{{
tItem
.
UpdateByName
}}
</div>
<div>
{{
tItem
.
UpdateTime
}}
</div>
<div>
{{
tItem
.
UpdateByName
}}
</div>
</div>
</
template
>
<div>
{{tItem.Remark}}
<div>
{{ tItem.Remark }}
</div>
<div
class=
"img_box"
>
<img
v-for=
"(e,i) in tItem.ImageList"
:key=
"i"
:src=
"e"
class=
"img"
/>
</div>
<div
class=
"file_box"
>
<div
v-for=
"(e,i) in tItem.FileList"
:key=
"i"
class=
"flex items-center file_name"
>
附件:
<span
style=
"color:#000"
>
{{ e.FileName }}
</span>
<div
class=
"del_btn"
@
click=
"DownLoadFileByUrl(e.FileUrl,e.FileName)"
>
下载
</div>
</div>
</div>
</div>
</q-timeline-entry>
</q-timeline>
</div>
</div>
<div
style=
"margin:20px 0;"
>
<q-pagination
class=
"full-width justify-end"
v-model=
"customTripMsg.pageIndex"
color=
"primary"
:max=
"data.TripPageCount"
input
@
update:model-value=
"changePage"
/>
<q-pagination
class=
"full-width justify-end"
v-model=
"customTripMsg.pageIndex"
color=
"primary"
:max=
"data.TripPageCount"
input
@
update:model-value=
"changePage"
/>
</div>
</div>
</div>
...
...
@@ -308,21 +496,29 @@
<div
class=
"dialog-out-close"
@
click=
"closeCutomer"
>
<q-icon
name=
"iconfont icon-close"
size=
"15px"
/>
</div>
<labelgroup
v-if=
"isshowlabel"
:list=
"LableList"
@
close=
"isshowlabel = false"
@
submit=
"getlabel"
></labelgroup>
<labelgroup
v-if=
"isshowlabel"
:list=
"LableList"
@
close=
"isshowlabel = false"
@
submit=
"getlabel"
></labelgroup>
</div>
</q-dialog>
</template>
<
script
lang=
"ts"
>
import
{
import
{
ref
,
reactive
,
onMounted
}
from
'vue'
import
message
from
'@/utils/message'
import
customer2
from
'@/api/customer2'
import
labelgroup
from
'@/components/customer/label-group.vue'
import
fileUpload
from
'@/components/common/fileUpload.vue'
export
default
{
onMounted
,
provide
}
from
'vue'
import
{
DownLoadFileByUrl
}
from
'@/utils/upload'
import
message
from
'@/utils/message'
import
customer2
from
'@/api/customer2'
import
labelgroup
from
'@/components/customer/label-group.vue'
import
fileUpload
from
'@/components/common/fileUpload.vue'
export
default
{
props
:
{
//样式字符串
CustomerId
:
{
...
...
@@ -336,7 +532,7 @@
},
setup
(
props
,
ctx
)
{
let
isshowlabel
=
ref
(
false
)
//标签弹出显示
let
LableList
=
ref
<
Array
<
any
>
|
string
>
([])
//标签的数组
let
LableList
=
ref
<
Array
<
any
>
|
string
>
([])
//标签的数组
interface
msgParam
{
CustomerId
:
number
...
...
@@ -344,18 +540,19 @@
interface
dataParam
{
[
key
:
string
]:
any
}
const
msg
=
reactive
<
msgParam
>
({
const
msg
=
reactive
<
msgParam
>
({
CustomerId
:
props
.
CustomerId
})
provide
(
'CustomerId'
,
props
.
CustomerId
)
//客户信息保存数据
const
cutomMsg
=
reactive
<
dataParam
>
({
const
cutomMsg
=
reactive
<
dataParam
>
({
CustomerId
:
0
,
Type
:
2
,
CustomId
:
0
,
//自定义字段Id
Value
:
''
})
//客户旅程分页列表
const
customTripMsg
=
reactive
<
dataParam
>
({
const
customTripMsg
=
reactive
<
dataParam
>
({
pageIndex
:
1
,
pageSize
:
10
,
CustomerId
:
0
,
...
...
@@ -365,7 +562,7 @@
const
closeCutomer
=
()
=>
{
ctx
.
emit
(
'close'
);
}
const
data
=
reactive
<
dataParam
>
({
const
data
=
reactive
<
dataParam
>
({
dataList
:
{},
customData
:
[],
FiledDetailList
:
[],
...
...
@@ -473,7 +670,7 @@
const
getlabel
=
(
list
)
=>
{
isshowlabel
.
value
=
false
;
console
.
log
(
list
);
const
labelMsg
=
reactive
<
dataParam
>
({
const
labelMsg
=
reactive
<
dataParam
>
({
CustomerIds
:
0
,
LableIds
:
''
})
...
...
@@ -542,28 +739,29 @@
getCustomerTripType
,
customTripMsg
,
getckedType
,
changePage
}
changePage
,
DownLoadFileByUrl
}
}
}
</
script
>
<
style
lang=
"scss"
>
.custom_RModel
{
<
style
lang=
"scss"
scoped
>
.custom_RModel
{
width
:
500px
;
height
:
100%
;
}
}
.customMain
{
.customMain
{
width
:
1000px
!
important
;
display
:
flex
;
flex-direction
:
column
;
height
:
100
vh
;
padding
:
15px
17px
0
17px
;
background-color
:
#f4f4f6
;
}
}
.custom_Top
{
.custom_Top
{
width
:
100%
;
padding
:
22px
;
background
:
#fff
;
...
...
@@ -571,47 +769,47 @@
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
}
}
.custom_HLeft
{
.custom_HLeft
{
display
:
flex
;
}
}
.nameplate_avatar
{
.nameplate_avatar
{
width
:
60px
;
height
:
60px
;
flex-shrink
:
0
;
margin-right
:
14px
;
border-radius
:
5px
;
overflow
:
hidden
;
}
}
.F_16
{
.F_16
{
font-size
:
16px
;
}
}
.Name_List
{
.Name_List
{
display
:
flex
;
flex-direction
:
column
;
justify-content
:
space-around
;
overflow
:
hidden
;
}
}
.wechat_Name
{
.wechat_Name
{
color
:
#9999a8
;
display
:
flex
;
font-size
:
14px
;
}
}
.custom_Bottom
{
.custom_Bottom
{
margin-top
:
17px
;
flex
:
1
;
display
:
flex
;
margin-top
:
17px
;
overflow
:
hidden
;
}
}
.detail-info
{
.detail-info
{
flex-shrink
:
0
;
box-sizing
:
border-box
;
display
:
flex
;
...
...
@@ -623,13 +821,13 @@
background
:
#fff
;
border-radius
:
8px
8px
0
0
;
overflow
:
auto
;
}
}
.
detail-info
:
:-
webkit-scrollbar
{
.
detail-info
:
:-
webkit-scrollbar
{
display
:
none
;
}
}
.detail-travel
{
.detail-travel
{
width
:
100%
;
flex-grow
:
1
;
display
:
flex
;
...
...
@@ -638,22 +836,22 @@
background
:
#fff
;
border-radius
:
8px
8px
0
0
;
overflow
:
hidden
;
}
}
.info_title
{
.info_title
{
padding
:
0
22px
;
margin-bottom
:
20px
;
flex-shrink
:
0
;
font-size
:
16px
;
font-weight
:
700
;
font-family
:
Microsoft
YaHei
,
Avenir
,
Helvetica
,
Arial
,
sans-serif
!
important
}
font-family
:
Microsoft
YaHei
,
Avenir
,
Helvetica
,
Arial
,
sans-serif
!
important
;
}
.info_content
{
.info_content
{
margin-bottom
:
30px
;
}
}
.customer_info_Stage
{
.customer_info_Stage
{
width
:
100%
;
padding
:
0
7px
;
cursor
:
pointer
;
...
...
@@ -662,62 +860,62 @@
width
:
100%
;
padding
:
12px
22px
;
justify-content
:
space-between
;
}
}
.stage_label
{
.stage_label
{
color
:
#606266
;
flex-shrink
:
0
;
margin-right
:
10px
;
}
}
.stage_value
{
.stage_value
{
overflow
:
hidden
;
text-overflow
:
ellipsis
;
white-space
:
nowrap
;
}
}
.customer_info_component
{
.customer_info_component
{
width
:
100%
;
}
}
.edit_bar
{
.edit_bar
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
padding
:
12px
22px
;
}
}
.item_label
{
.item_label
{
color
:
#606266
;
flex-shrink
:
0
;
width
:
120px
;
font-size
:
14px
;
}
}
.edit_info_wrap
{
.edit_info_wrap
{
padding
:
0
22px
12px
;
}
}
.info_item
{
.info_item
{
position
:
relative
;
display
:
flex
;
padding
:
12px
22px
;
}
}
.item_value
{
.item_value
{
flex
:
1
;
font-size
:
14px
;
word-break
:
break-all
;
overflow
:
hidden
;
}
}
.custom_Line
{
.custom_Line
{
width
:
calc
(
100%
-
44px
);
margin
:
16px
22px
;
border-bottom
:
1px
solid
#d7d7d7
;
}
}
.custom_Edit
{
.custom_Edit
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
...
...
@@ -728,9 +926,9 @@
border-radius
:
4px
;
font-size
:
12px
;
cursor
:
pointer
;
}
}
.dialog-out-close
{
.dialog-out-close
{
background-color
:
#3470ff
;
border-top-left-radius
:
5px
;
border-bottom-left-radius
:
5px
;
...
...
@@ -742,86 +940,111 @@
top
:
0
;
left
:
-20px
;
text-align
:
center
;
}
}
.customTag_component
{
.customTag_component
{
margin-bottom
:
20px
;
display
:
flex
;
flex-wrap
:
wrap
;
align-items
:
center
;
padding
:
12px
22px
;
}
}
.tripTypeContent
{
.tripTypeContent
{
display
:
flex
;
margin-top
:
20px
;
overflow-x
:
auto
;
white-space
:
nowrap
;
}
}
.ckedClass
{
.ckedClass
{
color
:
#3470ff
;
font-weight
:
700
;
}
}
.tripTypeContent
div
{
.tripTypeContent
div
{
margin-right
:
20px
;
cursor
:
pointer
;
}
}
.TimeLineDiv
{
.TimeLineDiv
{
margin-top
:
20px
;
overflow
:
auto
;
// height:620px;
flex
:
1
;
height
:
100%
;
padding-right
:
20px
;
}
}
.q-timeline__title
{
.q-timeline__title
{
margin-bottom
:
5px
;
}
}
.customUpdateTime
{
.customUpdateTime
{
display
:
flex
;
justify-content
:
space-between
;
font-size
:
14px
;
color
:
#9696a6
;
}
}
.q-timeline__subtitle
{
.q-timeline__subtitle
{
opacity
:
1
;
font-weight
:
normal
;
}
}
.follow_Component
{
.follow_Component
{
padding
:
0
22px
;
margin-top
:
10px
;
width
:
100%
;
background-color
:
#f6f6f6
;
border-radius
:
5px
;
}
}
.q-textarea
.q-field__native
{
.q-textarea
.q-field__native
{
padding-top
:
0
;
}
}
.editer_input
.q-field__native
{
.editer_input
.q-field__native
{
height
:
50px
;
}
.detail_first
{
margin
:
0
22px
;
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.detail_Main
{
}
.detail_first
{
margin
:
0
22px
;
display
:
flex
;
flex-direction
:
column
;
height
:
100%
;
}
.detail_Main
{
display
:
flex
;
flex-direction
:
column
;
width
:
100%
;
height
:
100%
;
padding-top
:
10px
;
overflow
:
hidden
;
}
.img_box
{
margin-top
:
10px
;
.img
{
width
:
100px
;
height
:
100px
;
object-fit
:
cover
;
box-shadow
:
0px
10px
30px
0px
rgba
(
36
,
36
,
36
,
0
.2
);
margin
:
5px
;
border-radius
:
10px
;
}
}
.file_box
{
margin-top
:
10px
;
.file_name
{
font-size
:
14px
;
color
:
#9696A6
;
margin
:
3px
0
;
.del_btn
{
margin-left
:
10px
;
padding-left
:
5px
;
border-left
:
1px
solid
var
(
--
q-primary
);
color
:
var
(
--
q-primary
);
cursor
:
pointer
;
}
}
}
</
style
>
src/components/common/fileUpload.vue
View file @
c0b88b7e
<
template
>
<div>
<template
v-if=
"!data.isShowEdit"
>
<q-input
filled
bg-color=
"myInput"
@
focus=
"data.isShowEdit
=
true"
label=
"请输入跟进记录"
/>
<q-input
filled
bg-color=
"myInput"
@
focus=
"data.isShowEdit
=
true"
label=
"请输入跟进记录"
/>
</
template
>
<
template
v-else
>
<div
class=
"editer_input"
>
<q-input
v-model=
"text"
style=
"50px"
maxlength=
"1000"
type=
"textarea"
placeholder=
"请填写跟进记录"
/>
<!--
<div></div>
-->
<q-input
v-model=
"msg.Remark"
maxlength=
"1000"
type=
"textarea"
placeholder=
"请填写跟进记录"
/>
<div
class=
"file_box"
>
<div
class=
"img_list"
>
<div
v-for=
"(e,i) in msg.ImageList"
:key=
"i"
class=
"img_box"
>
<img
:src=
"e"
class=
"img"
/>
<q-icon
name=
"cancel"
color=
"primary"
class=
"del_icon"
@
click=
"delImg(i)"
/>
</div>
</div>
<div
class=
"file_list"
>
<div
v-for=
"(e,i) in msg.FileList"
:key=
"i"
class=
"flex items-center file_box"
>
<div
class=
"flex items-center"
>
附件:
<span
style=
"color:#333"
>
{{
e
.
FileName
}}
</span>
(
{{
e
.
size
}}
)
</div>
<div
class=
"del_btn"
@
click=
"delFile(i)"
>
删除
</div>
</div>
</div>
</div>
<div
class=
"file_Space"
>
<div
style=
"display:flex;align-items:center;"
>
<div>
<a-upload
v-model:file-list=
"data.imageList"
name=
"file"
:multiple=
"true"
action=
"https://www.mocky.io/v2/5cc8019d300000980a055e76"
@
change=
"uploadImg"
>
<a-upload
accept=
"image/*"
v-model:file-list=
"data.imageList"
name=
"file"
:multiple=
"true"
:show-upload-list=
"false"
:customRequest=
"customUploadImg"
>
<i
style=
"font-size:25px;cursor:pointer;"
class=
"iconfont icon-picture"
></i>
</a-upload>
</div>
<div
style=
"margin-left:8px;"
>
<a-upload
v-model:file-list=
"data.fileList"
name=
"file"
:multiple=
"true"
action=
"https://www.mocky.io/v2/5cc8019d300000980a055e76"
@
change=
"handleChange"
>
<a-upload
v-model:file-list=
"data.fileList"
name=
"file"
:multiple=
"true"
:show-upload-list=
"false"
:customRequest=
"customUploadFile"
>
<i
style=
"font-size:20px;cursor:pointer;"
class=
"iconfont icon-paperclip"
></i>
</a-upload>
</div>
</div>
<div>
<q-btn
color=
"myInput"
text-color=
"#000"
size=
"sm"
@
click=
"data.isShowEdit=false"
label=
"取消"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
label=
"确定"
/>
<q-btn
color=
"myInput"
text-color=
"#000"
size=
"sm"
@
click=
"data.isShowEdit = false"
label=
"取消"
/>
<q-btn
color=
"primary"
style=
"margin-left:10px;"
size=
"sm"
@
click=
"save"
label=
"确定"
/>
</div>
</div>
</div>
...
...
@@ -32,76 +66,129 @@
</div>
</template>
<
script
lang=
"ts"
>
import
{
import
{
reactive
,
}
from
'vue'
// import message from '@/utils/messag
e'
//
import customer2 from '@/api/customer2'
export
default
{
setup
()
{
interface
dataParam
{
inject
}
from
'vu
e'
import
customer2
from
'@/api/customer2'
import
massage
from
"@/utils/message"
import
{
UploadSelfFile
}
from
'@/utils/upload'
interface
dataParam
{
[
key
:
string
]:
any
}
interface
FileItem
{
uid
:
string
;
name
?:
string
;
status
?:
string
;
response
?:
string
;
url
?:
string
;
}
interface
FileInfo
{
file
:
FileItem
;
fileList
:
FileItem
[];
}
const
data
=
reactive
<
dataParam
>
({
}
export
default
{
setup
(
props
,
ctx
)
{
let
msg
=
reactive
<
dataParam
>
({
CustomerId
:
inject
(
'CustomerId'
),
Remark
:
""
,
ImageList
:
[],
FileList
:
[]
})
const
data
=
reactive
<
dataParam
>
({
isShowEdit
:
false
,
fileList
:
[],
imageList
:
[]
})
const
uploadImg
=
(
info
:
FileInfo
)
=>
{
if
(
info
.
file
.
status
!==
'uploading'
)
{
console
.
log
(
info
.
file
,
info
.
fileList
);
let
customUploadImg
=
(
file
)
=>
{
UploadSelfFile
(
'/horse'
,
file
.
file
,
(
res
)
=>
{
msg
.
ImageList
.
push
(
res
.
FileUrl
)
})
}
let
customUploadFile
=
(
file
)
=>
{
UploadSelfFile
(
'/horse'
,
file
.
file
,
(
res
)
=>
{
msg
.
FileList
.
push
({
FileName
:
res
.
FileName
,
FileUrl
:
res
.
FileUrl
,
size
:
res
.
Size
})
})
}
const
delImg
=
(
i
)
=>
{
msg
.
ImageList
.
splice
(
i
,
1
)
}
const
delFile
=
(
i
)
=>
{
msg
.
FileList
.
splice
(
i
,
1
)
}
const
save
=
()
=>
{
customer2
.
setCustomerTripFollowUpInfo
(
msg
).
then
((
res
)
=>
{
massage
.
successMsg
(
res
.
data
.
Message
)
msg
.
Remark
=
""
msg
.
ImageList
=
[]
msg
.
FileList
=
[]
ctx
.
emit
(
"success"
)
})
}
console
.
log
(
info
,
'info'
);
// if (info.file.status === 'done') {
// message.success(`${info.file.name} file uploaded successfully`);
// } else if (info.file.status === 'error') {
// message.error(`${info.file.name} file upload failed.`);
// }
};
// onMounted(() => {
// })
return
{
msg
,
data
,
uploadImg
}
customUploadImg
,
customUploadFile
,
delImg
,
delFile
,
UploadSelfFile
,
save
}
}
}
</
script
>
<
style
lang=
"scss"
>
.editer_input
{
<
style
lang=
"scss"
scoped
>
.editer_input
{
padding
:
5px
0
;
}
}
.myInput
{
.myInput
{
background-color
:
#f6f6f6
!
important
;
}
}
.file_box
{
margin-top
:
5px
;
.img_list
{
display
:
flex
;
flex-wrap
:
wrap
;
.img_box
{
width
:
40px
;
height
:
40px
;
margin
:
10px
;
.file_Space
{
position
:
relative
;
.img
{
width
:
100%
;
height
:
100%
;
overflow
:
hidden
;
object-fit
:
cover
;
}
.del_icon
{
font-size
:
18px
;
position
:
absolute
;
top
:
0
;
right
:
0
;
transform
:
translate
(
50%
,
-50%
);
}
}
}
.file_list
{
.file_box
{
font-size
:
14px
;
color
:
#9696a6
;
.del_btn
{
margin-left
:
10px
;
padding-left
:
5px
;
border-left
:
1px
solid
var
(
--
q-primary
);
color
:
var
(
--
q-primary
);
cursor
:
pointer
;
}
}
}
}
.file_Space
{
display
:
flex
;
justify-content
:
space-between
;
margin-top
:
10px
;
align-items
:
center
;
}
}
.q-field__control
{
.q-field__control
{
background-color
:
#f6f6f6
!
important
;
}
}
.q-field--filled
.q-field__control
:hover:before
{
.q-field--filled
.q-field__control
:hover:before
{
opacity
:
0
;
}
}
</
style
>
src/pages/customer/customerSetup.vue
View file @
c0b88b7e
<
template
>
<div
class=
"q-pa-md"
>
<q-page
padding
style=
"background: #FFF;border-radius: 10px;"
>
<q-page
padding
class=
"page"
:style-fn=
"myTweak(640)"
>
<q-tabs
v-model=
"tab"
dense
...
...
@@ -16,12 +16,12 @@
<q-tab
name=
"clue"
label=
"线索分配规则"
/>
<q-tab
name=
"phase"
label=
"客户阶段"
/>
</q-tabs>
<div
class=
"container fit"
>
<customer-Field
v-if=
"tab == 'field'"
></customer-Field>
<clue-rule
v-if=
"tab == 'clue'"
></clue-rule>
<customer-phase
v-if=
"tab == 'phase'"
></customer-phase>
<customerlabel
v-if=
"tab == 'label'"
></customerlabel>
</div>
</q-page>
</div>
</
template
>
...
...
@@ -48,15 +48,31 @@ export default defineComponent({
},
setup
()
{
let
tab
=
ref
<
string
>
(
'field'
)
if
(
router
.
currentRoute
.
value
.
query
&&
router
.
currentRoute
.
value
.
query
.
type
)
{
if
(
router
.
currentRoute
.
value
.
query
&&
router
.
currentRoute
.
value
.
query
.
type
)
{
tab
.
value
=
router
.
currentRoute
.
value
.
query
.
type
as
string
}
let
myTweak
=
(
offset
)
=>
{
return
{
minHeight
:
offset
?
`calc(100vh -
${
offset
}
px)`
:
'100vh'
}
}
return
{
tab
,
myTweak
}
}
})
</
script
>
<
style
lang=
"scss"
scoped
>
.page
{
background
:
#FFF
;
box-sizing
:
border-box
;
border-radius
:
10px
;
}
.container
{
box-sizing
:
border-box
;
overflow
:
scroll
;
}
</
style
>
\ No newline at end of file
src/store/modules/user/getters.ts
View file @
c0b88b7e
...
...
@@ -14,6 +14,9 @@ const userGetter = {
const
userInfo
=
store
.
state
.
user
.
userDetail
return
userInfo
},
getLoginUserInfo
()
{
return
store
.
state
.
user
.
loginUserInfo
}
}
type
UserGetter
=
typeof
userGetter
...
...
src/store/modules/user/state.ts
View file @
c0b88b7e
...
...
@@ -18,6 +18,7 @@ const state = {
roleId
:
0
,
userAvatar
:
''
},
loginUserInfo
:{},
currentTeamRoleId
:
0
,
// 当前所选择的团队用户所具有的权限
currentProjectRoleId
:
0
,
// 当前所选择的项目用户所具有的权限
menuList
:
[]
...
...
src/utils/common.ts
deleted
100644 → 0
View file @
4c99e7ee
import
{
Loading
}
from
'quasar'
interface
itemParams
{
[
propName
:
string
]:
any
}
/**
* 配置相关
*/
export
function
CommonConfig
()
{
return
{
FileConfig
:
{
FileUrl
:
'http://192.168.10.214:8130'
,
//本地服务器文件预览地址
UploadUrl
:
"http://192.168.10.214:8120"
,
//本地上传文件地址
}
}
}
/**
* 上传文件
*/
export
function
UploadSelfFile
(
path
,
file
,
callback
,
configObj
)
{
//用户登录缓存
const
cacheInfo
:
itemParams
=
JSON
.
parse
(
window
.
localStorage
[
"loginUserInfo"
]);
//上传配置
let
uploadConfig
:
itemParams
=
{};
if
(
cacheInfo
&&
cacheInfo
.
data
&&
cacheInfo
.
data
.
UploadConfig
)
{
uploadConfig
=
cacheInfo
.
data
.
UploadConfig
;
}
//获取文件扩展名
// const index:string = file.name.lastIndexOf(".");
// let suffix:string = file.name.substr(index);
// const MyDate:any = new Date()
// var timestamp1 = Date.parse(MyDate) + "_" + (Math.ceil(Math.random() * 1000));
const
str
=
'/Test'
;
const
newPath
=
"/EduSystem"
+
str
+
'/Upload/'
+
path
;
const
uploadLoadding
=
Loading
;
uploadLoadding
.
show
({
message
:
'正在上传文件,请稍后...'
})
if
(
uploadConfig
)
{
switch
(
uploadConfig
.
StoreType
)
{
//上传文件到腾讯云
// case 1:
// newPath += "/" + timestamp1 + "" + suffix;
// UploadFileToTencent(uploadConfig, newPath, file, uploadLoadding, callback);
// break;
// //上传文件到阿里云
// case 2:
// newPath += "/" + timestamp1 + "" + suffix;
// UploadFileToALi(uploadConfig, newPath, file, uploadLoadding, callback);
// break;
//上传文件到自己文件服务器
case
3
:
UploadFileToSystem
(
uploadConfig
,
newPath
,
file
,
uploadLoadding
,
callback
,
configObj
);
break
;
}
}
}
/**
* 上传文件到本地文件系统
*/
export
function
UploadFileToSystem
(
uploadConfig
,
fileFullPath
,
fileObj
,
uploadLoadding
,
successCall
,
configObj
)
{
const
fileConfig
:
itemParams
=
CommonConfig
();
const
locationName
:
string
=
window
.
location
.
hostname
;
if
(
locationName
.
indexOf
(
'localhost'
)
!==
-
1
)
{
uploadConfig
.
UploadDomain
=
fileConfig
.
FileConfig
.
UploadUrl
;
uploadConfig
.
CustomDomain
=
fileConfig
.
FileConfig
.
FileUrl
;
}
let
url
=
uploadConfig
.
UploadDomain
+
"/Upload?filePath="
+
fileFullPath
;
if
(
configObj
)
{
//是否转换图片
if
(
configObj
.
isTrans
&&
configObj
.
isTrans
==
1
)
{
url
+=
"&isTrans=1"
}
if
(
configObj
.
isCreateCover
&&
configObj
.
isCreateCover
==
1
)
{
url
+=
"&isCreateCover=1"
}
}
const
formData
=
new
FormData
()
formData
.
append
(
'myfile'
,
fileObj
)
const
xhr
=
new
XMLHttpRequest
()
xhr
.
onload
=
function
()
{
uploadLoadding
.
hide
();
const
jsonObj
:
itemParams
=
JSON
.
parse
(
xhr
.
responseText
);
if
(
jsonObj
.
StatusCode
===
1
&&
successCall
)
{
const
tempArray
:
any
=
[];
if
(
jsonObj
.
OtherFile
&&
jsonObj
.
OtherFile
.
length
>
0
)
{
jsonObj
.
OtherFile
.
forEach
(
item
=>
{
tempArray
.
push
(
uploadConfig
.
CustomDomain
+
item
);
})
}
const
uploadResult
:
itemParams
=
{
Code
:
1
,
FileName
:
fileObj
.
name
,
FileUrl
:
uploadConfig
.
CustomDomain
+
jsonObj
.
FilePath
,
VideoCoverImg
:
uploadConfig
.
CustomDomain
+
jsonObj
.
VideoCoverImg
,
ExtFile
:
tempArray
}
if
(
successCall
)
{
successCall
(
uploadResult
);
}
}
}
xhr
.
open
(
'post'
,
url
,
true
)
xhr
.
send
(
formData
)
}
// export function UploadFileToTencent(){
// }
// export function UploadFileToALi(){
// }
\ No newline at end of file
src/utils/upload.ts
0 → 100644
View file @
c0b88b7e
import
Axios
from
'@/api/axios'
import
{
getStoreGetter
}
from
'@/store/utils'
import
{
Loading
}
from
'quasar'
/**
* 配置相关
*/
export
function
CommonConfig
()
{
return
{
FileConfig
:
{
FileUrl
:
'http://192.168.20.214:8130'
,
//本地服务器文件预览地址
UploadUrl
:
'http://192.168.20.214:8120'
//本地上传文件地址
}
}
}
/**
* 上传文件
*/
// interface uploadConfigParams {
// }
//用户登录缓存
const
cacheInfo
=
getStoreGetter
(
'user'
,
'getLoginUserInfo'
)
export
function
UploadSelfFile
(
path
,
file
,
callback
,
configObj
?)
{
//上传配置
let
uploadConfig
:
any
=
{}
if
(
cacheInfo
.
UploadConfig
)
{
uploadConfig
=
JSON
.
parse
(
JSON
.
stringify
(
cacheInfo
.
UploadConfig
))
console
.
log
(
'上传配置'
,
uploadConfig
)
}
//获取文件扩展名
const
index
=
file
.
name
.
lastIndexOf
(
'.'
)
const
suffix
=
file
.
name
.
substr
(
index
)
const
timestamp1
=
Date
.
parse
(
new
Date
().
toString
())
+
'_'
+
Math
.
ceil
(
Math
.
random
()
*
1000
)
const
str
=
'/Test'
let
newPath
=
'/EduSystem'
+
str
+
'/Upload/'
+
path
const
uploadLoadding
=
Loading
uploadLoadding
.
show
({
message
:
'正在上传文件,请稍后...'
})
if
(
uploadConfig
)
{
switch
(
uploadConfig
.
StoreType
)
{
//上传文件到腾讯云
case
1
:
newPath
+=
'/'
+
timestamp1
+
''
+
suffix
UploadFileToTencent
(
uploadConfig
,
newPath
,
file
,
uploadLoadding
,
callback
)
break
//上传文件到阿里云
case
2
:
newPath
+=
'/'
+
timestamp1
+
''
+
suffix
UploadFileToALi
(
uploadConfig
,
newPath
,
file
,
uploadLoadding
,
callback
)
break
//上传文件到自己文件服务器
case
3
:
UploadFileToSystem
(
uploadConfig
,
newPath
,
file
,
uploadLoadding
,
callback
,
configObj
)
break
}
}
}
//上传视频文件到本地服务器
export
function
UploadViittoFile
(
path
,
file
,
callback
)
{
const
uploadLoadding
=
Loading
uploadLoadding
.
show
({
message
:
'正在上传文件,请稍后...'
})
const
fileConfig
=
CommonConfig
()
let
viewFileUrl
=
fileConfig
.
FileConfig
.
FileUrl
let
vtUploadUrl
=
fileConfig
.
FileConfig
.
UploadUrl
const
locationName
=
window
.
location
.
hostname
if
(
locationName
.
indexOf
(
'testerp.oytour'
)
!==
-
1
)
{
vtUploadUrl
=
'http://upload.oytour.com'
viewFileUrl
=
'https://imgfile.oytour.com'
}
else
if
(
locationName
.
indexOf
(
'oytour'
)
!==
-
1
)
{
vtUploadUrl
=
'http://upload.oytour.com'
viewFileUrl
=
'https://imgfile.oytour.com'
}
else
if
(
locationName
.
indexOf
(
'kookaku'
)
!==
-
1
)
{
vtUploadUrl
=
'https://upload.oytour.com'
viewFileUrl
=
'https://imgfile.oytour.com'
}
const
UploadConfig
=
{
Bucket
:
'系统'
,
CustomDomain
:
viewFileUrl
,
Region
:
'成都'
,
SecretId
:
'SecreId'
,
SecretKey
:
'SecreKey'
,
StoreType
:
3
,
UploadDomain
:
vtUploadUrl
}
const
configObj
=
{
isCreateCover
:
1
}
UploadFileToSystem
(
UploadConfig
,
path
,
file
,
uploadLoadding
,
callback
,
configObj
)
}
// 上传Blob视频文件到本地服务器
export
function
UploadViittoBlobFile
(
path
,
file
,
callback
)
{
const
uploadLoadding
=
Loading
uploadLoadding
.
show
({
message
:
'正在上传文件,请稍后...'
})
let
viewFileUrl
=
'http://192.168.20.214:8130'
let
vtUploadUrl
=
'http://192.168.20.214:8120/upload/UploadBlob'
const
locationName
=
window
.
location
.
hostname
if
(
locationName
.
indexOf
(
'testerp.oytour'
)
!==
-
1
)
{
vtUploadUrl
=
'http://upload.oytour.com/upload/UploadBlob'
viewFileUrl
=
'https://imgfile.oytour.com'
}
else
if
(
locationName
.
indexOf
(
'oytour'
)
!==
-
1
)
{
vtUploadUrl
=
'http://upload.oytour.com/upload/UploadBlob'
viewFileUrl
=
'https://imgfile.oytour.com'
}
const
UploadConfig
=
{
Bucket
:
'系统'
,
CustomDomain
:
viewFileUrl
,
Region
:
'成都'
,
SecretId
:
'SecreId'
,
SecretKey
:
'SecreKey'
,
StoreType
:
3
,
UploadDomain
:
vtUploadUrl
}
const
configObj
=
{
isCreateCover
:
1
}
UploadBolbFileToSystem
(
UploadConfig
,
path
,
file
,
uploadLoadding
,
callback
,
configObj
)
}
/**
* 上传bolb文件到本地文件系统
*/
export
function
UploadBolbFileToSystem
(
uploadConfig
,
fileFullPath
,
fileObj
,
uploadLoadding
,
successCall
,
configObj
)
{
let
url
=
uploadConfig
.
UploadDomain
+
'/Upload?filePath='
+
fileFullPath
if
(
configObj
)
{
//是否转换图片
if
(
configObj
.
isTrans
&&
configObj
.
isTrans
==
1
)
{
url
+=
'&isTrans=1'
}
if
(
configObj
.
isCreateCover
&&
configObj
.
isCreateCover
==
1
)
{
url
+=
'&isCreateCover=1'
}
}
const
formData
=
new
FormData
()
formData
.
append
(
'myfile'
,
fileObj
)
const
xhr
=
new
XMLHttpRequest
()
xhr
.
onload
=
function
()
{
uploadLoadding
.
hide
()
const
jsonObj
:
any
=
JSON
.
parse
(
xhr
.
responseText
)
if
((
jsonObj
.
StatusCode
===
1
||
jsonObj
.
StatusCode
===
0
)
&&
successCall
)
{
const
tempArray
:
Array
<
any
>
=
[]
if
(
jsonObj
.
OtherFile
&&
jsonObj
.
OtherFile
.
length
>
0
)
{
jsonObj
.
OtherFile
.
forEach
(
item
=>
{
tempArray
.
push
(
uploadConfig
.
CustomDomain
+
item
)
})
}
const
uploadResult
=
{
Code
:
1
,
FileName
:
fileObj
.
name
,
FileUrl
:
uploadConfig
.
CustomDomain
+
'/'
+
jsonObj
.
FilePath
,
VideoCoverImg
:
uploadConfig
.
CustomDomain
+
jsonObj
.
VideoCoverImg
,
ExtFile
:
tempArray
}
if
(
successCall
)
{
successCall
(
uploadResult
)
}
}
}
xhr
.
open
(
'post'
,
url
,
true
)
xhr
.
send
(
formData
)
}
/**
* 上传文件到本地文件系统
*/
export
function
UploadFileToSystem
(
uploadConfig
,
fileFullPath
,
fileObj
,
uploadLoadding
,
successCall
,
configObj
)
{
// const fileConfig = CommonConfig()
// const locationName = window.location.hostname
// if (locationName.indexOf('localhost') !== -1) {
// uploadConfig.UploadDomain = fileConfig.FileConfig.UploadUrl
// uploadConfig.CustomDomain = fileConfig.FileConfig.FileUrl
// }
let
url
=
uploadConfig
.
UploadDomain
+
'/Upload?filePath='
+
fileFullPath
if
(
configObj
)
{
//是否转换图片
if
(
configObj
.
isTrans
&&
configObj
.
isTrans
==
1
)
{
url
+=
'&isTrans=1'
}
if
(
configObj
.
isCreateCover
&&
configObj
.
isCreateCover
==
1
)
{
url
+=
'&isCreateCover=1'
}
}
const
formData
=
new
FormData
()
formData
.
append
(
'myfile'
,
fileObj
)
const
xhr
=
new
XMLHttpRequest
()
xhr
.
onload
=
function
()
{
uploadLoadding
.
hide
()
const
jsonObj
=
JSON
.
parse
(
xhr
.
responseText
)
if
(
jsonObj
.
StatusCode
===
1
&&
successCall
)
{
const
tempArray
:
Array
<
any
>
=
[]
if
(
jsonObj
.
OtherFile
&&
jsonObj
.
OtherFile
.
length
>
0
)
{
jsonObj
.
OtherFile
.
forEach
(
item
=>
{
tempArray
.
push
(
uploadConfig
.
CustomDomain
+
item
)
})
}
console
.
log
(
'obj'
,
fileObj
)
const
uploadResult
=
{
Code
:
1
,
Size
:
(
fileObj
.
size
/
1000
).
toFixed
(
2
)
+
'KB'
,
FileName
:
fileObj
.
name
,
FileUrl
:
uploadConfig
.
CustomDomain
+
jsonObj
.
FilePath
,
VideoCoverImg
:
uploadConfig
.
CustomDomain
+
jsonObj
.
VideoCoverImg
,
ExtFile
:
tempArray
}
if
(
successCall
)
{
successCall
(
uploadResult
)
}
}
}
xhr
.
open
(
'post'
,
url
,
true
)
xhr
.
send
(
formData
)
}
/**
* 上传文件到阿里云
*/
export
function
UploadFileToALi
(
uploadConfig
,
fileFullPath
,
fileObj
,
uploadLoadding
,
successCall
)
{
// const OSS = require('ali-oss')
// // const oss = new OSS({
// // region: uploadConfig.Region,
// // accessKeyId: uploadConfig.SecretId,
// // accessKeySecret: uploadConfig.SecretKey,
// // bucket: uploadConfig.Bucket
// // })
// // const result = oss
// .multipartUpload(fileFullPath, fileObj, {
// progress: function (p) {
// console.log('ali',p)
// }
// })
// .then(res => {
// uploadLoadding.hide()
// const uploadResult = {
// Code: 1,
// FileName: fileObj.name,
// FileUrl: res.res.requestUrls[0].split('?')[0].replace('http', 'https')
// }
if
(
successCall
)
{
// successCall(uploadResult)
}
// })
}
/**
* 上传文件到腾讯云
*/
export
function
UploadFileToTencent
(
uploadConfig
,
fileFullPath
,
fileObj
,
uploadLoadding
,
successCall
)
{
// const COS = require('cos-js-sdk-v5')
// const cos = new COS({
// SecretId: uploadConfig.SecretId,
// SecretKey: uploadConfig.SecretKey
// })
// cos.putObject(
// {
// Bucket: uploadConfig.Bucket,
// Region: uploadConfig.Region, //存储桶所在地域,必须字段
// Key: fileFullPath, //文件名
// StorageClass: 'STANDARD',
// Body: fileObj, // 上传文件对象
// onProgress: function (progressData) {
// console.log('progressData', progressData)
// }
// },
// function (err, data) {
// uploadLoadding.hide()
// if (data && data.statusCode == 200) {
// const uploadResult = {
// Code: 1,
// FileName: fileObj.name,
// FileUrl: 'https://' + data.Location
// }
if
(
successCall
)
{
// successCall(uploadResult)
}
// } else {
// /*上传文件异常*/
// console.log(err || data)
// }
// }
// )
}
/***
* 本地文件下载
*/
export
function
downloadLocalFile
(
fileName
,
filePath
)
{
const
a
=
document
.
createElement
(
'a'
)
a
.
setAttribute
(
'download'
,
''
)
const
url
=
process
.
env
.
API
a
.
setAttribute
(
'href'
,
url
+
'/Upload/DownloadFileForPdf?fileName='
+
fileName
+
'.pdf&fPath='
+
filePath
)
a
.
click
()
}
/**
* 获取文件扩展名
*/
export
function
getFileExt
(
filename
)
{
const
index
=
filename
.
lastIndexOf
(
'.'
)
const
suffix
=
filename
.
substr
(
index
+
1
)
return
suffix
}
/**
*
* 教育文件下载
*/
export
function
EduDownLoad
(
cmd
,
msg
,
fileName
,
callBack
)
{
return
Axios
({
url
:
cmd
,
method
:
'post'
,
data
:
msg
,
headers
:
{
responseType
:
'arraybuffer'
}
}).
then
(
res
=>
{
const
blob
=
new
Blob
([
res
.
data
],
{
type
:
'application/vnd.ms-excel'
})
const
url
=
URL
.
createObjectURL
(
blob
)
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
url
link
.
setAttribute
(
'download'
,
fileName
)
document
.
body
.
appendChild
(
link
)
link
.
click
()
if
(
callBack
)
{
const
result
=
{
Code
:
1
}
callBack
(
result
)
}
})
}
export
function
DownLoadFileByUrl
(
url
,
fileName
)
{
const
link
=
document
.
createElement
(
'a'
)
link
.
href
=
url
link
.
setAttribute
(
'download'
,
fileName
)
document
.
body
.
appendChild
(
link
)
link
.
click
()
}
/**
* 上传文件 企微写死阿里云
*/
// export function wechatUploadSelfFile(path, file, callback) {
// //用户登录缓存
// //配置写死的 腾讯云
// const uploadConfig = {
// Region: 'ap-chengdu',
// SecretId: 'AKIDDPnbIzi8C1eqEOPP8dw6MNAg9H9ldDKd',
// SecretKey: 'PdcLtOjslUzNFYdU4OSI1fKtdHpFT2Ob',
// Bucket: 'viitto-1301420277'
// }
// //获取文件扩展名
// const index = file.name.lastIndexOf('.')
// const suffix = file.name.substr(index)
// const timestamp1 = Date.parse(new Date()) + '_' + Math.ceil(Math.random() * 1000)
// const str = '/Test'
// let newPath = '/EduSystem' + str + '/Upload/' + path
// const uploadLoadding = Loading
// uploadLoadding.show({
// message: '正在上传文件,请稍后...'
// })
// if (uploadConfig) {
// newPath += '/' + timestamp1 + '' + suffix
// UploadFileToTencent(uploadConfig, newPath, file, uploadLoadding, callback)
// }
// }
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