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
54897b6d
authored
Nov 25, 2023
by
芋道源码
Committed by
Gitee
Nov 25, 2023
Browse files
Options
Browse Files
Download
Plain Diff
!332 同步最新的代码到 dev
Merge pull request !332 from 芋道源码/master
parents
c6192a19
1744c6ec
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
237 additions
and
49 deletions
+237
-49
.env.base
+2
-2
src/api/mall/product/favorite.ts
+12
-0
src/api/system/notice/index.ts
+5
-0
src/api/system/sms/smsLog/index.ts
+0
-2
src/locales/zh-CN.ts
+2
-1
src/views/infra/webSocket/index.vue
+102
-40
src/views/member/user/detail/UserFavoriteList.vue
+96
-0
src/views/member/user/detail/index.vue
+4
-1
src/views/system/notice/index.vue
+14
-0
src/views/system/sms/log/SmsLogDetail.vue
+0
-3
No files found.
.env.base
View file @
54897b6d
...
@@ -4,10 +4,10 @@ NODE_ENV=development
...
@@ -4,10 +4,10 @@ NODE_ENV=development
VITE_DEV=true
VITE_DEV=true
# 请求路径
# 请求路径
VITE_BASE_URL='http://
localhost
:48080'
VITE_BASE_URL='http://
127.0.0.1
:48080'
# 上传路径
# 上传路径
VITE_UPLOAD_URL='http://
localhost
:48080/admin-api/infra/file/upload'
VITE_UPLOAD_URL='http://
127.0.0.1
:48080/admin-api/infra/file/upload'
# 接口前缀
# 接口前缀
VITE_API_BASEPATH=/dev-api
VITE_API_BASEPATH=/dev-api
...
...
src/api/mall/product/favorite.ts
0 → 100644
View file @
54897b6d
import
request
from
'@/config/axios'
export
interface
Favorite
{
id
?:
number
userId
?:
string
// 用户编号
spuId
?:
number
|
null
// 商品 SPU 编号
}
// 获得 ProductFavorite 列表
export
const
getFavoritePage
=
(
params
:
PageParam
)
=>
{
return
request
.
get
({
url
:
'/product/favorite/page'
,
params
})
}
src/api/system/notice/index.ts
View file @
54897b6d
...
@@ -35,3 +35,8 @@ export const updateNotice = (data: NoticeVO) => {
...
@@ -35,3 +35,8 @@ export const updateNotice = (data: NoticeVO) => {
export
const
deleteNotice
=
(
id
:
number
)
=>
{
export
const
deleteNotice
=
(
id
:
number
)
=>
{
return
request
.
delete
({
url
:
'/system/notice/delete?id='
+
id
})
return
request
.
delete
({
url
:
'/system/notice/delete?id='
+
id
})
}
}
// 推送公告
export
const
pushNotice
=
(
id
:
number
)
=>
{
return
request
.
post
({
url
:
'/system/notice/push?id='
+
id
})
}
src/api/system/sms/smsLog/index.ts
View file @
54897b6d
...
@@ -15,8 +15,6 @@ export interface SmsLogVO {
...
@@ -15,8 +15,6 @@ export interface SmsLogVO {
userType
:
number
|
null
userType
:
number
|
null
sendStatus
:
number
|
null
sendStatus
:
number
|
null
sendTime
:
Date
|
null
sendTime
:
Date
|
null
sendCode
:
number
|
null
sendMsg
:
string
apiSendCode
:
string
apiSendCode
:
string
apiSendMsg
:
string
apiSendMsg
:
string
apiRequestId
:
string
apiRequestId
:
string
...
...
src/locales/zh-CN.ts
View file @
54897b6d
...
@@ -437,5 +437,6 @@ export default {
...
@@ -437,5 +437,6 @@ export default {
btn_zoom_in
:
'放大'
,
btn_zoom_in
:
'放大'
,
btn_zoom_out
:
'缩小'
,
btn_zoom_out
:
'缩小'
,
preview
:
'预览'
preview
:
'预览'
}
},
'OAuth 2.0'
:
'OAuth 2.0'
// 避免菜单名是 OAuth 2.0 时,一直 warn 报错
}
}
src/views/infra/webSocket/index.vue
View file @
54897b6d
<
template
>
<
template
>
<div
class=
"flex"
>
<div
class=
"flex"
>
<!-- 左侧:建立连接、发送消息 -->
<el-card
:gutter=
"12"
class=
"w-1/2"
shadow=
"always"
>
<el-card
:gutter=
"12"
class=
"w-1/2"
shadow=
"always"
>
<template
#
header
>
<template
#
header
>
<div
class=
"card-header"
>
<div
class=
"card-header"
>
...
@@ -11,28 +12,38 @@
...
@@ -11,28 +12,38 @@
<el-tag
:color=
"getTagColor"
>
{{ status }}
</el-tag>
<el-tag
:color=
"getTagColor"
>
{{ status }}
</el-tag>
</div>
</div>
<hr
class=
"my-4"
/>
<hr
class=
"my-4"
/>
<div
class=
"flex"
>
<div
class=
"flex"
>
<el-input
v-model=
"server"
disabled
>
<el-input
v-model=
"server"
disabled
>
<
template
#
prepend
>
服务地址
</
template
>
<
template
#
prepend
>
服务地址
</
template
>
</el-input>
</el-input>
<el-button
:type=
"getIsOpen ? 'danger' : 'primary'"
@
click=
"toggle"
>
<el-button
:type=
"getIsOpen ? 'danger' : 'primary'"
@
click=
"toggle
ConnectStatus
"
>
{{ getIsOpen ? '关闭连接' : '开启连接' }}
{{ getIsOpen ? '关闭连接' : '开启连接' }}
</el-button>
</el-button>
</div>
</div>
<p
class=
"mt-4 text-lg font-medium"
>
设置
</p>
<p
class=
"mt-4 text-lg font-medium"
>
消息输入框
</p>
<hr
class=
"my-4"
/>
<hr
class=
"my-4"
/>
<el-input
<el-input
v-model=
"send
Value
"
v-model=
"send
Text
"
:autosize=
"{ minRows: 2, maxRows: 4 }"
:autosize=
"{ minRows: 2, maxRows: 4 }"
:disabled=
"!getIsOpen"
:disabled=
"!getIsOpen"
clearable
clearable
type=
"textarea"
type=
"textarea"
placeholder=
"请输入你要发送的消息"
/>
/>
<el-button
:disabled=
"!getIsOpen"
block
class=
"mt-4"
type=
"primary"
@
click=
"handlerSend"
>
<el-select
v-model=
"sendUserId"
class=
"mt-4"
placeholder=
"请选择发送人"
>
<el-option
key=
""
label=
"所有人"
value=
""
/>
<el-option
v-for=
"user in userList"
:key=
"user.id"
:label=
"user.nickname"
:value=
"user.id"
/>
</el-select>
<el-button
:disabled=
"!getIsOpen"
block
class=
"ml-2 mt-4"
type=
"primary"
@
click=
"handlerSend"
>
发送
发送
</el-button>
</el-button>
</el-card>
</el-card>
<!-- 右侧:消息记录 -->
<el-card
:gutter=
"12"
class=
"w-1/2"
shadow=
"always"
>
<el-card
:gutter=
"12"
class=
"w-1/2"
shadow=
"always"
>
<
template
#
header
>
<
template
#
header
>
<div
class=
"card-header"
>
<div
class=
"card-header"
>
...
@@ -41,13 +52,13 @@
...
@@ -41,13 +52,13 @@
</
template
>
</
template
>
<div
class=
"max-h-80 overflow-auto"
>
<div
class=
"max-h-80 overflow-auto"
>
<ul>
<ul>
<li
v-for=
"
item in getList"
:key=
"item
.time"
class=
"mt-2"
>
<li
v-for=
"
msg in messageList.reverse()"
:key=
"msg
.time"
class=
"mt-2"
>
<div
class=
"flex items-center"
>
<div
class=
"flex items-center"
>
<span
class=
"text-primary mr-2 font-medium"
>
收到消息:
</span>
<span
class=
"text-primary mr-2 font-medium"
>
收到消息:
</span>
<span>
{{ formatDate(
item
.time) }}
</span>
<span>
{{ formatDate(
msg
.time) }}
</span>
</div>
</div>
<div>
<div>
{{
item.res
}}
{{
msg.text
}}
</div>
</div>
</li>
</li>
</ul>
</ul>
...
@@ -57,62 +68,113 @@
...
@@ -57,62 +68,113 @@
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
useWebSocket
}
from
'@vueuse/core'
import
{
useWebSocket
}
from
'@vueuse/core'
import
{
getAccessToken
}
from
'@/utils/auth'
import
*
as
UserApi
from
'@/api/system/user'
defineOptions
({
name
:
'InfraWebSocket'
})
defineOptions
({
name
:
'InfraWebSocket'
})
const
userStore
=
useUserStore
()
const
message
=
useMessage
()
// 消息弹窗
const
sendValue
=
ref
(
''
)
const
server
=
ref
(
const
server
=
ref
(
(
import
.
meta
.
env
.
VITE_BASE_URL
+
'/websocket/message'
).
replace
(
'http'
,
'ws'
)
+
(
import
.
meta
.
env
.
VITE_BASE_URL
+
'/infra/ws'
).
replace
(
'http'
,
'ws'
)
+
'?token='
+
getAccessToken
()
'?userId='
+
)
// WebSocket 服务地址
userStore
.
getUser
.
id
const
getIsOpen
=
computed
(()
=>
status
.
value
===
'OPEN'
)
// WebSocket 连接是否打开
)
const
getTagColor
=
computed
(()
=>
(
getIsOpen
.
value
?
'success'
:
'red'
))
// WebSocket 连接的展示颜色
const
state
=
reactive
({
recordList
:
[]
as
{
id
:
number
;
time
:
number
;
res
:
string
}[]
})
/** 发起 WebSocket 连接 */
const
{
status
,
data
,
send
,
close
,
open
}
=
useWebSocket
(
server
.
value
,
{
const
{
status
,
data
,
send
,
close
,
open
}
=
useWebSocket
(
server
.
value
,
{
autoReconnect
:
false
,
autoReconnect
:
false
,
heartbeat
:
true
heartbeat
:
true
})
})
/** 监听接收到的数据 */
const
messageList
=
ref
([]
as
{
time
:
number
;
text
:
string
}[])
// 消息列表
watchEffect
(()
=>
{
watchEffect
(()
=>
{
if
(
data
.
value
)
{
if
(
!
data
.
value
)
{
try
{
return
const
res
=
JSON
.
parse
(
data
.
value
)
}
state
.
recordList
.
push
(
res
)
try
{
}
catch
(
error
)
{
// 1. 收到心跳
state
.
recordList
.
push
({
if
(
data
.
value
===
'pong'
)
{
res
:
data
.
value
,
// state.recordList.push({
id
:
Math
.
ceil
(
Math
.
random
()
*
1000
),
// text: '【心跳】',
// time: new Date().getTime()
// })
return
}
// 2.1 解析 type 消息类型
const
jsonMessage
=
JSON
.
parse
(
data
.
value
)
const
type
=
jsonMessage
.
type
const
content
=
JSON
.
parse
(
jsonMessage
.
content
)
if
(
!
type
)
{
message
.
error
(
'未知的消息类型:'
+
data
.
value
)
return
}
// 2.2 消息类型:demo-message-receive
if
(
type
===
'demo-message-receive'
)
{
const
single
=
content
.
single
if
(
single
)
{
messageList
.
value
.
push
({
text
:
`【单发】用户编号(
${
content
.
fromUserId
}
):
${
content
.
text
}
`
,
time
:
new
Date
().
getTime
()
})
}
else
{
messageList
.
value
.
push
({
text
:
`【群发】用户编号(
${
content
.
fromUserId
}
):
${
content
.
text
}
`
,
time
:
new
Date
().
getTime
()
})
}
return
}
// 2.3 消息类型:notice-push
if
(
type
===
'notice-push'
)
{
messageList
.
value
.
push
({
text
:
`【系统通知】:
${
content
.
title
}
`
,
time
:
new
Date
().
getTime
()
time
:
new
Date
().
getTime
()
})
})
return
}
}
message
.
error
(
'未处理消息:'
+
data
.
value
)
}
catch
(
error
)
{
message
.
error
(
'处理消息发生异常:'
+
data
.
value
)
console
.
error
(
error
)
}
}
})
})
const
getIsOpen
=
computed
(()
=>
status
.
value
===
'OPEN'
)
/** 发送消息 */
const
getTagColor
=
computed
(()
=>
(
getIsOpen
.
value
?
'success'
:
'red'
))
const
sendText
=
ref
(
''
)
// 发送内容
const
sendUserId
=
ref
(
''
)
// 发送人
const
getList
=
computed
(()
=>
{
const
handlerSend
=
()
=>
{
return
[...
state
.
recordList
].
reverse
()
// 1.1 先 JSON 化 message 消息内容
})
const
messageContent
=
JSON
.
stringify
({
text
:
sendText
.
value
,
function
handlerSend
()
{
toUserId
:
sendUserId
.
value
send
(
sendValue
.
value
)
})
sendValue
.
value
=
''
// 1.2 再 JSON 化整个消息
const
jsonMessage
=
JSON
.
stringify
({
type
:
'demo-message-send'
,
content
:
messageContent
})
// 2. 最后发送消息
send
(
jsonMessage
)
sendText
.
value
=
''
}
}
function
toggle
()
{
/** 切换 websocket 连接状态 */
const
toggleConnectStatus
=
()
=>
{
if
(
getIsOpen
.
value
)
{
if
(
getIsOpen
.
value
)
{
close
()
close
()
}
else
{
}
else
{
open
()
open
()
}
}
}
}
/** 初始化 **/
const
userList
=
ref
<
any
[]
>
([])
// 用户列表
onMounted
(
async
()
=>
{
// 获取用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
})
</
script
>
</
script
>
src/views/member/user/detail/UserFavoriteList.vue
0 → 100644
View file @
54897b6d
<
template
>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
key=
"id"
align=
"center"
label=
"商品编号"
width=
"180"
prop=
"id"
/>
<el-table-column
label=
"商品图"
min-width=
"80"
>
<template
#
default=
"
{ row }">
<el-image
:src=
"row.picUrl"
class=
"h-30px w-30px"
@
click=
"imagePreview(row.picUrl)"
/>
</
template
>
</el-table-column>
<el-table-column
:show-overflow-tooltip=
"true"
label=
"商品名称"
min-width=
"300"
prop=
"name"
/>
<el-table-column
align=
"center"
label=
"商品售价"
min-width=
"90"
prop=
"price"
>
<
template
#
default=
"{ row }"
>
{{
floatToFixed2
(
row
.
price
)
}}
元
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"销量"
min-width=
"90"
prop=
"salesCount"
/>
<el-table-column
:formatter=
"dateFormatter"
align=
"center"
label=
"收藏时间"
prop=
"createTime"
width=
"180"
/>
<el-table-column
align=
"center"
label=
"状态"
min-width=
"80"
>
<
template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.PRODUCT_SPU_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
</template>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
*
as
FavoriteApi
from
'@/api/mall/product/favorite'
import
{
floatToFixed2
}
from
'@/utils'
const
message
=
useMessage
()
// 消息弹窗
const
{
t
}
=
useI18n
()
// 国际化
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
name
:
null
,
createTime
:
[],
userId
:
NaN
})
const
queryFormRef
=
ref
()
// 搜索的表单
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
FavoriteApi
.
getFavoritePage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
.
value
.
resetFields
()
handleQuery
()
}
const
{
userId
}
=
defineProps
({
userId
:
{
type
:
Number
,
required
:
true
}
})
/** 初始化 **/
onMounted
(()
=>
{
queryParams
.
userId
=
userId
getList
()
})
</
script
>
src/views/member/user/detail/index.vue
View file @
54897b6d
...
@@ -48,7 +48,9 @@
...
@@ -48,7 +48,9 @@
<UserOrderList
:user-id=
"id"
/>
<UserOrderList
:user-id=
"id"
/>
</el-tab-pane>
</el-tab-pane>
<el-tab-pane
label=
"售后管理"
lazy
>
售后管理(WIP)
</el-tab-pane>
<el-tab-pane
label=
"售后管理"
lazy
>
售后管理(WIP)
</el-tab-pane>
<el-tab-pane
label=
"收藏记录"
lazy
>
收藏记录(WIP)
</el-tab-pane>
<el-tab-pane
label=
"收藏记录"
lazy
>
<UserFavoriteList
:user-id=
"id"
/>
</el-tab-pane>
<el-tab-pane
label=
"优惠劵"
lazy
>
<el-tab-pane
label=
"优惠劵"
lazy
>
<UserCouponList
:user-id=
"id"
/>
<UserCouponList
:user-id=
"id"
/>
</el-tab-pane>
</el-tab-pane>
...
@@ -76,6 +78,7 @@ import UserExperienceRecordList from './UserExperienceRecordList.vue'
...
@@ -76,6 +78,7 @@ import UserExperienceRecordList from './UserExperienceRecordList.vue'
import
UserOrderList
from
'./UserOrderList.vue'
import
UserOrderList
from
'./UserOrderList.vue'
import
UserPointList
from
'./UserPointList.vue'
import
UserPointList
from
'./UserPointList.vue'
import
UserSignList
from
'./UserSignList.vue'
import
UserSignList
from
'./UserSignList.vue'
import
UserFavoriteList
from
'./UserFavoriteList.vue'
import
{
CardTitle
}
from
'@/components/Card/index'
import
{
CardTitle
}
from
'@/components/Card/index'
import
{
ElMessage
}
from
'element-plus'
import
{
ElMessage
}
from
'element-plus'
...
...
src/views/system/notice/index.vue
View file @
54897b6d
...
@@ -87,6 +87,9 @@
...
@@ -87,6 +87,9 @@
>
>
删除
删除
</el-button>
</el-button>
<el-button
link
@
click=
"handlePush(scope.row.id)"
v-hasPermi=
"['system:notice:update']"
>
推送
</el-button>
</
template
>
</
template
>
</el-table-column>
</el-table-column>
</el-table>
</el-table>
...
@@ -168,6 +171,17 @@ const handleDelete = async (id: number) => {
...
@@ -168,6 +171,17 @@ const handleDelete = async (id: number) => {
}
catch
{}
}
catch
{}
}
}
/** 推送按钮操作 */
const
handlePush
=
async
(
id
:
number
)
=>
{
try
{
// 推送的二次确认
await
message
.
confirm
(
'是否推送所选中通知?'
)
// 发起推送
await
NoticeApi
.
pushNotice
(
id
)
message
.
success
(
t
(
'推送成功'
))
}
catch
{}
}
/** 初始化 **/
/** 初始化 **/
onMounted
(()
=>
{
onMounted
(()
=>
{
getList
()
getList
()
...
...
src/views/system/sms/log/SmsLogDetail.vue
View file @
54897b6d
...
@@ -37,9 +37,6 @@
...
@@ -37,9 +37,6 @@
<el-descriptions-item
label=
"发送时间"
>
<el-descriptions-item
label=
"发送时间"
>
{{
formatDate
(
detailData
.
sendTime
)
}}
{{
formatDate
(
detailData
.
sendTime
)
}}
</el-descriptions-item>
</el-descriptions-item>
<el-descriptions-item
label=
"发送结果"
>
{{
detailData
.
sendCode
}}
|
{{
detailData
.
sendMsg
}}
</el-descriptions-item>
<el-descriptions-item
label=
"API 发送结果"
>
<el-descriptions-item
label=
"API 发送结果"
>
{{
detailData
.
apiSendCode
}}
|
{{
detailData
.
apiSendMsg
}}
{{
detailData
.
apiSendCode
}}
|
{{
detailData
.
apiSendMsg
}}
</el-descriptions-item>
</el-descriptions-item>
...
...
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