111
This commit is contained in:
@@ -114,6 +114,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { IUserInfo } from '~/types/user'
|
||||
|
||||
definePageMeta({
|
||||
layout: layout.empty
|
||||
})
|
||||
@@ -121,6 +123,8 @@ definePageMeta({
|
||||
type ErrorField = 'username' | 'password' | 'agreement'
|
||||
|
||||
const isSubmitting = ref(false)
|
||||
const userStore = useUserStore()
|
||||
const { emit } = useEventBus()
|
||||
|
||||
const form = reactive({
|
||||
username: '',
|
||||
@@ -194,6 +198,23 @@ const handleSubmit = async () => {
|
||||
try {
|
||||
isSubmitting.value = true
|
||||
await new Promise((resolve) => setTimeout(resolve, 900))
|
||||
|
||||
const loginAt = new Date().toISOString()
|
||||
const mockUserInfo: IUserInfo = {
|
||||
id: Date.now(),
|
||||
username: form.username.trim(),
|
||||
nickname: form.username.trim(),
|
||||
role: 'user'
|
||||
}
|
||||
|
||||
userStore.setUserInfo(mockUserInfo, `demo-token-${mockUserInfo.id}`)
|
||||
emit('auth:login', {
|
||||
userId: mockUserInfo.id || 0,
|
||||
username: mockUserInfo.username || '',
|
||||
nickname: mockUserInfo.nickname || '',
|
||||
loginAt
|
||||
})
|
||||
|
||||
showSuccessToast('登录成功')
|
||||
await navigateTo('/home')
|
||||
} finally {
|
||||
|
||||
@@ -5,14 +5,13 @@
|
||||
<p class="eyebrow">SignalR IM Demo</p>
|
||||
<h1>即时通讯测试页</h1>
|
||||
<p class="hero-text">
|
||||
当前已对接服务端 `ChatHub`,默认调用 `SendMessage(user, message)`,监听 `ReceiveMessage`、
|
||||
`UserConnected` 和 `UserDisconnected`。
|
||||
当前页面会连接服务端 `ChatHub`,默认调用 `SendMessage(user, message)`,并监听 `ReceiveMessage`、`UserConnected`、`UserDisconnected`。收到聊天消息时会同步发出全局事件 `chat:received`。
|
||||
</p>
|
||||
</div>
|
||||
<div class="status-box">
|
||||
<span class="status-label">连接状态</span>
|
||||
<strong :class="['status-pill', `is-${status}`]">{{ statusText }}</strong>
|
||||
<span v-if="connectionId" class="connection-id">连接ID:{{ connectionId }}</span>
|
||||
<span v-if="connectionId" class="connection-id">连接 ID:{{ connectionId }}</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -34,7 +33,7 @@
|
||||
<textarea
|
||||
v-model.trim="accessToken"
|
||||
rows="3"
|
||||
placeholder="如后端开启鉴权,可在这里粘贴 token;为空则匿名连接。"
|
||||
placeholder="如果服务端开启鉴权,可以在这里粘贴 token;为空则匿名连接。"
|
||||
/>
|
||||
</label>
|
||||
|
||||
@@ -48,7 +47,7 @@
|
||||
<section class="panel">
|
||||
<div class="panel-title">消息面板</div>
|
||||
<div ref="messageListRef" class="message-list">
|
||||
<div v-if="!messages.length" class="empty-state">还没有消息,先连接然后发送一条试试。</div>
|
||||
<div v-if="!messages.length" class="empty-state">还没有消息,先连接再发一条试试。</div>
|
||||
<article
|
||||
v-for="item in messages"
|
||||
:key="item.id"
|
||||
@@ -113,6 +112,7 @@ interface LogItem {
|
||||
}
|
||||
|
||||
const userStore = useUserStore()
|
||||
const { emit } = useEventBus()
|
||||
|
||||
const defaultHubUrl = `${BaseConfig.BaseUrl.replace(/\/$/, '')}/chatHub`
|
||||
|
||||
@@ -193,7 +193,16 @@ const resolveHubUrl = (value: string) => {
|
||||
|
||||
const registerConnectionEvents = (hub: HubConnection) => {
|
||||
hub.on('ReceiveMessage', (user: string, message: string) => {
|
||||
addMessage(user || '匿名用户', message || '')
|
||||
const sender = user || '匿名用户'
|
||||
const text = message || ''
|
||||
|
||||
addMessage(sender, text)
|
||||
emit('chat:received', {
|
||||
user: sender,
|
||||
message: text,
|
||||
receivedAt: new Date().toISOString(),
|
||||
type: 'chat'
|
||||
})
|
||||
})
|
||||
|
||||
hub.on('UserConnected', (id: string) => {
|
||||
@@ -214,7 +223,7 @@ const registerConnectionEvents = (hub: HubConnection) => {
|
||||
hub.onreconnected((id) => {
|
||||
status.value = 'connected'
|
||||
connectionId.value = id || hub.connectionId || ''
|
||||
addLog(`重连成功:${connectionId.value || '无连接ID'}`)
|
||||
addLog(`重连成功:${connectionId.value || '无连接 ID'}`)
|
||||
})
|
||||
|
||||
hub.onclose((error) => {
|
||||
@@ -265,7 +274,7 @@ const connectHub = async () => {
|
||||
connectionId.value = hub.connectionId || ''
|
||||
status.value = 'connected'
|
||||
|
||||
addLog(`连接成功:${connectionId.value || '未返回连接ID'}`)
|
||||
addLog(`连接成功:${connectionId.value || '未返回连接 ID'}`)
|
||||
addMessage('系统', 'SignalR 已连接,可以开始发送消息。', 'system')
|
||||
} catch (error) {
|
||||
status.value = 'error'
|
||||
@@ -389,6 +398,7 @@ h1 {
|
||||
max-width: 640px;
|
||||
color: #665246;
|
||||
font-size: 14px;
|
||||
line-height: 1.7;
|
||||
}
|
||||
|
||||
.status-box {
|
||||
|
||||
@@ -2,14 +2,44 @@
|
||||
<div class="page-home">
|
||||
<section class="home-card">
|
||||
<p class="page-tag">Home</p>
|
||||
<h1>前端调试入口</h1>
|
||||
<h1>页面事件总线</h1>
|
||||
<p class="page-desc">
|
||||
这里先放一个即时通讯测试页入口,方便直接验证 SignalR 连接、收发消息和连接状态。
|
||||
这一版只保留最小能力:页面自己定义事件名,自己决定 payload 结构,通过 `on / emit / off / clear` 完成页面间监听和订阅。
|
||||
</p>
|
||||
|
||||
<NuxtLink class="entry-link" to="/home/im">
|
||||
进入 IM Demo
|
||||
</NuxtLink>
|
||||
<div class="feature-list">
|
||||
<div class="feature-item">
|
||||
<strong>自定义事件名</strong>
|
||||
<span>例如 `auth:login`、`chat:received`、`user:refresh`</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<strong>自定义数据</strong>
|
||||
<span>payload 不做预设,页面按业务自己约定</span>
|
||||
</div>
|
||||
<div class="feature-item">
|
||||
<strong>自动解绑</strong>
|
||||
<span>`useEventBus().on()` 在页面销毁时会自动取消监听</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="code-card">
|
||||
<pre><code>const { on, emit } = useEventBus()
|
||||
|
||||
on('user:refresh', (payload) => {
|
||||
console.log(payload)
|
||||
})
|
||||
|
||||
emit('user:refresh', { id: 1 })</code></pre>
|
||||
</div>
|
||||
|
||||
<div class="entry-row">
|
||||
<NuxtLink class="entry-link" to="/auth/login">
|
||||
前往登录页
|
||||
</NuxtLink>
|
||||
<NuxtLink class="entry-link secondary" to="/home/im">
|
||||
进入 IM Demo
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</template>
|
||||
@@ -18,6 +48,26 @@
|
||||
definePageMeta({
|
||||
layout: layout.default
|
||||
})
|
||||
|
||||
interface IUserRefreshPayload {
|
||||
id: number
|
||||
name: string
|
||||
}
|
||||
|
||||
const { on, emit } = useEventBus()
|
||||
|
||||
// EventBus 使用示例:订阅自定义事件
|
||||
on<IUserRefreshPayload>('user:refresh', (payload) => {
|
||||
console.log('收到 user:refresh 事件', payload)
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
// EventBus 使用示例:派发自定义事件
|
||||
emit<IUserRefreshPayload>('user:refresh', {
|
||||
id: 1,
|
||||
name: 'captain'
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -25,7 +75,11 @@ definePageMeta({
|
||||
.page-home div,
|
||||
.page-home section,
|
||||
.page-home p,
|
||||
.page-home h1 {
|
||||
.page-home h1,
|
||||
.page-home strong,
|
||||
.page-home span,
|
||||
.page-home pre,
|
||||
.page-home code {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
@@ -38,7 +92,7 @@ definePageMeta({
|
||||
}
|
||||
|
||||
.home-card {
|
||||
width: min(720px, 100%);
|
||||
width: min(760px, 100%);
|
||||
margin: 0 auto;
|
||||
padding: 24px;
|
||||
border-radius: 24px;
|
||||
@@ -62,8 +116,54 @@ h1 {
|
||||
|
||||
.page-desc {
|
||||
margin-top: 12px;
|
||||
color: #665246;
|
||||
font-size: 15px;
|
||||
line-height: 1.7;
|
||||
color: #665246;
|
||||
}
|
||||
|
||||
.feature-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.feature-item,
|
||||
.code-card {
|
||||
padding: 14px 16px;
|
||||
border-radius: 18px;
|
||||
background: rgba(255, 255, 255, 0.88);
|
||||
border: 1px solid rgba(98, 77, 65, 0.12);
|
||||
}
|
||||
|
||||
.feature-item strong {
|
||||
display: block;
|
||||
font-size: 15px;
|
||||
color: #2a221d;
|
||||
}
|
||||
|
||||
.feature-item span {
|
||||
display: block;
|
||||
margin-top: 6px;
|
||||
font-size: 14px;
|
||||
color: #665246;
|
||||
}
|
||||
|
||||
.code-card {
|
||||
margin-top: 16px;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.code-card code {
|
||||
font-size: 14px;
|
||||
line-height: 1.7;
|
||||
color: #3f3129;
|
||||
}
|
||||
|
||||
.entry-row {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.entry-link {
|
||||
@@ -71,12 +171,19 @@ h1 {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-width: 140px;
|
||||
margin-top: 20px;
|
||||
padding: 12px 18px;
|
||||
border-radius: 14px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.entry-link {
|
||||
background: linear-gradient(135deg, #fe5e08 0%, #d9534f 100%);
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.entry-link.secondary {
|
||||
background: rgba(89, 70, 59, 0.08);
|
||||
color: #4a3a31;
|
||||
}
|
||||
|
||||
.entry-link:hover,
|
||||
@@ -85,4 +192,10 @@ h1 {
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #db5208 0%, #bf4744 100%);
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
h1 {
|
||||
font-size: 24px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -91,16 +91,19 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
|
||||
// MessageExtend.showToast('success', '更新成功!')
|
||||
MessageExtend.notifyList('primary', ['获取装备'])
|
||||
|
||||
|
||||
//MessageExtend.ShowToast('success', '更新成功!')
|
||||
//MessageExtend.NotifyList("success", ['获取装备',"获取物品"])
|
||||
definePageMeta({
|
||||
layout: layout.empty
|
||||
})
|
||||
showNotify({ message: '提示' });
|
||||
// await navigateTo('/auth/login', { replace: true })
|
||||
onMounted(() => {
|
||||
req();
|
||||
alert(1);
|
||||
onMounted(async () => {
|
||||
|
||||
const test = await LoginService.Test("dddd","dddd2");
|
||||
console.log(test);
|
||||
|
||||
//alert(1);
|
||||
})
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user