Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
S
standalone-anyremote
Overview
Overview
Details
Activity
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
qlintonger xeno
standalone-anyremote
Commits
7511e0c8
Commit
7511e0c8
authored
May 08, 2024
by
pangchong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 事件详情开发
parent
1228eb37
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
324 additions
and
216 deletions
+324
-216
components.d.ts
+1
-0
src/assets/css/style.css
+11
-4
src/components/file-preview/index.vue
+49
-0
src/utils/dataTypes/dateRelated/formatDate.ts
+44
-58
src/views/remote/contacts/constants/data.config.ts
+23
-14
src/views/remote/contacts/eventDetails.vue
+99
-106
src/views/remote/contacts/eventInfo.vue
+18
-2
src/views/remote/contacts/eventList.vue
+76
-25
src/views/remote/videoCall/chatDetails.vue
+3
-7
No files found.
components.d.ts
View file @
7511e0c8
...
...
@@ -36,5 +36,6 @@ declare module 'vue' {
RangePickey
:
(
typeof
import
(
'./src/components/range-pickey/index.vue'
))[
'default'
]
GlobalAvatar
:
(
typeof
import
(
'./src/components/global-avatar/index.vue'
))[
'default'
]
GlobalModel
:
(
typeof
import
(
'./src/components/global-model/index.vue'
))[
'default'
]
FilePreview
:
(
typeof
import
(
'./src/components/file-preview/index.vue'
))[
'default'
]
}
}
src/assets/css/style.css
View file @
7511e0c8
/* HTML5 display-role reset for older browsers */
html
,
body
,
div
,
...
...
@@ -83,8 +84,6 @@ video {
padding
:
0
;
border
:
0
;
}
/* HTML5 display-role reset for older browsers */
article
,
aside
,
details
,
...
...
@@ -137,6 +136,7 @@ div {
box-sizing
:
border-box
;
}
/* 滚动轴 */
::-webkit-scrollbar
{
border-radius
:
10px
;
-moz-border-radius
:
10px
;
...
...
@@ -144,7 +144,6 @@ div {
width
:
7px
;
height
:
7px
;
}
::-webkit-scrollbar-thumb
{
border-radius
:
10px
;
-moz-border-radius
:
10px
;
...
...
@@ -153,10 +152,18 @@ div {
background-clip
:
padding-box
;
min-height
:
28px
;
}
::-webkit-scrollbar-thumb:hover
{
border-radius
:
10px
;
-moz-border-radius
:
10px
;
-webkit-border-radius
:
10px
;
background-color
:
var
(
--color-fill-4
);
}
/* arco.design */
.arco-table-th
{
background
:
var
(
--color-fill-1
);
border-bottom
:
1px
solid
var
(
--color-neutral-3
);
}
.arco-table-td
{
background
:
inherit
;
}
src/components/file-preview/index.vue
0 → 100644
View file @
7511e0c8
<
template
>
<global-model
v-model:visible=
"showPreview"
width=
"80%"
:footer=
"false"
modal-class=
"file-preview"
:title=
"file.title"
:onClose=
"onClose"
>
<div
style=
"height: 80vh"
>
<template
v-if=
"file.type == 'image'"
>
<a-image
:preview=
"false"
width=
"100%"
height=
"100%"
:src=
"file.src"
></a-image>
</
template
>
<
template
v-else-if=
"file.type == 'video'"
>
<video
width=
"100%"
height=
"100%"
:src=
"file.src"
controls=
"true"
></video>
</
template
>
<
template
v-else
>
<iframe
:src=
"file.src"
frameborder=
"0"
width=
"100%"
height=
"100%"
></iframe>
</
template
>
</div>
</global-model>
</template>
<
script
setup
lang=
"ts"
>
const
showPreview
=
ref
(
false
)
interface
FileType
{
title
?:
string
src
:
string
type
?:
'image'
|
'file'
|
'video'
}
const
file
=
reactive
<
FileType
>
({
title
:
'预览'
,
src
:
''
,
type
:
'image'
})
const
open
=
(
params
:
FileType
)
=>
{
Object
.
assign
(
file
,
params
)
showPreview
.
value
=
true
}
const
onClose
=
()
=>
{
Object
.
assign
(
file
,
{
title
:
'预览'
,
src
:
''
,
type
:
'image'
})
}
defineExpose
({
open
})
</
script
>
<
style
lang=
"less"
>
.file-preview
.arco-modal-body
{
padding
:
16px
;
}
</
style
>
src/utils/dataTypes/dateRelated/formatDate.ts
View file @
7511e0c8
import
Day
from
'@/utils/dayjs'
/**
* 通用的格式化时间
* @param input {String | Date | Number | null} 可以被传入Date构造函数的任意数据
...
...
@@ -5,37 +7,22 @@
* @param defaultVal {String} 当传入数据不合法时的默认值,默认为'--’
* @return String 格式化之后的字符串
*/
export
const
formatDate
=
(
input
:
Date
|
string
|
number
|
null
,
until
=
"all"
,
defaultVal
:
string
=
'--'
):
string
=>
{
export
const
formatDate
=
(
input
:
Date
|
string
|
number
|
null
,
until
=
'all'
,
defaultVal
:
string
=
'--'
):
string
=>
{
// @ts-ignore
if
(
input
===
null
||
input
===
0
||
input
<
0
)
return
defaultVal
;
const
date
=
new
Date
(
input
);
const
year
=
date
.
getFullYear
();
const
month
=
date
.
getMonth
()
+
1
;
const
day
=
date
.
getDate
();
const
hour
=
date
.
getHours
();
const
min
=
date
.
getMinutes
();
const
sec
=
date
.
getSeconds
();
if
(
until
===
'day'
)
return
`
${
year
}
-
${
month
.
toString
().
padStart
(
2
,
"0"
)}
-
${
day
.
toString
()
.
padStart
(
2
,
"0"
)}
`
if
(
until
===
"min"
)
{
return
`
${
year
}
-
${
month
.
toString
().
padStart
(
2
,
"0"
)}
-
${
day
.
toString
()
.
padStart
(
2
,
"0"
)}
${
hour
.
toString
().
padStart
(
2
,
"0"
)}
:
${
min
.
toString
()
.
padStart
(
2
,
"0"
)}
`
;
if
(
input
===
null
||
input
===
0
||
input
<
0
)
return
defaultVal
const
date
=
new
Date
(
input
)
const
year
=
date
.
getFullYear
()
const
month
=
date
.
getMonth
()
+
1
const
day
=
date
.
getDate
()
const
hour
=
date
.
getHours
()
const
min
=
date
.
getMinutes
()
const
sec
=
date
.
getSeconds
()
if
(
until
===
'day'
)
return
`
${
year
}
-
${
month
.
toString
().
padStart
(
2
,
'0'
)}
-
${
day
.
toString
().
padStart
(
2
,
'0'
)}
`
if
(
until
===
'min'
)
{
return
`
${
year
}
-
${
month
.
toString
().
padStart
(
2
,
'0'
)}
-
${
day
.
toString
().
padStart
(
2
,
'0'
)}
${
hour
.
toString
().
padStart
(
2
,
'0'
)}
:
${
min
.
toString
().
padStart
(
2
,
'0'
)}
`
}
return
`
${
year
}
-
${
month
.
toString
().
padStart
(
2
,
"0"
)}
-
${
day
.
toString
()
.
padStart
(
2
,
"0"
)}
${
hour
.
toString
().
padStart
(
2
,
"0"
)}
:
${
min
.
toString
()
.
padStart
(
2
,
"0"
)}
:
${
sec
.
toString
().
padStart
(
2
,
"0"
)}
`
;
};
return
`
${
year
}
-
${
month
.
toString
().
padStart
(
2
,
'0'
)}
-
${
day
.
toString
().
padStart
(
2
,
'0'
)}
${
hour
.
toString
().
padStart
(
2
,
'0'
)}
:
${
min
.
toString
().
padStart
(
2
,
'0'
)}
:
${
sec
.
toString
().
padStart
(
2
,
'0'
)}
`
}
/**
* 加上年月日时分秒的中国本土化的格式化时间
...
...
@@ -44,34 +31,34 @@ export const formatDate = (
* @param defaultVal {String} 当传入数据不合法时的默认值,默认为'--’
* @return String 格式化之后的字符串
*/
export
const
formatDateZh
=
(
input
:
Date
|
string
|
number
|
null
,
until
=
"all"
,
defaultVal
:
string
=
'--'
):
string
=>
{
export
const
formatDateZh
=
(
input
:
Date
|
string
|
number
|
null
,
until
=
'all'
,
defaultVal
:
string
=
'--'
):
string
=>
{
// @ts-ignore
if
(
input
===
null
||
input
===
0
||
input
<
0
)
return
defaultVal
;
const
date
=
new
Date
(
input
);
const
year
=
date
.
getFullYear
();
const
month
=
date
.
getMonth
()
+
1
;
const
day
=
date
.
getDate
();
const
hour
=
date
.
getHours
();
const
min
=
date
.
getMinutes
();
const
sec
=
date
.
getSeconds
();
if
(
until
===
'day'
)
return
`
${
year
}
年
${
month
.
toString
().
padStart
(
2
,
"0"
)}
月
${
day
.
toString
()
.
padStart
(
2
,
"0"
)}
日`
if
(
until
===
"min"
)
{
return
`
${
year
}
年
${
month
.
toString
().
padStart
(
2
,
"0"
)}
月
${
day
.
toString
()
.
padStart
(
2
,
"0"
)}
日
${
hour
.
toString
().
padStart
(
2
,
"0"
)}
:
${
min
.
toString
()
.
padStart
(
2
,
"0"
)}
`
;
if
(
input
===
null
||
input
===
0
||
input
<
0
)
return
defaultVal
const
date
=
new
Date
(
input
)
const
year
=
date
.
getFullYear
()
const
month
=
date
.
getMonth
()
+
1
const
day
=
date
.
getDate
()
const
hour
=
date
.
getHours
()
const
min
=
date
.
getMinutes
()
const
sec
=
date
.
getSeconds
()
if
(
until
===
'day'
)
return
`
${
year
}
年
${
month
.
toString
().
padStart
(
2
,
'0'
)}
月
${
day
.
toString
().
padStart
(
2
,
'0'
)}
日`
if
(
until
===
'min'
)
{
return
`
${
year
}
年
${
month
.
toString
().
padStart
(
2
,
'0'
)}
月
${
day
.
toString
().
padStart
(
2
,
'0'
)}
日
${
hour
.
toString
().
padStart
(
2
,
'0'
)}
:
${
min
.
toString
().
padStart
(
2
,
'0'
)}
`
}
return
`
${
year
}
年
${
month
.
toString
().
padStart
(
2
,
"0"
)}
月
${
day
return
`
${
year
}
年
${
month
.
toString
().
padStart
(
2
,
'0'
)}
月
${
day
.
toString
().
padStart
(
2
,
'0'
)}
日
${
hour
.
toString
().
padStart
(
2
,
'0'
)}
:
${
min
.
toString
()
.
padStart
(
2
,
"0"
)}
日
${
hour
.
toString
().
padStart
(
2
,
"0"
)}
:
${
min
.
toString
()
.
padStart
(
2
,
"0"
)}
:
${
sec
.
toString
().
padStart
(
2
,
"0"
)}
`
;
};
\ No newline at end of file
.
padStart
(
2
,
'0'
)}
:
${
sec
.
toString
().
padStart
(
2
,
'0'
)}
`
}
/**
* 时间戳格式化
* 1715072168340 => 2024-05-07 16:56:08
*/
export
const
timeStampFormat
=
(
timeStamp
:
string
|
number
,
opt
?:
{
format
?:
string
}):
string
=>
{
if
(
!
timeStamp
)
{
return
''
}
timeStamp
=
parseInt
(
String
(
timeStamp
))
const
format
=
opt
?.
format
||
'YYYY-MM-DD HH:mm:ss'
return
Day
(
timeStamp
).
format
(
format
)
}
src/views/remote/contacts/constants/data.config.ts
View file @
7511e0c8
...
...
@@ -11,7 +11,8 @@ export const eventListColumns: TableColumnData[] = [
{
title
:
'事件名称'
,
dataIndex
:
'title'
,
slotName
:
'title'
slotName
:
'title'
,
width
:
400
},
{
title
:
'发起人'
,
...
...
@@ -58,22 +59,26 @@ export const eventDetailsColumns1: TableColumnData[] = [
{
title
:
'文件名'
,
align
:
'center'
,
dataIndex
:
'fileName'
dataIndex
:
'fileName'
,
slotName
:
'fileName'
},
{
title
:
'文件大小'
,
align
:
'center'
,
dataIndex
:
'fileSize'
dataIndex
:
'fileSize'
,
slotName
:
'fileSize'
},
{
title
:
'发送人'
,
align
:
'center'
,
dataIndex
:
'fromId'
dataIndex
:
'fromId'
,
slotName
:
'fromId'
},
{
title
:
'发送时间'
,
align
:
'center'
,
dataIndex
:
'updatedTime'
dataIndex
:
'createdTime'
,
slotName
:
'createdTime'
},
{
title
:
'操作'
,
...
...
@@ -87,27 +92,31 @@ export const eventDetailsColumns2: TableColumnData[] = [
{
title
:
'文件名'
,
align
:
'center'
,
dataIndex
:
'fileName'
dataIndex
:
'fileName'
,
slotName
:
'fileName'
},
{
title
:
'文件大小'
,
align
:
'center'
,
dataIndex
:
'fileSize'
},
{
title
:
'视频时长'
,
align
:
'center'
,
dataIndex
:
'videoDuration'
dataIndex
:
'fileSize'
,
slotName
:
'fileSize'
},
// {
// title: '视频时长',
// align: 'center',
// dataIndex: 'videoDuration'
// },
{
title
:
'发送人'
,
align
:
'center'
,
dataIndex
:
'fromId'
dataIndex
:
'fromId'
,
slotName
:
'fromId'
},
{
title
:
'发送时间'
,
align
:
'center'
,
dataIndex
:
'updatedTime'
dataIndex
:
'createdTime'
,
slotName
:
'createdTime'
},
{
title
:
'操作'
,
...
...
src/views/remote/contacts/eventDetails.vue
View file @
7511e0c8
<
template
>
<div
class=
"g-block ml-4 px-4"
>
<template
v-if=
"details && record"
>
<div
class=
"flex justify-between"
>
<div
class=
"flex items-center space-x-8"
>
<icon-left
:size=
"20
"
/>
<span>
2023-10-26 10:15:54通话事件
</span>
<icon-left
:size=
"20"
@
click=
"showList"
class=
"cursor-pointer
"
/>
<span>
{{
record
.
title
}}
</span>
</div>
<a-radio-group
v-model=
"active"
>
<template
v-for=
"(item, i) in tabs"
:key=
"i"
>
...
...
@@ -17,132 +18,75 @@
</div>
<div
class=
"flex items-center py-8"
>
<a-avatar-group
:size=
"40"
>
<global-avatar
:icon-size=
"15"
></global-avatar>
<global-avatar
:icon-size=
"15"
></global-avatar>
<global-avatar
:icon-size=
"15"
v-for=
"item in record.userList"
:key=
"item.id"
></global-avatar>
</a-avatar-group>
<span
class=
"ml-2"
>
专家1,维修1 参与过该事件
</span>
<span
class=
"ml-2"
>
{{ getParticipantsName(record.userList) }}
</span>
</div>
<div
class=
"overflow-y-auto
"
>
<div
class=
"overflow-y-auto"
v-if=
"details?.total
"
>
<
template
v-if=
"active == 0"
>
<div
class=
"mb-4"
>
<template
v-for=
"item in details.list"
:key=
"item._id"
>
<div
class=
"flex-center mb-4"
v-if=
"item.fileType == 'txt'"
>
<div
class=
"flex-center flex-col shadow-lg rounded bg-fill-bg2 p-4"
>
<div>
{{
item
.
content
}}
</div>
<div
class=
"mt-2"
>
{{
timeStampFormat
(
item
.
createdTime
)
}}
</div>
</div>
</div>
<div
class=
"mb-4"
v-else
>
<div
class=
"flex items-center space-x-4"
>
<global-avatar
:icon-size=
"12
"
></global-avatar>
<global-avatar
:icon-size=
"15
"
></global-avatar>
<div
class=
"space-x-4"
>
<span>
专家
</span>
<span>
11698288374814
</span>
<span>
{{
getInitiatorInfo
(
item
.
fromId
).
nickname
}}
</span>
<span>
{{
timeStampFormat
(
item
.
createdTime
)
}}
</span>
</div>
</div>
<div
class=
"flex items-center space-x-8 mt-4 ml-14"
>
<icon-play-circle
class=
"cursor-pointer"
:size=
"25"
/>
<icon-download
class=
"cursor-pointer"
:size=
"25"
/>
</div>
</div>
<div
class=
"flex-center mb-4"
v-for=
"item in 10"
>
<div
class=
"flex-center flex-col shadow-lg rounded bg-fill-bg2 p-4"
>
<div>
专家1加入了通话
</div>
<div
class=
"mt-2"
>
1698288370706
</div>
<icon-play-circle
class=
"cursor-pointer"
:size=
"25"
@
click=
"handlePreview(item)"
/>
<icon-download
class=
"cursor-pointer"
:size=
"25"
@
click=
"handleDown(item)"
/>
</div>
</div>
</
template
>
</template>
<
template
v-else
>
<a-table
:columns=
"eventDetailsColumns1"
:data=
"[]"
:bordered=
"false"
:pagination=
"false"
/>
<a-table
:columns=
"getEventDetailsColumns"
:data=
"getEventDetailsData"
:bordered=
"false"
:pagination=
"false"
>
<template
#
fileName=
"
{ record }">
{{
JSON
.
parse
(
record
.
content
).
fileName
}}
</
template
>
<
template
#
fileSize=
"{ record }"
>
{{
(
parseFloat
(
JSON
.
parse
(
record
.
content
).
fileSize
)
/
1024
/
1024
).
toFixed
(
2
)
}}
MB
</
template
>
<
template
#
createdTime=
"{ record }"
>
{{
timeStampFormat
(
record
.
createdTime
)
}}
</
template
>
<
template
#
fromId=
"{ record }"
>
{{
getInitiatorInfo
(
record
.
fromId
).
nickname
}}
</
template
>
<
template
#
operation=
"{ record }"
>
<a-button
type=
"text"
@
click=
"handleDown(record)"
>
下载
</a-button>
</
template
>
</a-table>
</template>
</div>
<
template
v-else
>
<a-empty
class=
"w-full h-full flex-center flex-col"
/>
</
template
>
</template>
</div>
<file-preview
ref=
"previewRef"
></file-preview>
</template>
<
script
setup
lang=
"ts"
>
import
{
IconLeft
,
IconPlayCircle
,
IconDownload
}
from
'@arco-design/web-vue/es/icon'
import
{
eventDetailsColumns1
,
eventDetailsColumns2
}
from
'./constants/data.config'
import
{
timeStampFormat
}
from
'@/utils/dataTypes/dateRelated/formatDate'
import
{
directlyDownloadFromURL
}
from
'@/utils/downloadData/downloadBlob'
const
details
=
{
total
:
'3'
,
pageIndex
:
'1'
,
pageSize
:
'10'
,
list
:
[
{
_id
:
'6539d2f6561a4d043c508871'
,
channelId
:
'2_1698288370581'
,
closeTime
:
'1970-01-01T08:00:00'
,
companyId
:
'1'
,
content
:
'https://video.anyremote.cn:444/89169459-01e2-4594-a01a-cbbca9dd5bab/0_20231026024612670.mp4'
,
createdTime
:
1698288374814
,
fileMd5
:
''
,
fileName
:
'0_20231026024612670.mp4'
,
fileSize
:
'351399'
,
fileSizeTxt
:
''
,
fileType
:
'video'
,
fileUploadId
:
'1717372034058698754'
,
fileUrl
:
'https://video.anyremote.cn:444/89169459-01e2-4594-a01a-cbbca9dd5bab/0_20231026024612670.mp4'
,
fromId
:
'2'
,
isDel
:
'0'
,
isTop
:
'0'
,
msgId
:
''
,
quoteId
:
''
,
readUid
:
'2'
,
receiveUid
:
',7,'
,
status
:
''
,
toId
:
'-2'
,
updatedTime
:
1698288374814
,
videoDuration
:
'1'
,
videoDurationTxt
:
''
},
{
_id
:
'6539d2f2561a4d043c508870'
,
channelId
:
'2_1698288370581'
,
closeTime
:
'1970-01-01T08:00:00'
,
companyId
:
'1'
,
content
:
'专家1加入了通话'
,
createdTime
:
1698288370706
,
fileMd5
:
''
,
fileName
:
''
,
fileSize
:
'0'
,
fileSizeTxt
:
''
,
fileType
:
'txt'
,
fileUploadId
:
'0'
,
fileUrl
:
''
,
fromId
:
'2'
,
isDel
:
'0'
,
isTop
:
'0'
,
msgId
:
''
,
quoteId
:
''
,
readUid
:
'2'
,
receiveUid
:
',7,'
,
status
:
''
,
toId
:
''
,
updatedTime
:
1698288370706
,
videoDuration
:
'0'
,
videoDurationTxt
:
''
},
{
_id
:
'6539d2f2561a4d043c50886f'
,
channelId
:
'2_1698288370581'
,
closeTime
:
'1970-01-01T08:00:00'
,
companyId
:
'1'
,
content
:
'维修1加入了通话'
,
createdTime
:
1698288370696
,
fileMd5
:
''
,
fileName
:
''
,
fileSize
:
'0'
,
fileSizeTxt
:
''
,
fileType
:
'txt'
,
fileUploadId
:
'0'
,
fileUrl
:
''
,
fromId
:
'7'
,
isDel
:
'0'
,
isTop
:
'0'
,
msgId
:
''
,
quoteId
:
''
,
readUid
:
'7'
,
receiveUid
:
',7,'
,
status
:
''
,
toId
:
''
,
updatedTime
:
1698288370696
,
videoDuration
:
'0'
,
videoDurationTxt
:
''
}
]
interface
Props
{
details
?:
any
record
?:
any
}
const
ps
=
withDefaults
(
defineProps
<
Props
>
(),
{
details
:
()
=>
undefined
,
record
:
()
=>
undefined
})
const
es
=
defineEmits
([
'showList'
])
const
active
=
ref
(
0
)
const
tabs
=
ref
([
...
...
@@ -151,6 +95,55 @@ const tabs = ref([
{
value
:
2
,
label
:
'文档'
},
{
value
:
3
,
label
:
'视频'
}
])
//返回列表
const
showList
=
()
=>
{
es
(
'showList'
)
active
.
value
=
0
}
//获取表格列名称
const
getEventDetailsColumns
=
computed
(()
=>
{
if
(
active
.
value
==
1
||
active
.
value
==
2
)
{
return
eventDetailsColumns1
}
else
{
return
eventDetailsColumns2
}
})
//获取表格数据
const
getEventDetailsData
=
computed
(()
=>
{
if
(
active
.
value
==
1
)
{
return
ps
.
details
?.
list
.
filter
((
item
)
=>
item
.
fileType
==
'image'
)
}
if
(
active
.
value
==
2
)
{
return
ps
.
details
?.
list
.
filter
((
item
)
=>
item
.
fileType
==
'file'
)
}
if
(
active
.
value
==
3
)
{
return
ps
.
details
?.
list
.
filter
((
item
)
=>
item
.
fileType
==
'video'
)
}
return
[]
})
//获取所有参与人名称
const
getParticipantsName
=
(
userList
:
any
[])
=>
{
return
userList
.
map
((
item
)
=>
item
.
nickname
).
join
(
','
)
}
//获取参与人信息
const
getInitiatorInfo
=
(
id
)
=>
{
return
ps
.
record
?.
userList
.
find
((
item
)
=>
item
.
id
==
id
)
}
//预览文件
const
previewRef
=
ref
()
const
handlePreview
=
(
file
:
any
)
=>
{
const
content
=
JSON
.
parse
(
file
.
content
)
const
params
=
{
src
:
content
.
fileUrl
,
type
:
file
.
fileType
}
previewRef
.
value
!
.
open
(
params
)
}
//下载文件
const
handleDown
=
(
file
:
any
)
=>
{
const
content
=
JSON
.
parse
(
file
.
content
)
directlyDownloadFromURL
(
content
.
fileUrl
,
content
.
fileName
)
}
</
script
>
<
style
lang=
"less"
scoped
>
.arco-tag
{
...
...
src/views/remote/contacts/eventInfo.vue
View file @
7511e0c8
<
template
>
<!-- 事件列表 -->
<event-list></event-list>
<event-list
v-show=
"!showDetails"
@
show-details=
"handleShowDetails"
@
show-list=
"handleShowList"
></event-list>
<!-- 事件详情 -->
<
!--
<event-details></event-details>
--
>
<
event-details
v-show=
"showDetails"
:record=
"record"
:details=
"details"
@
show-list=
"handleShowList"
></event-details
>
</
template
>
<
script
setup
lang=
"ts"
>
import
EventList
from
'./eventList.vue'
import
EventDetails
from
'./eventDetails.vue'
const
showDetails
=
ref
(
false
)
const
record
=
ref
()
const
details
=
ref
()
//显示详情
const
handleShowDetails
=
(
data
:
any
)
=>
{
showDetails
.
value
=
true
record
.
value
=
data
.
record
details
.
value
=
data
.
details
}
//显示列表
const
handleShowList
=
()
=>
{
showDetails
.
value
=
false
record
.
value
=
undefined
details
.
value
=
undefined
}
</
script
>
<
style
lang=
"less"
scoped
></
style
>
src/views/remote/contacts/eventList.vue
View file @
7511e0c8
...
...
@@ -11,14 +11,20 @@
<template
#
index=
"
{ rowIndex }">
{{
rowIndex
+
1
}}
</
template
>
<
template
#
title=
"{ record }"
>
<div
class=
"flex items-center w-full space-x-4"
>
<
template
#
title=
"{ record, rowIndex }"
>
<a-spin
:loading=
"loadingTitle && record.isFocus"
>
<div
class=
"flex items-center w-full space-x-4"
v-if=
"record.isFocus"
>
<div
class=
"flex-auto"
>
<a-input
:default-value=
"record.title"
></a-input>
<a-input
v-model=
"record.title"
:ref=
"(vc: any) => (titleArr[rowIndex] = vc)"
allow-clear
></a-input>
</div>
<icon-close
class=
"cursor-pointer
"
/>
<icon-check
class=
"cursor-pointer
"
/>
<icon-close
class=
"cursor-pointer"
@
click=
"handleClose(record, rowIndex)
"
/>
<icon-check
class=
"cursor-pointer"
@
click=
"handleConfirm(record, rowIndex)
"
/>
</div>
<div
class=
"flex justify-between items-center w-full"
v-else
>
<div>
{{
record
.
title
}}
</div>
<div
class=
"min-w-5"
><icon-edit
class=
"cursor-pointer"
@
click=
"handleFocus(record, rowIndex)"
/></div>
</div>
</a-spin>
</
template
>
<
template
#
initiator=
"{ record }"
>
<div
class=
"flex items-center"
>
...
...
@@ -29,16 +35,18 @@
<
template
#
participants=
"{ record }"
>
<div
class=
"flex items-center"
>
<a-avatar-group
:size=
"32"
:max-count=
"2"
>
<global-avatar
:icon-size=
"12"
v-for=
"item in record.userList"
></global-avatar>
<global-avatar
:icon-size=
"12"
v-for=
"item in record.userList"
:key=
"item.id"
></global-avatar>
</a-avatar-group>
<span
class=
"ml-2"
>
{{
getParticipantsName
(
record
.
userList
)
}}
</span>
<a-tooltip
:content=
"getParticipantsName(record.userList)"
>
<span
class=
"ml-2 truncate max-w-20"
>
{{
getParticipantsName
(
record
.
userList
)
}}
</span>
</a-tooltip>
</div>
</
template
>
<
template
#
createdTime=
"{ record }"
>
{{
Day
(
parseInt
(
record
.
createdTime
)).
format
(
'YYYY-MM-DD HH:mm:ss'
)
}}
{{
timeStampFormat
(
record
.
createdTime
)
}}
</
template
>
<
template
#
operation=
"{ record }"
>
<a-button
type=
"text"
@
click=
"showDetails(record
.channelId
)"
>
查看详情
</a-button>
<a-button
type=
"text"
@
click=
"showDetails(record)"
>
查看详情
</a-button>
</
template
>
</a-table>
</div>
...
...
@@ -54,10 +62,12 @@ import { eventListColumns } from './constants/data.config'
import
{
alova
}
from
'@/api/alova-instance'
import
useContactsStore
from
'@/store/contacts/index'
import
{
storeToRefs
}
from
'pinia'
import
Day
from
'@/utils/dayjs
'
import
{
timeStampFormat
}
from
'@/utils/dataTypes/dateRelated/formatDate
'
import
{
Message
}
from
'@arco-design/web-vue'
import
{
IconCheck
,
IconClose
}
from
'@arco-design/web-vue/es/icon'
import
{
IconCheck
,
IconClose
,
IconEdit
}
from
'@arco-design/web-vue/es/icon'
import
{
useRequest
}
from
'alova'
const
es
=
defineEmits
([
'showDetails'
,
'showList'
])
const
beginTime
=
ref
(
''
)
const
endTime
=
ref
(
''
)
const
keyword
=
ref
(
''
)
...
...
@@ -117,7 +127,11 @@ const {
debounce
:
[
800
],
abortLast
:
true
,
total
:
(
res
)
=>
parseInt
(
res
.
data
.
total
),
data
:
(
res
)
=>
res
.
data
.
list
,
data
:
(
res
)
=>
{
return
res
.
data
?.
list
?.
map
((
item
)
=>
{
return
{
...
item
,
_title
:
item
.
title
}
})
},
sendable
:
()
=>
{
return
!!
chooseContactsItem
?.
value
?.
id
}
...
...
@@ -128,32 +142,69 @@ const getInitiatorName = (record: any) => {
const
initiatorId
=
record
.
channelId
.
split
(
'_'
)[
0
]
return
record
.
userList
.
find
((
item
:
any
)
=>
item
.
id
==
initiatorId
)?.
nickname
}
//获取参与人名称
//获取
所有
参与人名称
const
getParticipantsName
=
(
userList
:
any
[])
=>
{
return
userList
.
map
((
item
)
=>
item
.
nickname
).
join
(
','
)
}
//修改事件标题
const
titleArr
=
ref
([])
const
handleFocus
=
(
record
:
any
,
rowIndex
:
number
)
=>
{
if
(
record
.
isFocus
)
{
record
.
isFocus
=
false
}
else
{
record
.
isFocus
=
true
nextTick
(()
=>
{
titleArr
.
value
[
rowIndex
].
focus
()
})
}
}
const
updateRemoteEventName
=
(
record
:
any
)
=>
{
const
params
=
{
uid
:
2
,
projectName
:
'mu'
,
id
:
record
.
id
,
title
:
record
.
title
}
return
alova
.
Post
<
any
>
(
'/call/updateRemoteEventName'
,
params
)
}
const
{
loading
:
loadingTitle
,
send
:
sendUpdateTitle
}
=
useRequest
((
record
:
any
)
=>
updateRemoteEventName
(
record
),
{
immediate
:
false
})
const
handleConfirm
=
async
(
record
:
any
,
rowIndex
:
number
)
=>
{
if
(
!
record
.
title
)
{
titleArr
.
value
[
rowIndex
].
focus
()
return
Message
.
error
(
'请输入事件名称!'
)
}
const
res
=
await
sendUpdateTitle
(
record
,
rowIndex
)
if
(
res
.
code
==
200
)
{
handleFocus
(
record
,
rowIndex
)
}
else
{
titleArr
.
value
[
rowIndex
].
focus
()
Message
.
error
(
res
.
message
)
}
}
const
handleClose
=
(
record
:
any
,
rowIndex
:
number
)
=>
{
record
.
title
=
record
.
_title
handleFocus
(
record
,
rowIndex
)
}
//显示详情
const
showDetails
=
async
(
channelId
:
string
)
=>
{
const
showDetails
=
async
(
record
:
any
)
=>
{
const
params
=
{
uid
:
2
,
projectName
:
'mu'
,
channelId
channelId
:
record
.
channelId
}
// @ts-ignore
const
res
=
await
alova
.
Post
<
any
>
(
'/call/getChatRoomMsgList'
,
params
,
{
meta
:
{
loading
:
true
}
})
if
(
res
.
code
==
200
)
{
console
.
log
(
res
.
data
)
es
(
'showDetails'
,
{
details
:
res
.
data
,
record
}
)
}
else
{
Message
.
error
(
res
.
message
)
}
}
//数据发生改变就展示列表
watch
(
tableData
,
()
=>
{
es
(
'showList'
)
})
</
script
>
<
style
lang=
"less"
scoped
>
:deep
(
.arco-table-th
)
{
background
:
var
(
--color-fill-1
);
border-bottom
:
1px
solid
var
(
--color-neutral-3
);
}
:deep
(
.arco-table-td
)
{
background
:
inherit
;
}
</
style
>
<
style
lang=
"less"
scoped
></
style
>
src/views/remote/videoCall/chatDetails.vue
View file @
7511e0c8
...
...
@@ -33,11 +33,7 @@
</
template
>
</div>
</div>
<global-model
v-model:visible=
"showPreview"
width=
"80%"
:footer=
"false"
:simple=
"true"
>
<div
style=
"height: 80vh"
>
<iframe
:src=
"data.src"
frameborder=
"0"
width=
"100%"
height=
"100%"
></iframe>
</div>
</global-model>
<file-preview
ref=
"previewRef"
></file-preview>
</template>
<
script
setup
lang=
"ts"
>
...
...
@@ -54,9 +50,9 @@ const ps = withDefaults(defineProps<Props>(), {
data
:
()
=>
{}
})
//预览文件
const
showPreview
=
ref
(
false
)
const
previewRef
=
ref
(
)
const
handlePreview
=
()
=>
{
showPreview
.
value
=
true
previewRef
.
value
!
.
open
({
src
:
ps
.
data
.
src
,
type
:
'file'
})
}
//下载文件
const
handleDown
=
()
=>
{
...
...
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