新增智能助手推送的系统消息类型对接,并处理对应类型消息的卡片展示和交互细节
Some checks are pending
Check / lint (push) Waiting to run
Check / typecheck (push) Waiting to run
Check / build (build, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build, 18.x, windows-latest) (push) Waiting to run
Check / build (build:app, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:app, 18.x, windows-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, ubuntu-latest) (push) Waiting to run
Check / build (build:mp-weixin, 18.x, windows-latest) (push) Waiting to run

This commit is contained in:
wangyifeng 2025-08-05 15:45:49 +08:00
parent 227d8c7524
commit b046388c86
14 changed files with 251 additions and 31 deletions

1
components.d.ts vendored
View File

@ -51,6 +51,7 @@ declare module 'vue' {
SysGroupMemberRemovedMessage: typeof import('./src/components/talk/message/system/SysGroupMemberRemovedMessage.vue')['default'] SysGroupMemberRemovedMessage: typeof import('./src/components/talk/message/system/SysGroupMemberRemovedMessage.vue')['default']
SysGroupMutedMessage: typeof import('./src/components/talk/message/system/SysGroupMutedMessage.vue')['default'] SysGroupMutedMessage: typeof import('./src/components/talk/message/system/SysGroupMutedMessage.vue')['default']
SysGroupTransferMessage: typeof import('./src/components/talk/message/system/SysGroupTransferMessage.vue')['default'] SysGroupTransferMessage: typeof import('./src/components/talk/message/system/SysGroupTransferMessage.vue')['default']
SysPushMessage: typeof import('./src/components/talk/message/system/sysPushMessage.vue')['default']
SysTextMessage: typeof import('./src/components/talk/message/system/SysTextMessage.vue')['default'] SysTextMessage: typeof import('./src/components/talk/message/system/SysTextMessage.vue')['default']
TabbarItem: typeof import('./src/components/x-tabbar/components/tabbar-item/index.vue')['default'] TabbarItem: typeof import('./src/components/x-tabbar/components/tabbar-item/index.vue')['default']
TextMessage: typeof import('./src/components/talk/message/TextMessage.vue')['default'] TextMessage: typeof import('./src/components/talk/message/TextMessage.vue')['default']

6
env/.env.dev vendored
View File

@ -5,8 +5,10 @@ VITE_SHOW_CONSOLE = true
# 是否开启sourcemap # 是否开启sourcemap
VITE_SHOW_SOURCEMAP = true VITE_SHOW_SOURCEMAP = true
# baseUrl # baseUrl
VITE_BASEURL = 'http://172.16.100.93:8503' # VITE_BASEURL = 'http://172.16.100.93:8503'
VITE_BASEURL = 'http://192.168.88.47:9503'
#VITE_SOCKET_API #VITE_SOCKET_API
VITE_SOCKET_API = 'ws://172.16.100.93:8504' # VITE_SOCKET_API = 'ws://172.16.100.93:8504'
VITE_SOCKET_API = 'ws://192.168.88.47:9504'
# EPRAPI baseUrl # EPRAPI baseUrl
VITE_EPR_BASEURL = 'http://114.218.158.24:9020' VITE_EPR_BASEURL = 'http://114.218.158.24:9020'

View File

@ -5,6 +5,7 @@
"packageManager": "pnpm@8.14.1", "packageManager": "pnpm@8.14.1",
"license": "MIT", "license": "MIT",
"scripts": { "scripts": {
"dev:h5": "uni --mode dev --port 2468",
"test:h5": "uni --mode test --port 2468", "test:h5": "uni --mode test --port 2468",
"prod:h5": "uni --mode prod", "prod:h5": "uni --mode prod",
"build:h5:test": "uni build --mode test", "build:h5:test": "uni build --mode test",

View File

@ -36,6 +36,7 @@
<div class="mt-1">转文字</div> <div class="mt-1">转文字</div>
</div> </div>
<div <div
v-if="props.isShowMultipleChoose && !props.isChatRobot"
@click="() => itemClick('multipleChoose')" @click="() => itemClick('multipleChoose')"
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
@ -47,7 +48,7 @@
<div class="mt-1">多选</div> <div class="mt-1">多选</div>
</div> </div>
<div <div
v-if="props.isShowCite" v-if="props.isShowCite && !props.isChatRobot"
@click="() => itemClick('actionCite')" @click="() => itemClick('actionCite')"
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
@ -63,6 +64,7 @@
<div class="mt-1">撤回</div> <div class="mt-1">撤回</div>
</div> </div>
<div <div
:class="{ 'w-full': props.isChatRobot }"
@click="() => itemClick('actionDelete')" @click="() => itemClick('actionDelete')"
class="flex flex-col items-center justify-center" class="flex flex-col items-center justify-center"
> >
@ -110,14 +112,17 @@ const bubbleRef = ref(null)
const props = defineProps({ const props = defineProps({
isShowCopy: { isShowCopy: {
//
type: Boolean, type: Boolean,
default: true, default: true,
}, },
isShowCite: { isShowCite: {
//
type: Boolean, type: Boolean,
default: true, default: true,
}, },
isShowWithdraw: { isShowWithdraw: {
//
type: Boolean, type: Boolean,
default: true, default: true,
}, },
@ -126,6 +131,16 @@ const props = defineProps({
type: Boolean, type: Boolean,
default: false, default: false,
}, },
isShowMultipleChoose: {
//
type: Boolean,
default: true,
},
isChatRobot: {
//
type: Boolean,
default: false,
}
}) })
const emits = defineEmits(['clickMenu']) const emits = defineEmits(['clickMenu'])

View File

@ -0,0 +1,133 @@
<script setup>
import { handleFindWebview } from '@/utils/common'
import noClockAfterWork from '@/static/image/chatBotMessageCard/noClockAfterWork.png'
import noClockBeforeWork from '@/static/image/chatBotMessageCard/noClockBeforeWork.png'
import copy from '@/static/image/chatBotMessageCard/copy.png'
import errorClock from '@/static/image/chatBotMessageCard/errorClock.png'
import prompt from '@/static/image/chatBotMessageCard/prompt.png'
const props = defineProps({
extra: Object,
data: Object,
})
//
const getMessageCard = computed(() => {
switch (props.data.msg_type) {
case 1117: //
return prompt
case 1118: //
return noClockBeforeWork
case 1119: //
return noClockAfterWork
case 1120: //
return prompt
case 1121: //
return copy
case 1122: //
return errorClock
case 1123: //
return errorClock
case 1124: //退
return errorClock
default:
return ''
}
})
//
const getTextColor = computed(() => {
const msgType = props.data.msg_type
//
if ([1117, 1120].includes(msgType)) return '#2668BF'
//
if ([1118, 1119].includes(msgType)) return '#46299D'
//
if (msgType === 1121) return '#2099BE'
//退
if ([1122, 1123, 1124].includes(msgType)) return '#933BA3'
return ''
})
//
const getTextContent = computed(() => {
const msgType = props.data.msg_type
//
if ([1117, 1120].includes(msgType)) return '立即审批'
//
if ([1118, 1119].includes(msgType)) return '立即打卡'
//退
if ([1121, 1122, 1123, 1124].includes(msgType)) return '立即查看'
return ''
})
//webview
const handleSysMessagePush = () => {
handleFindWebview(`handleSysMessagePush('${encodeURIComponent(props?.extra?.url)}')`)
}
</script>
<template>
<div class="sys-message-push" @click="handleSysMessagePush">
<div class="sys-message-push-card">
<span class="sys-message-push-card-title">{{ props.extra.title }}</span>
<span class="sys-message-push-card-message" v-html="props.extra.message">
</span>
<img :src="getMessageCard" alt="" />
</div>
<div class="sys-message-push-card-btn">
<span :style="{ color: getTextColor }">{{ getTextContent }}</span>
</div>
</div>
</template>
<style lang="less" scoped>
.sys-message-push {
border-radius: 0 16rpx 16rpx 16rpx;
overflow: hidden;
box-shadow: 0 6px 12px 2px rgba(188, 188, 188, 0.08);
.sys-message-push-card {
position: relative;
width: 486rpx;
height: 270rpx;
.sys-message-push-card-title {
position: absolute;
top: 28rpx;
left: 30rpx;
font-size: 24rpx;
line-height: 34rpx;
color: rgba(255, 255, 255, 0.73);
font-weight: 500;
}
.sys-message-push-card-message {
position: absolute;
bottom: 44rpx;
left: 30rpx;
font-size: 40rpx;
line-height: 58rpx;
color: #fff;
font-weight: bold;
max-width: 326rpx;
}
img {
width: 100%;
height: 100%;
}
}
.sys-message-push-card-btn {
background-color: #fff;
width: 486rpx;
height: 78rpx;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
text {
color: #000;
font-size: 28rpx;
line-height: 40rpx;
font-weight: 500;
}
}
}
</style>

View File

@ -29,6 +29,14 @@ export const ChatMsgSysGroupTransfer = 1113 // 变更群主
export const ChatMsgSysGroupAdmin = 1114 // 设置管理员 export const ChatMsgSysGroupAdmin = 1114 // 设置管理员
export const ChatMsgSysGroupMemberRemoved = 1115 // 移出群成员消息(部门群、公司群自动移出) export const ChatMsgSysGroupMemberRemoved = 1115 // 移出群成员消息(部门群、公司群自动移出)
export const ChatMsgSysGroupInfoChange = 1116 // 管理员更新了群信息 export const ChatMsgSysGroupInfoChange = 1116 // 管理员更新了群信息
export const ChatMsgSysPush_PromptReminder = 1117 // 系统推送消息-催办提醒
export const ChatMsgSysPush_NoClockReminderBeforeWork = 1118 // 系统推送消息-上班未打卡
export const ChatMsgSysPush_NoClockReminderAfterWork = 1119 // 系统推送消息-下班未打卡
export const ChatMsgSysPush_ApprovalReminder = 1120 // 系统推送消息-待审批提醒
export const ChatMsgSysPush_CopyReminder = 1121 // 系统推送消息-抄送提醒
export const ChatMsgSysPush_AbsentReminder = 1122 // 系统推送消息-缺卡提醒
export const ChatMsgSysPush_LateReminder = 1123 // 系统推送消息-迟到提醒
export const ChatMsgSysPush_EarlyReminder = 1124 // 系统推送消息-早退提醒
export const ChatMsgTypeMapping = { export const ChatMsgTypeMapping = {
[ChatMsgTypeText]: '[文本消息]', [ChatMsgTypeText]: '[文本消息]',
@ -60,7 +68,15 @@ export const ChatMsgTypeMapping = {
[ChatMsgSysGroupTransfer]: '[转让群主]', [ChatMsgSysGroupTransfer]: '[转让群主]',
[ChatMsgSysGroupAdmin]: '[设置管理员]', [ChatMsgSysGroupAdmin]: '[设置管理员]',
[ChatMsgSysGroupMemberRemoved]: '[移出群成员消息]', [ChatMsgSysGroupMemberRemoved]: '[移出群成员消息]',
[ChatMsgSysGroupInfoChange]: '[群信息更新]' [ChatMsgSysGroupInfoChange]: '[群信息更新]',
[ChatMsgSysPush_PromptReminder]: '[催办提醒]',
[ChatMsgSysPush_NoClockReminderBeforeWork]: '[未打卡提醒]',
[ChatMsgSysPush_NoClockReminderAfterWork]: '[未打卡提醒]',
[ChatMsgSysPush_ApprovalReminder]: '[审批提醒]',
[ChatMsgSysPush_CopyReminder]: '[抄送提醒]',
[ChatMsgSysPush_AbsentReminder]: '[异常卡提醒]',
[ChatMsgSysPush_LateReminder]: '[异常卡提醒]',
[ChatMsgSysPush_EarlyReminder]: '[异常卡提醒]'
} }
// 消息类型 - 消息组件 映射关系 // 消息类型 - 消息组件 映射关系
@ -93,7 +109,16 @@ export const MessageComponents = {
[ChatMsgSysGroupTransfer]: 'sys-group-transfer-message', [ChatMsgSysGroupTransfer]: 'sys-group-transfer-message',
[ChatMsgSysGroupAdmin]:'sys-group-admin-message', [ChatMsgSysGroupAdmin]:'sys-group-admin-message',
[ChatMsgSysGroupMemberRemoved]:'sys-group-member-removed-message', [ChatMsgSysGroupMemberRemoved]:'sys-group-member-removed-message',
[ChatMsgSysGroupInfoChange]:'sys-group-info-change-message' [ChatMsgSysGroupInfoChange]:'sys-group-info-change-message',
// 智能助手推送的系统消息采用相同的模版
[ChatMsgSysPush_PromptReminder]:'sys-push-message',
[ChatMsgSysPush_NoClockReminderBeforeWork]:'sys-push-message',
[ChatMsgSysPush_NoClockReminderAfterWork]:'sys-push-message',
[ChatMsgSysPush_ApprovalReminder]:'sys-push-message',
[ChatMsgSysPush_CopyReminder]:'sys-push-message',
[ChatMsgSysPush_AbsentReminder]:'sys-push-message',
[ChatMsgSysPush_LateReminder]:'sys-push-message',
[ChatMsgSysPush_EarlyReminder]:'sys-push-message'
} }
// 可转发的消息类型 // 可转发的消息类型

View File

@ -94,7 +94,11 @@ class Talk extends Base {
*/ */
getTalkText() { getTalkText() {
let text = '' let text = ''
if (this.resource.msg_type != message.ChatMsgTypeText) { if (
this.resource.msg_type != message.ChatMsgTypeText &&
//智能助手发送的系统消息,也直接显示内容
this.resource.user_id !== 2
) {
text = message.ChatMsgTypeMapping[this.resource.msg_type] text = message.ChatMsgTypeMapping[this.resource.msg_type]
} else { } else {
text = this.resource.extra.content.replace(/<img .*?>/g, '') text = this.resource.extra.content.replace(/<img .*?>/g, '')

View File

@ -58,7 +58,7 @@
:isManager="groupParams?.groupInfo?.is_manager"></settingFormItem> :isManager="groupParams?.groupInfo?.is_manager"></settingFormItem>
</div> </div>
</div> </div>
<div class="chat-records-search chat-settings-card"> <div class="chat-records-search chat-settings-card" v-if="dialogueParams.type !== 1 || (dialogueParams.type === 1 && dialogueParams?.receiver_id !== 2)">
<div @click="toSearchPage"> <div @click="toSearchPage">
<customInput :disabled="true"></customInput> <customInput :disabled="true"></customInput>
</div> </div>
@ -81,7 +81,7 @@
<settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem> <settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem>
</div> </div>
</div> </div>
<div class="chat-group-infos chat-settings-card"> <div class="chat-group-infos chat-settings-card" v-if="dialogueParams.type !== 1 || (dialogueParams.type === 1 && dialogueParams?.receiver_id !== 2)">
<div class="chat-group-infos-each" v-for="(item, index) in state.chatReport" :key="index"> <div class="chat-group-infos-each" v-for="(item, index) in state.chatReport" :key="index">
<settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem> <settingFormItem :item="item" @toManagePage="toManagePage"></settingFormItem>
</div> </div>

View File

@ -84,7 +84,14 @@
" "
> >
<!-- 系统消息 --> <!-- 系统消息 -->
<div v-if="item.msg_type >= 1000" class="message-box"> <!-- item.user_id = 2 是智能助手发送的系统消息风格属于普通消息 -->
<div
v-if="
item.msg_type >= 1000 &&
item.user_id !== 2
"
class="message-box"
>
<component <component
:is="MessageComponents[item.msg_type] || 'unknown-message'" :is="MessageComponents[item.msg_type] || 'unknown-message'"
:extra="item.extra" :extra="item.extra"
@ -147,7 +154,7 @@
class="avatar-column" class="avatar-column"
@click="toUserDetailPage(item)" @click="toUserDetailPage(item)"
@touchstart="() => handleAvatarTouchStart(item)" @touchstart="() => handleAvatarTouchStart(item)"
@touchend="handleAvatarTouchEnd" @touchend="handleAvatarTouchEnd(item)"
> >
<!-- <im-avatar <!-- <im-avatar
class="pointer" class="pointer"
@ -183,6 +190,14 @@
<!-- <span class="at">@</span> --> <!-- <span class="at">@</span> -->
{{ item.nickname }} {{ item.nickname }}
</span> </span>
<!-- 智能助手发送的消息特殊处理 -->
<span
class="nickname pointer"
v-show="talkParams.type == 1 && item.user_id === 2"
>
<!-- <span class="at">@</span> -->
{{ '智能助手' || item?.extra?.title }}
</span>
<span> <span>
{{ parseTime(item.created_at, '{m}/{d} {h}:{i}') }} {{ parseTime(item.created_at, '{m}/{d} {h}:{i}') }}
</span> </span>
@ -197,6 +212,7 @@
:isShowCopy="isShowCopy(item)" :isShowCopy="isShowCopy(item)"
:isShowWithdraw="isRevoke(talkParams.uid, item) || isLeader" :isShowWithdraw="isRevoke(talkParams.uid, item) || isLeader"
:isShowConvertText="isShowConvertText(item)" :isShowConvertText="isShowConvertText(item)"
:isChatRobot="item.user_id === 2"
> >
<component <component
class="component-content" class="component-content"
@ -294,7 +310,11 @@
</div> </div>
</div> </div>
<template #bottom> <template #bottom>
<div class="footBox" id="footBoxArea"> <div
class="footBox"
id="footBoxArea"
v-if="talkParams.receiver_id !== 2"
>
<span <span
class="flex items-center justify-center text-[24rpx] text-[#999999]" class="flex items-center justify-center text-[24rpx] text-[#999999]"
style="background-color: #e5e5e5; padding: 12rpx 24rpx;" style="background-color: #e5e5e5; padding: 12rpx 24rpx;"
@ -510,6 +530,9 @@
</div> </div>
</tm-drawer> </tm-drawer>
</div> </div>
<div id="footBoxArea" v-else>
<div class="h-[68rpx] w-full bg-[#fff]"></div>
</div>
</template> </template>
</ZPaging> </ZPaging>
<tm-drawer <tm-drawer
@ -1910,6 +1933,10 @@ const toChatSettingsPage = () => {
// //
const toUserDetailPage = (userItem) => { const toUserDetailPage = (userItem) => {
//
if (userItem?.user_id === 2) {
return
}
uni.navigateTo({ uni.navigateTo({
url: url:
'/pages/dialog/dialogDetail/userDetail?erpUserId=' + userItem.erp_user_id, '/pages/dialog/dialogDetail/userDetail?erpUserId=' + userItem.erp_user_id,
@ -2073,15 +2100,17 @@ const queryRecordsByMsgInfo = async (msgInfo) => {
}) })
.exec() .exec()
const footBoxAreaQuery = uni.createSelectorQuery() const footBoxAreaQuery = uni.createSelectorQuery()
footBoxAreaQuery const footBoxArea = footBoxAreaQuery.select('#footBoxArea')
.select('#footBoxArea') if (footBoxArea) {
.boundingClientRect((res) => { footBoxArea
if (res) { .boundingClientRect((res) => {
// console.log(':', res.height) if (res) {
offset = offset - res.height // console.log(':', res.height)
} offset = offset - res.height
}) }
.exec() })
.exec()
}
setTimeout(() => { setTimeout(() => {
zpagingRef.value.scrollIntoViewById( zpagingRef.value.scrollIntoViewById(
'zp-id-' + msgInfo.msg_id, 'zp-id-' + msgInfo.msg_id,
@ -2192,6 +2221,10 @@ let avatarPressTimer = null
let currentPressItem = null let currentPressItem = null
const handleAvatarTouchStart = (item) => { const handleAvatarTouchStart = (item) => {
//@
if (item?.user_id === 2) {
return
}
currentPressItem = item currentPressItem = item
avatarPressTimer = setTimeout(() => { avatarPressTimer = setTimeout(() => {
if (!state.value.canUseQuillEditor) { if (!state.value.canUseQuillEditor) {
@ -2202,7 +2235,11 @@ const handleAvatarTouchStart = (item) => {
}, 500) }, 500)
} }
const handleAvatarTouchEnd = () => { const handleAvatarTouchEnd = (item) => {
//@
if (item?.user_id === 2) {
return
}
if (avatarPressTimer) { if (avatarPressTimer) {
clearTimeout(avatarPressTimer) clearTimeout(avatarPressTimer)
avatarPressTimer = null avatarPressTimer = null
@ -2788,16 +2825,18 @@ const convertText = (msgItem) => {
msgId: msgItem.msg_id, msgId: msgItem.msg_id,
}) })
// console.log(resp, 'resp') // console.log(resp, 'resp')
resp.then(({ code, data }) => { resp
msgItem.isVoiceToTexting = false .then(({ code, data }) => {
// console.log(code, data, 'data') msgItem.isVoiceToTexting = false
if (code === 200) { // console.log(code, data, 'data')
console.log(data.convText, 'convText') if (code === 200) {
msgItem.voiceContent = data.convText console.log(data.convText, 'convText')
} msgItem.voiceContent = data.convText
}).catch(() => { }
msgItem.isVoiceToTexting = false })
}) .catch(() => {
msgItem.isVoiceToTexting = false
})
} }
// //
const chatInputHeight = computed(() => { const chatInputHeight = computed(() => {

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB