Skip to content

Commit 63a172a

Browse files
authored
feat: add remote control page, update next dependency (#3501)
* feat: 添加遥控器页面,更新next依赖 * chore: 修改代理为https url
1 parent 299734c commit 63a172a

File tree

8 files changed

+548
-25
lines changed

8 files changed

+548
-25
lines changed

examples/sites/package.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@opentiny/vue-docs",
33
"type": "module",
4-
"version": "3.24.0",
4+
"version": "3.24.3",
55
"license": "MIT",
66
"scripts": {
77
"start": "vite",
@@ -27,8 +27,7 @@
2727
"@docsearch/css": "^3.8.0",
2828
"@docsearch/js": "^3.8.0",
2929
"@docsearch/react": "npm:@docsearch/css",
30-
"@opentiny/next": "0.1.2",
31-
"@opentiny/next-vue": "0.0.1-alpha.1",
30+
"@opentiny/next-vue": "0.0.1",
3231
"@opentiny/tiny-robot": "0.2.1",
3332
"@opentiny/tiny-robot-kit": "0.2.1",
3433
"@opentiny/tiny-robot-svgs": "0.2.1",

examples/sites/src/App.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { iconClose } from '@opentiny/vue-icon'
1717
import { appData } from './tools'
1818
import useTheme from './tools/useTheme'
1919
import { useNextClient } from '@opentiny/next-vue'
20-
import { globalConversation } from './composable/utils'
20+
import { globalConversation, $session } from './composable/utils'
2121
2222
export default defineComponent({
2323
name: 'AppVue',
@@ -33,7 +33,7 @@ export default defineComponent({
3333
3434
const { sessionId } = useNextClient({
3535
clientInfo: { name: 'tiny-vue-website', version: '1.0.0' },
36-
proxyOptions: { url: 'https://39.108.160.245/sse', token: '' }
36+
proxyOptions: { url: 'https://agent.icjs.ink/sse', token: '', sessionId: $session.sessionId }
3737
})
3838
3939
watch(
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
<template>
2+
<div class="message-card" :class="role">
3+
<div class="avatar">
4+
<component :is="avatarIcon" class="avatar-icon" />
5+
</div>
6+
<div class="content">
7+
<div class="role-name">{{ roleName }}</div>
8+
<div class="message">{{ message }}</div>
9+
<div class="time">{{ formatTime }}</div>
10+
</div>
11+
</div>
12+
</template>
13+
14+
<script setup lang="ts">
15+
import { computed } from 'vue'
16+
import { IconAi, IconUser } from '@opentiny/tiny-robot-svgs'
17+
18+
interface Props {
19+
role: 'user' | 'assistant'
20+
message: string
21+
timestamp: number
22+
}
23+
24+
const props = defineProps<Props>()
25+
26+
const roleName = computed(() => (props.role === 'assistant' ? '智能助手' : ''))
27+
28+
const avatarIcon = computed(() => (props.role === 'assistant' ? IconAi : IconUser))
29+
30+
const formatTime = computed(() => {
31+
const date = new Date(props.timestamp)
32+
return date.toLocaleTimeString('zh-CN', {
33+
hour: '2-digit',
34+
minute: '2-digit',
35+
hour12: false
36+
})
37+
})
38+
</script>
39+
40+
<style scoped lang="less">
41+
.message-card {
42+
display: flex;
43+
margin: 16px;
44+
gap: 12px;
45+
max-width: 80%;
46+
47+
&.assistant {
48+
margin-right: auto;
49+
50+
.content {
51+
background-color: #f0f2f5;
52+
}
53+
54+
.avatar-icon {
55+
color: #2080f0;
56+
}
57+
}
58+
59+
&.user {
60+
margin-left: auto;
61+
flex-direction: row-reverse;
62+
63+
.content {
64+
background-color: #e8f5e9;
65+
}
66+
67+
.avatar-icon {
68+
color: #18a058;
69+
}
70+
}
71+
72+
.avatar {
73+
width: 40px;
74+
height: 40px;
75+
border-radius: 50%;
76+
overflow: hidden;
77+
flex-shrink: 0;
78+
display: flex;
79+
align-items: center;
80+
justify-content: center;
81+
background-color: #f5f7fa;
82+
83+
.avatar-icon {
84+
width: 24px;
85+
height: 24px;
86+
}
87+
}
88+
89+
.content {
90+
padding: 12px;
91+
border-radius: 12px;
92+
position: relative;
93+
min-width: 120px;
94+
max-width: calc(100% - 60px);
95+
96+
.role-name {
97+
font-size: 14px;
98+
color: #666;
99+
margin-bottom: 4px;
100+
}
101+
102+
.message {
103+
font-size: 16px;
104+
line-height: 1.5;
105+
word-break: break-word;
106+
white-space: pre-wrap;
107+
}
108+
109+
.time {
110+
font-size: 12px;
111+
color: #999;
112+
margin-top: 4px;
113+
text-align: right;
114+
}
115+
}
116+
}
117+
</style>

examples/sites/src/composable/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@
55

66
import type { ChatMessage, ChatCompletionResponse, StreamHandler } from '@opentiny/tiny-robot-kit'
77
import type { ChatCompletionRequest } from '@opentiny/tiny-robot-kit'
8-
import { ref, type Ref } from 'vue'
8+
import { ref, reactive, type Ref } from 'vue'
99

10-
export { $local } from './storage'
10+
export { $local, $session } from './storage'
1111

1212
export const showTinyRobot = ref(true)
1313

14-
export const globalConversation = {
14+
export const globalConversation = reactive({
1515
id: '',
1616
sessionId: ''
17-
}
17+
})
1818
/**
1919
* 处理SSE流式响应
2020
* @param response fetch响应对象

examples/sites/src/router.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const Docs = () => import('@/views/docs/docs.vue')
88
const Overview = () => import('@/views/overview.vue')
99
const Features = () => import('@/views/features.vue')
1010
const Comprehensive = () => import('@/views/comprehensive/index.vue')
11+
const Remoter = () => import('@/views/remoter/index.vue')
1112

1213
const context = import.meta.env.VITE_CONTEXT
1314

@@ -24,6 +25,11 @@ let routes = [
2425
component: Comprehensive,
2526
name: 'comprehensive'
2627
},
28+
{
29+
path: `${context}:all?/zh-CN/:theme/remoter`,
30+
component: Remoter,
31+
name: 'remoter'
32+
},
2733
// 文档
2834
{
2935
path: `${context}:all?/:lang/:theme/docs/:docId`,

examples/sites/src/views/comprehensive/index.vue

Lines changed: 5 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ watch(
9696
const encryptedId = CryptoJS.AES.encrypt(newVal, 'secret-session-id').toString()
9797
9898
const secretId = encodeURIComponent(encryptedId)
99-
sessionUrl.value = 'http://39.108.160.245?id=' + secretId
99+
sessionUrl.value = `https://agent.icjs.ink?id=${secretId}`
100100
}
101101
},
102102
{ immediate: true }
@@ -202,9 +202,7 @@ watch(
202202
border-radius: 12px;
203203
padding: 32px;
204204
width: 460px;
205-
box-shadow:
206-
0 20px 25px -5px rgba(0, 0, 0, 0.1),
207-
0 10px 10px -5px rgba(0, 0, 0, 0.04);
205+
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
208206
}
209207
210208
.qr-modal-header {
@@ -267,22 +265,13 @@ watch(
267265
268266
@keyframes glow {
269267
0% {
270-
box-shadow:
271-
0 0 5px rgba(22, 119, 255, 0.2),
272-
0 0 10px rgba(22, 119, 255, 0.2),
273-
0 0 15px rgba(22, 119, 255, 0.2);
268+
box-shadow: 0 0 5px rgba(22, 119, 255, 0.2), 0 0 10px rgba(22, 119, 255, 0.2), 0 0 15px rgba(22, 119, 255, 0.2);
274269
}
275270
50% {
276-
box-shadow:
277-
0 0 10px rgba(22, 119, 255, 0.3),
278-
0 0 20px rgba(22, 119, 255, 0.3),
279-
0 0 30px rgba(22, 119, 255, 0.3);
271+
box-shadow: 0 0 10px rgba(22, 119, 255, 0.3), 0 0 20px rgba(22, 119, 255, 0.3), 0 0 30px rgba(22, 119, 255, 0.3);
280272
}
281273
100% {
282-
box-shadow:
283-
0 0 5px rgba(22, 119, 255, 0.2),
284-
0 0 10px rgba(22, 119, 255, 0.2),
285-
0 0 15px rgba(22, 119, 255, 0.2);
274+
box-shadow: 0 0 5px rgba(22, 119, 255, 0.2), 0 0 10px rgba(22, 119, 255, 0.2), 0 0 15px rgba(22, 119, 255, 0.2);
286275
}
287276
}
288277
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
<script setup lang="ts">
2+
// 导入 CryptoJS 库
3+
import CryptoJS from 'crypto-js'
4+
import { reactive } from 'vue'
5+
import { TinyButton, TinyDrawer } from '@opentiny/vue'
6+
import RobotChat from '../../components/tiny-robot-chat.vue'
7+
import Sound from './sound.vue'
8+
import { globalConversation } from '../../composable/utils'
9+
10+
// 加密密钥,需要和生成二维码的页面保持一致
11+
const secretKey = 'secret-session-id'
12+
// 获取 URL 参数
13+
const urlParams = new URLSearchParams(window.location.search)
14+
const encryptedId = urlParams.get('id')
15+
const state = reactive({ isShow: true, showChat: false, showSound: false })
16+
17+
if (encryptedId) {
18+
// 解密 id
19+
const bytes = CryptoJS.AES.decrypt(encryptedId, secretKey)
20+
const originalText = bytes.toString(CryptoJS.enc.Utf8)
21+
// 存储解密后的 id 到 window.sessionId
22+
globalConversation.sessionId = originalText
23+
}
24+
const showMoter = (type) => {
25+
state.isShow = false
26+
state[type] = true
27+
}
28+
</script>
29+
30+
<template>
31+
<div>
32+
<RobotChat v-if="state.showChat" />
33+
<Sound v-if="state.showSound" />
34+
<tiny-drawer
35+
v-if="state.isShow"
36+
title="请选择控制器"
37+
placement="bottom"
38+
:mask-closable="false"
39+
:show-close="false"
40+
v-model:visible="state.isShow"
41+
height="400px"
42+
>
43+
<div class="link-box">
44+
<tiny-button @click="showMoter('showSound')" type="info" size="large">语音控制器</tiny-button>
45+
46+
<tiny-button @click="showMoter('showChat')" type="info" size="large">综合控制器</tiny-button>
47+
</div>
48+
</tiny-drawer>
49+
</div>
50+
</template>
51+
52+
<style scoped lang="less">
53+
.link-box {
54+
display: flex;
55+
flex-direction: column;
56+
justify-content: center;
57+
align-items: center;
58+
59+
.tiny-button {
60+
margin-bottom: 20px;
61+
}
62+
}
63+
</style>

0 commit comments

Comments
 (0)