Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
DCloud
uni-ai-chat
提交
2a5d4ce4
U
uni-ai-chat
项目概览
DCloud
/
uni-ai-chat
通知
893
Star
11
Fork
8
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
2
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
U
uni-ai-chat
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
2
Issue
2
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
提交
2a5d4ce4
编写于
5月 08, 2023
作者:
DCloud_JSON
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
替换 SSEChannel 为 sseChannel
上级
fe468eca
变更
6
隐藏空白更改
内联
并排
Showing
6 changed file
with
403 addition
and
421 deletion
+403
-421
manifest.json
manifest.json
+1
-1
pages/chat/chat.vue
pages/chat/chat.vue
+344
-344
uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js
uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js
+12
-12
uniCloud-aliyun/database/opendb-app-client-key.schema.json
uniCloud-aliyun/database/opendb-app-client-key.schema.json
+0
-34
uniCloud-aliyun/database/uni-ai-chat.schema.json
uniCloud-aliyun/database/uni-ai-chat.schema.json
+0
-30
uniCloud-aliyun/database/uni-id-scores.schema.json
uniCloud-aliyun/database/uni-id-scores.schema.json
+46
-0
未找到文件。
manifest.json
浏览文件 @
2a5d4ce4
...
@@ -88,7 +88,7 @@
...
@@ -88,7 +88,7 @@
"vueVersion"
:
"3"
,
"vueVersion"
:
"3"
,
"h5"
:
{
"h5"
:
{
"unipush"
:
{
"unipush"
:
{
"enable"
:
fals
e
"enable"
:
tru
e
}
}
},
},
"fallbackLocale"
:
"zh-Hans"
"fallbackLocale"
:
"zh-Hans"
...
...
pages/chat/chat.vue
浏览文件 @
2a5d4ce4
<
template
>
<
template
>
<view
class=
"page"
>
<view
class=
"page"
>
<view
class=
"container"
>
<view
class=
"container"
>
<view
v-if=
"isWidescreen"
class=
"header"
>
uni-ai-chat
</view>
<view
v-if=
"isWidescreen"
class=
"header"
>
uni-ai-chat
</view>
<text
class=
"noData"
v-if=
"msgList.length === 0"
>
没有对话记录
</text>
<text
class=
"noData"
v-if=
"msgList.length === 0"
>
没有对话记录
</text>
<scroll-view
:scroll-into-view=
"scrollIntoView"
scroll-y=
"true"
class=
"msg-list"
:enable-flex=
"true"
>
<scroll-view
:scroll-into-view=
"scrollIntoView"
scroll-y=
"true"
class=
"msg-list"
:enable-flex=
"true"
>
<view
v-for=
"(msg,index) in msgList"
class=
"msg-item"
:key=
"index"
>
<view
v-for=
"(msg,index) in msgList"
class=
"msg-item"
:key=
"index"
>
<view
class=
"create_time-box"
>
<view
class=
"create_time-box"
>
<uni-dateformat
class=
"create_time"
:date=
"msg.create_time"
format=
"MM/dd hh:mm:ss"
></uni-dateformat>
<uni-dateformat
class=
"create_time"
:date=
"msg.create_time"
format=
"MM/dd hh:mm:ss"
></uni-dateformat>
</view>
</view>
<view
:class=
"
{reverse:!msg.isAi}">
<view
:class=
"
{reverse:!msg.isAi}">
<view
class=
"userInfo"
>
<view
class=
"userInfo"
>
<image
class=
"avatar"
:src=
"msg.isAi?'../../static/uni-ai.png':'../../static/avatar.png'"
mode=
"widthFix"
></image>
<image
class=
"avatar"
:src=
"msg.isAi?'../../static/uni-ai.png':'../../static/avatar.png'"
mode=
"widthFix"
></image>
</view>
</view>
<view
class=
"content"
>
<view
class=
"content"
>
<!--
<text
class=
"copy"
@
click=
"copy"
>
复制
</text>
-->
<!--
<text
class=
"copy"
@
click=
"copy"
>
复制
</text>
-->
<uni-ai-msg
:md=
"msg.content"
:show-cursor=
"index == msgList.length-1 && msg.isAi && sseIndex"
></uni-ai-msg>
<uni-ai-msg
:md=
"msg.content"
:show-cursor=
"index == msgList.length-1 && msg.isAi && sseIndex"
></uni-ai-msg>
<view
v-if=
"index == msgList.length-1 && adpid && msg.insufficientPoints"
>
<view
v-if=
"index == msgList.length-1 && adpid && msg.insufficientPoints"
>
<uni-ad-rewarded-video
:adpid=
"adpid"
@
onAdClose=
"onAdClose"
></uni-ad-rewarded-video>
<uni-ad-rewarded-video
:adpid=
"adpid"
@
onAdClose=
"onAdClose"
></uni-ad-rewarded-video>
</view>
</view>
</view>
</view>
<uni-icons
v-if=
"index == msgList.length-1 && !msg.isAi && msg.state != 100 && msgStateIcon(msg)"
<uni-icons
v-if=
"index == msgList.length-1 && !msg.isAi && msg.state != 100 && msgStateIcon(msg)"
@
click=
"msg.state == -100 ? retriesSendMsg() : ''"
:color=
"msg.state===0?'#999':'#d22'"
@
click=
"msg.state == -100 ? retriesSendMsg() : ''"
:color=
"msg.state===0?'#999':'#d22'"
:type=
"msgStateIcon(msg)"
class=
"msgStateIcon"
>
:type=
"msgStateIcon(msg)"
class=
"msgStateIcon"
>
</uni-icons>
</uni-icons>
</view>
</view>
</view>
</view>
<view
class=
"tip-ai-ing"
v-if=
"msgList.length && msgList.length%2 !== 0"
>
<view
class=
"tip-ai-ing"
v-if=
"msgList.length && msgList.length%2 !== 0"
>
<text>
uni-ai正在思考中...
</text>
<text>
uni-ai正在思考中...
</text>
<view
v-if=
"NODE_ENV == 'development' && !stream"
>
<view
v-if=
"NODE_ENV == 'development' && !stream"
>
如需提速,请开通
<uni-link
class=
"uni-link"
href=
"https://uniapp.dcloud.net.cn/uniCloud/uni-ai-chat.html"
text=
"[流式响应]"
></uni-link>
如需提速,请开通
<uni-link
class=
"uni-link"
href=
"https://uniapp.dcloud.net.cn/uniCloud/uni-ai-chat.html"
text=
"[流式响应]"
></uni-link>
</view>
</view>
</view>
</view>
<view
id=
"last-msg-item"
></view>
<view
id=
"last-msg-item"
></view>
</scroll-view>
</scroll-view>
<view
class=
"foot-box"
>
<view
class=
"foot-box"
>
<view
class=
"menu"
v-if=
"isWidescreen"
>
<view
class=
"menu"
v-if=
"isWidescreen"
>
<view
class=
"trash menu-item"
>
<view
class=
"trash menu-item"
>
...
@@ -53,56 +53,56 @@
...
@@ -53,56 +53,56 @@
<text
v-if=
"isWidescreen"
class=
"send-btn-tip"
>
↵ 发送 / shift + ↵ 换行
</text>
<text
v-if=
"isWidescreen"
class=
"send-btn-tip"
>
↵ 发送 / shift + ↵ 换行
</text>
<button
@
click=
"beforeSendMsg"
:disabled=
"inputBoxDisabled || !content"
class=
"send"
type=
"primary"
>
发送
</button>
<button
@
click=
"beforeSendMsg"
:disabled=
"inputBoxDisabled || !content"
class=
"send"
type=
"primary"
>
发送
</button>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</
template
>
</
template
>
<
script
>
<
script
>
import
config
from
'
@/config.js
'
;
import
config
from
'
@/config.js
'
;
const
{
adpid
}
=
config
const
{
adpid
}
=
config
export
default
{
export
default
{
data
()
{
data
()
{
return
{
return
{
scrollIntoView
:
""
,
scrollIntoView
:
""
,
msgList
:
[],
msgList
:
[],
content
:
""
,
content
:
""
,
sseIndex
:
0
,
sseIndex
:
0
,
stream
:
true
,
stream
:
true
,
isWidescreen
:
false
,
isWidescreen
:
false
,
adpid
adpid
}
}
},
},
computed
:
{
computed
:
{
inputBoxDisabled
()
{
inputBoxDisabled
()
{
if
(
this
.
sseIndex
!==
0
)
{
if
(
this
.
sseIndex
!==
0
)
{
return
true
return
true
}
}
return
!!
(
this
.
msgList
.
length
&&
this
.
msgList
.
length
%
2
!==
0
)
return
!!
(
this
.
msgList
.
length
&&
this
.
msgList
.
length
%
2
!==
0
)
},
},
placeholderText
()
{
placeholderText
()
{
if
(
this
.
inputBoxDisabled
)
{
if
(
this
.
inputBoxDisabled
)
{
return
'
uni-ai正在回复中
'
return
'
uni-ai正在回复中
'
}
else
{
}
else
{
// #ifdef H5
// #ifdef H5
return
window
.
innerWidth
>
960
?
'
请输入内容,ctrl + enter 发送
'
:
'
请输入要发给uni-ai的内容
'
return
window
.
innerWidth
>
960
?
'
请输入内容,ctrl + enter 发送
'
:
'
请输入要发给uni-ai的内容
'
// #endif
// #endif
return
'
请输入要发给uni-ai的内容
'
return
'
请输入要发给uni-ai的内容
'
}
}
},
},
NODE_ENV
(){
NODE_ENV
(){
return
process
.
env
.
NODE_ENV
return
process
.
env
.
NODE_ENV
}
}
},
},
watch
:
{
watch
:
{
msgList
:{
msgList
:{
handler
(
msgList
)
{
handler
(
msgList
)
{
uni
.
setStorageSync
(
'
uni-ai-msg
'
,
msgList
)
uni
.
setStorageSync
(
'
uni-ai-msg
'
,
msgList
)
},
},
deep
:
true
deep
:
true
}
}
},
},
async
mounted
()
{
async
mounted
()
{
if
(
this
.
adpid
&&
uniCloud
.
getCurrentUserInfo
().
tokenExpired
>
Date
.
now
()){
if
(
this
.
adpid
&&
uniCloud
.
getCurrentUserInfo
().
tokenExpired
>
Date
.
now
()){
let
db
=
uniCloud
.
databaseForJQL
();
let
db
=
uniCloud
.
databaseForJQL
();
...
@@ -120,17 +120,17 @@
...
@@ -120,17 +120,17 @@
// console.log('score',score);
// console.log('score',score);
// for (let i = 0; i
<
15
;
i
++
)
{
// for (let i = 0; i
<
15
;
i
++
)
{
// this.msgList.push({
// this.msgList.push({
// isAi: i % 2 == true,
// isAi: i % 2 == true,
// content: "1-" + i
// content: "1-" + i
// })
// })
// }
// }
this
.
msgList
=
uni
.
getStorageSync
(
'
uni-ai-msg
'
)
||
[]
this
.
msgList
=
uni
.
getStorageSync
(
'
uni-ai-msg
'
)
||
[]
// this.msgList.pop()
// this.msgList.pop()
// console.log('this.msgList', this.msgList);
// console.log('this.msgList', this.msgList);
this
.
showLastMsg
()
this
.
showLastMsg
()
// #ifdef H5
// #ifdef H5
...
@@ -167,7 +167,7 @@
...
@@ -167,7 +167,7 @@
this
.
isWidescreen
=
matches
;
this
.
isWidescreen
=
matches
;
})
})
// #endif
// #endif
},
},
methods
:
{
methods
:
{
//检查是否开通uni-push;决定是否启用stream
//检查是否开通uni-push;决定是否启用stream
async
checkIsOpenPush
(){
async
checkIsOpenPush
(){
...
@@ -233,8 +233,8 @@
...
@@ -233,8 +233,8 @@
async
retriesSendMsg
()
{
async
retriesSendMsg
()
{
// 检查是否开通uni-push;决定是否启用stream
// 检查是否开通uni-push;决定是否启用stream
await
this
.
checkIsOpenPush
()
await
this
.
checkIsOpenPush
()
this
.
send
()
this
.
send
()
},
},
async
beforeSendMsg
()
{
async
beforeSendMsg
()
{
// 如果开启了广告位需要登录
// 如果开启了广告位需要登录
if
(
this
.
adpid
){
if
(
this
.
adpid
){
...
@@ -277,57 +277,57 @@
...
@@ -277,57 +277,57 @@
icon
:
'
none
'
icon
:
'
none
'
});
});
}
}
this
.
msgList
.
push
({
this
.
msgList
.
push
({
isAi
:
false
,
isAi
:
false
,
content
:
this
.
content
,
content
:
this
.
content
,
state
:
0
,
state
:
0
,
create_time
:
Date
.
now
()
create_time
:
Date
.
now
()
})
})
this
.
showLastMsg
()
this
.
showLastMsg
()
// 清空文本内容
// 清空文本内容
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
this
.
content
=
''
this
.
content
=
''
})
})
this
.
send
()
this
.
send
()
},
},
async
send
()
{
async
send
()
{
let
messages
=
[]
let
messages
=
[]
// 复制一份,消息列表数据
// 复制一份,消息列表数据
let
msgs
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
msgList
))
let
msgs
=
JSON
.
parse
(
JSON
.
stringify
(
this
.
msgList
))
// 带总结的消息 index
// 带总结的消息 index
let
findIndex
=
[...
msgs
].
reverse
().
findIndex
(
item
=>
item
.
summarize
)
let
findIndex
=
[...
msgs
].
reverse
().
findIndex
(
item
=>
item
.
summarize
)
// console.log('findIndex', findIndex)
// console.log('findIndex', findIndex)
if
(
findIndex
!=
-
1
)
{
if
(
findIndex
!=
-
1
)
{
let
aiSummaryIndex
=
msgs
.
length
-
findIndex
-
1
let
aiSummaryIndex
=
msgs
.
length
-
findIndex
-
1
// console.log('aiSummaryIndex', aiSummaryIndex)
// console.log('aiSummaryIndex', aiSummaryIndex)
msgs
[
aiSummaryIndex
].
content
=
msgs
[
aiSummaryIndex
].
summarize
msgs
[
aiSummaryIndex
].
content
=
msgs
[
aiSummaryIndex
].
summarize
// 拿最后一条带直接的消息作为与ai对话的msg body
// 拿最后一条带直接的消息作为与ai对话的msg body
msgs
=
msgs
.
splice
(
aiSummaryIndex
,
msgs
.
length
-
1
)
msgs
=
msgs
.
splice
(
aiSummaryIndex
,
msgs
.
length
-
1
)
}
else
{
}
else
{
// 如果未总结过就直接从末尾拿10条
// 如果未总结过就直接从末尾拿10条
msgs
=
msgs
.
splice
(
-
10
)
msgs
=
msgs
.
splice
(
-
10
)
}
}
messages
=
msgs
.
map
(
item
=>
{
messages
=
msgs
.
map
(
item
=>
{
let
role
=
"
user
"
let
role
=
"
user
"
if
(
item
.
isAi
)
{
if
(
item
.
isAi
)
{
role
=
item
.
summarize
?
'
system
'
:
'
assistant
'
role
=
item
.
summarize
?
'
system
'
:
'
assistant
'
}
}
return
{
return
{
content
:
item
.
content
,
content
:
item
.
content
,
role
role
}
}
})
})
console
.
log
(
'
send to ai messages:
'
,
messages
);
console
.
log
(
'
send to ai messages:
'
,
messages
);
let
SSE
Channel
=
false
;
let
sse
Channel
=
false
;
if
(
this
.
stream
){
if
(
this
.
stream
){
SSE
Channel
=
new
uniCloud
.
SSEChannel
()
// 创建消息通道
sse
Channel
=
new
uniCloud
.
SSEChannel
()
// 创建消息通道
// console.log('
SSEChannel',SSE
Channel);
// console.log('
sseChannel',sse
Channel);
SSE
Channel
.
on
(
'
message
'
,
(
message
)
=>
{
// 监听message事件
sse
Channel
.
on
(
'
message
'
,
(
message
)
=>
{
// 监听message事件
// console.log('on message', message);
// console.log('on message', message);
if
(
this
.
sseIndex
===
0
)
{
if
(
this
.
sseIndex
===
0
)
{
this
.
msgList
.
push
({
this
.
msgList
.
push
({
...
@@ -344,7 +344,7 @@
...
@@ -344,7 +344,7 @@
}
}
this
.
sseIndex
++
this
.
sseIndex
++
})
})
SSE
Channel
.
on
(
'
end
'
,
(
e
)
=>
{
// 监听end事件,如果云端执行end时传了message,会在客户端end事件内收到传递的消息
sse
Channel
.
on
(
'
end
'
,
(
e
)
=>
{
// 监听end事件,如果云端执行end时传了message,会在客户端end事件内收到传递的消息
// console.log('on end', e);
// console.log('on end', e);
if
(
e
&&
(
e
.
summarize
||
e
.
insufficientPoints
)){
if
(
e
&&
(
e
.
summarize
||
e
.
insufficientPoints
)){
this
.
updateLastMsg
(
lastMsg
=>
{
this
.
updateLastMsg
(
lastMsg
=>
{
...
@@ -358,102 +358,102 @@
...
@@ -358,102 +358,102 @@
this
.
sseIndex
=
0
this
.
sseIndex
=
0
this
.
showLastMsg
()
this
.
showLastMsg
()
})
})
await
SSE
Channel
.
open
()
// 等待通道开启
await
sse
Channel
.
open
()
// 等待通道开启
}
}
const
uniAiChat
=
uniCloud
.
importObject
(
"
uni-ai-chat
"
,{
const
uniAiChat
=
uniCloud
.
importObject
(
"
uni-ai-chat
"
,{
customUI
:
true
customUI
:
true
})
})
uniAiChat
.
send
({
uniAiChat
.
send
({
messages
,
messages
,
SSE
Channel
sse
Channel
})
})
.
then
(
res
=>
{
.
then
(
res
=>
{
this
.
updateLastMsg
({
state
:
100
})
this
.
updateLastMsg
({
state
:
100
})
if
(
!
SSEChannel
)
{
if
(
!
sseChannel
)
{
// console.log(res, res.reply);
// console.log(res, res.reply);
this
.
msgList
.
push
({
this
.
msgList
.
push
({
isAi
:
true
,
isAi
:
true
,
content
:
res
.
data
.
reply
,
content
:
res
.
data
.
reply
,
summarize
:
res
.
data
.
summarize
,
summarize
:
res
.
data
.
summarize
,
create_time
:
Date
.
now
(),
create_time
:
Date
.
now
(),
insufficientPoints
:
res
.
data
.
insufficientPoints
insufficientPoints
:
res
.
data
.
insufficientPoints
})
})
this
.
showLastMsg
()
this
.
showLastMsg
()
}
}
})
})
.
catch
(
e
=>
{
.
catch
(
e
=>
{
console
.
log
(
e
);
console
.
log
(
e
);
this
.
updateLastMsg
({
state
:
-
100
})
this
.
updateLastMsg
({
state
:
-
100
})
uni
.
showModal
({
uni
.
showModal
({
content
:
JSON
.
stringify
(
e
.
message
),
content
:
JSON
.
stringify
(
e
.
message
),
showCancel
:
false
showCancel
:
false
});
});
})
})
},
},
showLastMsg
()
{
showLastMsg
()
{
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
this
.
scrollIntoView
=
"
last-msg-item
"
this
.
scrollIntoView
=
"
last-msg-item
"
this
.
$nextTick
(()
=>
{
this
.
$nextTick
(()
=>
{
this
.
scrollIntoView
=
""
this
.
scrollIntoView
=
""
})
})
})
})
},
},
msgStateIcon
(
msg
)
{
msgStateIcon
(
msg
)
{
switch
(
msg
.
state
)
{
switch
(
msg
.
state
)
{
case
0
:
case
0
:
// 发送中
// 发送中
return
'
spinner-cycle
'
return
'
spinner-cycle
'
break
;
break
;
case
-
100
:
case
-
100
:
// 发送失败
// 发送失败
return
'
refresh-filled
'
return
'
refresh-filled
'
break
;
break
;
case
-
200
:
case
-
200
:
// 禁止发送(内容不合法)
// 禁止发送(内容不合法)
return
'
info-filled
'
return
'
info-filled
'
break
;
break
;
default
:
default
:
return
false
return
false
break
;
break
;
}
}
},
},
clear
()
{
clear
()
{
uni
.
showModal
({
uni
.
showModal
({
title
:
"
确认要清空聊天记录?
"
,
title
:
"
确认要清空聊天记录?
"
,
content
:
'
本操作不可撤销
'
,
content
:
'
本操作不可撤销
'
,
complete
:
(
e
)
=>
{
complete
:
(
e
)
=>
{
if
(
e
.
confirm
)
{
if
(
e
.
confirm
)
{
this
.
msgList
=
[]
this
.
msgList
=
[]
}
}
}
}
});
});
}
}
}
}
}
}
</
script
>
</
script
>
<
style
lang=
"scss"
>
<
style
lang=
"scss"
>
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
view
,
view
,
textarea
,
textarea
,
button
,
button
,
.page
.page
{
{
display
:
flex
;
display
:
flex
;
box-sizing
:
border-box
;
box-sizing
:
border-box
;
}
}
/* #endif */
/* #endif */
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
page
,
page
,
/*
#endif
*/
/*
#endif
*/
.page
,
.page
,
.container
{
.container
{
background-color
:
#efefef
;
background-color
:
#efefef
;
/* #ifdef APP-NVUE */
/* #ifdef APP-NVUE */
flex
:
1
;
flex
:
1
;
/* #endif */
/* #endif */
...
@@ -466,147 +466,147 @@
...
@@ -466,147 +466,147 @@
height
:
calc
(
100vh
-
44px
);
height
:
calc
(
100vh
-
44px
);
/* #endif */
/* #endif */
flex-direction
:
column
;
flex-direction
:
column
;
align-items
:
center
;
align-items
:
center
;
justify-content
:
center
;
justify-content
:
center
;
}
}
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
.container
{
.container
{
background-color
:
#FAFAFA
;
background-color
:
#FAFAFA
;
}
}
/* #endif */
/* #endif */
.foot-box
{
.foot-box
{
width
:
750rpx
;
width
:
750rpx
;
display
:
flex
;
display
:
flex
;
flex-direction
:
column
;
flex-direction
:
column
;
padding
:
10px
0px
;
padding
:
10px
0px
;
background-color
:
#FFF
;
background-color
:
#FFF
;
}
}
.foot-box-content
{
.foot-box-content
{
justify-content
:
space-around
;
justify-content
:
space-around
;
}
}
.textarea-box
{
.textarea-box
{
padding
:
8px
10px
;
padding
:
8px
10px
;
background-color
:
#f9f9f9
;
background-color
:
#f9f9f9
;
border-radius
:
5px
;
border-radius
:
5px
;
}
}
.textarea-box
.textarea
{
.textarea-box
.textarea
{
max-height
:
100px
;
max-height
:
100px
;
font-size
:
14px
;
font-size
:
14px
;
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
overflow
:
auto
;
overflow
:
auto
;
/* #endif */
/* #endif */
width
:
450rpx
;
width
:
450rpx
;
}
}
/* #ifdef H5 */
/* #ifdef H5 */
/*隐藏滚动条*/
/*隐藏滚动条*/
.
textarea-box
.
textarea
:
:-
webkit-scrollbar
{
.
textarea-box
.
textarea
:
:-
webkit-scrollbar
{
width
:
0
;
width
:
0
;
}
}
/* #endif */
/* #endif */
.input-placeholder
{
.input-placeholder
{
color
:
#bbb
;
color
:
#bbb
;
}
}
.trash
,
.trash
,
.send
{
.send
{
width
:
50px
;
width
:
50px
;
height
:
30px
;
height
:
30px
;
justify-content
:
center
;
justify-content
:
center
;
align-items
:
center
;
align-items
:
center
;
flex-shrink
:
0
;
flex-shrink
:
0
;
}
}
.trash
{
.trash
{
width
:
30rpx
;
width
:
30rpx
;
margin-left
:
10rpx
;
margin-left
:
10rpx
;
}
}
.send
{
.send
{
color
:
#FFF
;
color
:
#FFF
;
border-radius
:
4px
;
border-radius
:
4px
;
display
:
flex
;
display
:
flex
;
margin
:
0
;
margin
:
0
;
padding
:
0
;
padding
:
0
;
font-size
:
14px
;
font-size
:
14px
;
margin-right
:
20rpx
;
margin-right
:
20rpx
;
}
}
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
.
send
:
:
after
{
.
send
:
:
after
{
display
:
none
;
display
:
none
;
}
}
/* #endif */
/* #endif */
.msg-list
{
.msg-list
{
flex
:
1
;
flex
:
1
;
height
:
1px
;
height
:
1px
;
width
:
750rpx
;
width
:
750rpx
;
}
}
.userInfo
{
.userInfo
{
flex-direction
:
column
;
flex-direction
:
column
;
}
}
.msg-item
{
.msg-item
{
position
:
relative
;
position
:
relative
;
width
:
750rpx
;
width
:
750rpx
;
flex-direction
:
column
;
flex-direction
:
column
;
padding
:
0
15px
;
padding
:
0
15px
;
padding-bottom
:
15px
;
padding-bottom
:
15px
;
}
}
.msgStateIcon
{
.msgStateIcon
{
position
:
relative
;
position
:
relative
;
top
:
5px
;
top
:
5px
;
right
:
5px
;
right
:
5px
;
align-self
:
center
;
align-self
:
center
;
}
}
.avatar
{
.avatar
{
width
:
40px
;
width
:
40px
;
height
:
40px
;
height
:
40px
;
border-radius
:
2px
;
border-radius
:
2px
;
}
}
.create_time
{
.create_time
{
font-size
:
12px
;
font-size
:
12px
;
padding
:
5px
0
;
padding
:
5px
0
;
padding-top
:
0
;
padding-top
:
0
;
color
:
#aaa
;
color
:
#aaa
;
text-align
:
center
;
text-align
:
center
;
width
:
750rpx
;
width
:
750rpx
;
/* #ifdef MP */
/* #ifdef MP */
display
:
flex
;
display
:
flex
;
/* #endif */
/* #endif */
justify-content
:
center
;
justify-content
:
center
;
}
}
.content
{
.content
{
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
max-width
:
550rpx
;
max-width
:
550rpx
;
/* #endif */
/* #endif */
background-color
:
#FFF
;
background-color
:
#FFF
;
border-radius
:
5px
;
border-radius
:
5px
;
padding
:
12px
10px
;
padding
:
12px
10px
;
margin-left
:
10px
;
margin-left
:
10px
;
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
word-break
:
break-all
;
word-break
:
break-all
;
user-select
:
text
;
user-select
:
text
;
cursor
:
text
;
cursor
:
text
;
/* #endif */
/* #endif */
}
}
/* #ifndef APP-NVUE */
/* #ifndef APP-NVUE */
.content
{
.content
{
display
:
inline
;
display
:
inline
;
}
}
.
content
:
:
v-deep
rich-text
{
.
content
:
:
v-deep
rich-text
{
...
@@ -619,29 +619,29 @@
...
@@ -619,29 +619,29 @@
.content
*
{
.content
*
{
display
:
inline
;
display
:
inline
;
}
}
/* #endif */
/* #endif */
.reverse
{
.reverse
{
flex-direction
:
row-reverse
;
flex-direction
:
row-reverse
;
}
}
.reverse
.content
{
.reverse
.content
{
margin-left
:
0
;
margin-left
:
0
;
margin-right
:
10px
;
margin-right
:
10px
;
}
}
.reverse-align
{
.reverse-align
{
align-items
:
flex-end
;
align-items
:
flex-end
;
}
}
.noData
{
.noData
{
margin-top
:
15px
;
margin-top
:
15px
;
text-align
:
center
;
text-align
:
center
;
width
:
750rpx
;
width
:
750rpx
;
color
:
#aaa
;
color
:
#aaa
;
font-size
:
12px
;
font-size
:
12px
;
justify-content
:
center
;
justify-content
:
center
;
}
}
.tip-ai-ing
{
.tip-ai-ing
{
align-items
:
center
;
align-items
:
center
;
...
...
uniCloud-aliyun/cloudfunctions/uni-ai-chat/index.obj.js
浏览文件 @
2a5d4ce4
...
@@ -61,8 +61,8 @@ module.exports = {
...
@@ -61,8 +61,8 @@ module.exports = {
requestId
:
this
.
getUniCloudRequestId
()
requestId
:
this
.
getUniCloudRequestId
()
})
})
this
.
textSecCheck
=
async
(
content
)
=>
{
this
.
textSecCheck
=
async
(
content
)
=>
{
let
{
SSE
Channel
}
=
this
.
getParams
()[
0
]
||
{}
let
{
sse
Channel
}
=
this
.
getParams
()[
0
]
||
{}
if
(
SSE
Channel
){
if
(
sse
Channel
){
throw
"
流式响应模式,内容安全识别功能无效
"
throw
"
流式响应模式,内容安全识别功能无效
"
}
}
// 检测文本
// 检测文本
...
@@ -109,9 +109,9 @@ module.exports = {
...
@@ -109,9 +109,9 @@ module.exports = {
}
}
}
else
if
(
error
==
'
insufficientPoints
'
){
}
else
if
(
error
==
'
insufficientPoints
'
){
let
reply
=
"
积分不足,请看完激励视频广告后再试
"
let
reply
=
"
积分不足,请看完激励视频广告后再试
"
let
{
SSE
Channel
}
=
this
.
getParams
()[
0
]
||
{}
let
{
sse
Channel
}
=
this
.
getParams
()[
0
]
||
{}
if
(
SSE
Channel
){
if
(
sse
Channel
){
const
channel
=
uniCloud
.
deserializeSSEChannel
(
SSE
Channel
)
const
channel
=
uniCloud
.
deserializeSSEChannel
(
sse
Channel
)
await
channel
.
write
(
reply
)
await
channel
.
write
(
reply
)
await
channel
.
end
({
await
channel
.
end
({
"
insufficientPoints
"
:
true
"
insufficientPoints
"
:
true
...
@@ -147,7 +147,7 @@ module.exports = {
...
@@ -147,7 +147,7 @@ module.exports = {
},
},
async
send
({
async
send
({
messages
,
messages
,
SSE
Channel
sse
Channel
})
{
})
{
// 初次调试时,可不从客户端获取数据,直接使用下面写死在云函数里的数据
// 初次调试时,可不从客户端获取数据,直接使用下面写死在云函数里的数据
// messages = [{
// messages = [{
...
@@ -165,13 +165,13 @@ module.exports = {
...
@@ -165,13 +165,13 @@ module.exports = {
let
{
llm
,
chatCompletionOptions
}
=
config
let
{
llm
,
chatCompletionOptions
}
=
config
return
await
chatCompletion
({
return
await
chatCompletion
({
messages
,
//消息内容
messages
,
//消息内容
SSE
Channel
,
//sse渠道对象
sse
Channel
,
//sse渠道对象
llm
llm
})
})
async
function
chatCompletion
({
async
function
chatCompletion
({
messages
,
messages
,
summarize
=
false
,
summarize
=
false
,
SSE
Channel
=
false
,
sse
Channel
=
false
,
llm
llm
})
{
})
{
...
@@ -179,13 +179,13 @@ module.exports = {
...
@@ -179,13 +179,13 @@ module.exports = {
let
res
=
await
llmManager
.
chatCompletion
({
let
res
=
await
llmManager
.
chatCompletion
({
...
chatCompletionOptions
,
...
chatCompletionOptions
,
messages
,
messages
,
stream
:
SSE
Channel
!==
false
stream
:
sse
Channel
!==
false
})
})
if
(
SSE
Channel
)
{
if
(
sse
Channel
)
{
let
reply
=
""
let
reply
=
""
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
channel
=
uniCloud
.
deserializeSSEChannel
(
SSE
Channel
)
const
channel
=
uniCloud
.
deserializeSSEChannel
(
sse
Channel
)
res
.
on
(
'
message
'
,
async
(
message
)
=>
{
res
.
on
(
'
message
'
,
async
(
message
)
=>
{
// await channel.write(message)
// await channel.write(message)
// console.log('---message----', message)
// console.log('---message----', message)
...
@@ -256,7 +256,7 @@ module.exports = {
...
@@ -256,7 +256,7 @@ module.exports = {
messages
,
messages
,
summarize
:
true
,
summarize
:
true
,
stream
:
false
,
stream
:
false
,
SSE
Channel
:
false
sse
Channel
:
false
})
})
return
res
.
reply
return
res
.
reply
}
}
...
...
uniCloud-aliyun/database/opendb-app-client-key.schema.json
已删除
100644 → 0
浏览文件 @
fe468eca
{
"bsonType"
:
"object"
,
"required"
:
[
"_id"
,
"value"
],
"properties"
:
{
"_id"
:
{
"bsonType"
:
"string"
,
"description"
:
"自动生成的id"
},
"app_id"
:
{
"bsonType"
:
"string"
,
"description"
:
"客户端DCloud AppId"
},
"device_id"
:
{
"bsonType"
:
"string"
,
"description"
:
"客户端设备id"
},
"private_key"
:
{
"bsonType"
:
"string"
,
"description"
:
"私钥,仅保存在云端"
},
"public_key"
:
{
"bsonType"
:
"string"
,
"description"
:
"公钥,下发给客户端使用"
},
"create_date"
:
{
"bsonType"
:
"timestamp"
,
"description"
:
"创建时间"
}
},
"version"
:
"0.0.1"
}
\ No newline at end of file
uniCloud-aliyun/database/uni-ai-chat.schema.json
已删除
100644 → 0
浏览文件 @
fe468eca
//
文档教程:
https://uniapp.dcloud.net.cn/uniCloud/schema
{
"bsonType"
:
"object"
,
"required"
:
[],
"permission"
:
{
"read"
:
false
,
"create"
:
false
,
"update"
:
false
,
"delete"
:
false
},
"properties"
:
{
"_id"
:
{
"description"
:
"ID,系统自动生成"
},
"user_id"
:{
"bsonType"
:
"string"
,
"description"
:
"用户id"
},
"balance"
:{
"bsonType"
:
"int"
,
"description"
:
"剩余可对话的次数"
},
"update_time"
:{
"bsonType"
:
"timestamp"
,
"forceDefaultValue"
:{
"$env"
:
"now"
}
}
}
}
\ No newline at end of file
uniCloud-aliyun/database/uni-id-scores.schema.json
0 → 100644
浏览文件 @
2a5d4ce4
{
"bsonType"
:
"object"
,
"required"
:
[
"user_id"
,
"score"
,
"balance"
],
"properties"
:
{
"_id"
:
{
"description"
:
"ID,系统自动生成"
},
"user_id"
:
{
"bsonType"
:
"string"
,
"description"
:
"用户id,参考uni-id-users表"
},
"score"
:
{
"bsonType"
:
"int"
,
"description"
:
"本次变化的积分"
},
"type"
:
{
"bsonType"
:
"int"
,
"enum"
:
[
1
,
2
],
"description"
:
"积分类型 1:收入 2:支出"
},
"balance"
:
{
"bsonType"
:
"int"
,
"description"
:
"变化后的积分余额"
},
"comment"
:
{
"bsonType"
:
"string"
,
"description"
:
"备注,说明积分新增、消费的缘由"
,
"trim"
:
"both"
},
"create_date"
:
{
"bsonType"
:
"timestamp"
,
"description"
:
"创建时间"
,
"forceDefaultValue"
:
{
"$env"
:
"now"
}
}
},
"version"
:
"0.0.1"
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录