Skip to content

Commit 69c4aad

Browse files
committed
feat: 添加复制
1 parent 61c5d63 commit 69c4aad

File tree

11 files changed

+180
-31
lines changed

11 files changed

+180
-31
lines changed

apps/miniprogram-agent-ui/miniprogram/app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ App({
99
// env 参数决定接下来小程序发起的云开发调用(wx.cloud.xxx)会默认请求到哪个云环境的资源
1010
// 此处请填入环境 ID, 环境 ID 可打开云控制台查看
1111
// 如不填则使用默认环境(第一个创建的环境)
12-
env: "",
12+
env: "lowcode-1gm3ep4m027742a2",
1313
traceUser: true,
1414
});
1515
}

apps/miniprogram-agent-ui/miniprogram/components/agent-ui/index.js

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -376,19 +376,20 @@ Component({
376376
.reverse()
377377
.slice(0, freshNum)
378378
.map((item) => {
379-
let transformItem = {
380-
...item, record_id: item.recordId
381-
}
382-
if(item.role === "user" && item.fileInfos) {
383-
transformItem.fileList = item.fileInfos.map(item => ({
379+
let transformItem = {
380+
...item,
381+
record_id: item.recordId,
382+
};
383+
if (item.role === "user" && item.fileInfos) {
384+
transformItem.fileList = item.fileInfos.map((item) => ({
384385
parsed: true,
385386
rawFileName: item.fileName,
386387
rawType: item.type,
387388
fileId: item.cloudId,
388-
fileSize: item.bytes
389-
}))
389+
fileSize: item.bytes,
390+
}));
390391
}
391-
return transformItem
392+
return transformItem;
392393
});
393394
this.setData({
394395
chatRecords: [...freshChatRecords, ...this.data.chatRecords],
@@ -487,7 +488,7 @@ Component({
487488
});
488489
},
489490
handleUploadImg: function (sourceType) {
490-
if(!this.data.bot.searchFileEnable) {
491+
if (!this.data.bot.searchFileEnable) {
491492
wx.showModal({
492493
title: "提示",
493494
content: "请前往腾讯云开发平台启用 Agent 文件上传功能",
@@ -597,7 +598,7 @@ Component({
597598
},
598599
handleUploadMessageFile: function () {
599600
// 判断agent 配置是否打开上传文件
600-
if(!this.data.bot.searchFileEnable) {
601+
if (!this.data.bot.searchFileEnable) {
601602
wx.showModal({
602603
title: "提示",
603604
content: "请前往腾讯云开发平台启用 Agent 文件上传功能",
@@ -702,7 +703,7 @@ Component({
702703
if (!inputValue) {
703704
return;
704705
}
705-
706+
706707
const chatMode = this.data.chatMode;
707708
// console.log(inputValue,bot.botId)
708709
const userRecord = {
@@ -771,7 +772,7 @@ Component({
771772
knowledge_meta,
772773
knowledge_base,
773774
finish_reason,
774-
search_results
775+
search_results,
775776
} = dataJson;
776777
const newValue = [...this.data.chatRecords];
777778
// 取最后一条消息更新
@@ -842,12 +843,12 @@ Component({
842843
});
843844
}
844845
// 数据库,只更新一次
845-
if(type === "db" && !lastValue.db_len) {
846-
lastValue.db_len = search_results.relateTables || 0
846+
if (type === "db" && !lastValue.db_len) {
847+
lastValue.db_len = search_results.relateTables || 0;
847848
this.setData({
848849
[`chatRecords[${lastValueIndex}].db_len`]: lastValue.db_len,
849850
chatStatus: 2,
850-
})
851+
});
851852
}
852853
} catch (e) {
853854
// console.log('err', event, e)
@@ -1071,7 +1072,7 @@ Component({
10711072
});
10721073
},
10731074
handleClickWebSearch: function () {
1074-
if(!this.data.useWebSearch && !this.data.bot.searchEnable) {
1075+
if (!this.data.useWebSearch && !this.data.bot.searchEnable) {
10751076
wx.showModal({
10761077
title: "提示",
10771078
content: "请前往腾讯云开发平台启用 Agent 联网搜索功能",
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
Component({
2+
options: {
3+
virtualHost: true,
4+
},
5+
data: {
6+
},
7+
properties: {
8+
dataClipboardText: {
9+
type: String,
10+
value: '',
11+
},
12+
},
13+
methods: {
14+
// 复制到剪贴板
15+
copyClipBoard: function () {
16+
wx.setClipboardData({
17+
data: this.data.dataClipboardText,
18+
// success() {
19+
// wx.getClipboardData({
20+
// success() {},
21+
// });
22+
// },
23+
});
24+
},
25+
},
26+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"component": true,
3+
"styleIsolation": "shared",
4+
"usingComponents": {
5+
}
6+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<view class="markdown-it-code-copy" bindtap="copyClipBoard"></view>
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
@font-face {
2+
font-family: WdTd;
3+
src: url("t.eot"), url("t_iefix.eot") format("embedded-opentype"),
4+
url("t.woff") format("woff"), url("t.ttf") format("truetype"),
5+
url("t.svg") format("svg"),
6+
url("https://comp-public-replace-1303824488-cos.weda.tencent.com/icon/0.0.7/t.eot"),
7+
url("https://comp-public-replace-1303824488-cos.weda.tencent.com/icon/0.0.7/t_iefix.eot") format("embedded-opentype"),
8+
url("https://comp-public-replace-1303824488-cos.weda.tencent.com/icon/0.0.7/t.woff") format("woff"),
9+
url("https://comp-public-replace-1303824488-cos.weda.tencent.com/icon/0.0.7/t.ttf") format("truetype"),
10+
url("https://comp-public-replace-1303824488-cos.weda.tencent.com/icon/0.0.7/t.svg") format("svg");
11+
font-weight: 400;
12+
font-style: normal;
13+
}
14+
15+
/* .markdown-it-code-wrap {
16+
position: relative;
17+
} */
18+
.markdown-it-code-copy {
19+
font-family: WdTd !important;
20+
vertical-align: middle;
21+
font-size: 14px;
22+
border: none;
23+
background: transparent;
24+
position: absolute;
25+
top: 7.5px;
26+
right: 6px;
27+
cursor: pointer;
28+
outline: none;
29+
color: black;
30+
}
31+
32+
/* i.markdown-it-code-copy {
33+
font-style: normal;
34+
} */
35+
.markdown-it-code-copy::before {
36+
content: '\E1AC';
37+
position: absolute;
38+
top: 0;
39+
right: 0;
40+
cursor: pointer;
41+
width: 20px;
42+
height: 20px;
43+
display: inline-block;
44+
text-align: center;
45+
}
46+
47+
.markdown-it-code-copy:hover::before {
48+
background: #eef1f4;
49+
}

apps/miniprogram-agent-ui/miniprogram/components/agent-ui/wd-markdown/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import MarkdownIt from './utils/markdown-it.min.js';
22
import highlight from './utils/highlight.min.js';
33
import hljsJs from './utils/hljs_javascript.min.js';
44
import hljsCss from './utils/hljs_css.min.js';
5-
import { addCustomClassPlugin } from './utils/plugin'
5+
import { addCustomClassPlugin,copy } from './utils/plugin'
66
Component({
77
options: {
88
virtualHost: true,
@@ -63,6 +63,7 @@ Component({
6363
...options,
6464
});
6565
// console.log(md.renderer.rules)
66+
md.use(copy);
6667
addCustomClassPlugin(md)
6768
this.setData({ mdInstance: md });
6869
this.triggerEvent('onReady', { markdownInstance: md });
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"component":true,"usingComponents":{"node":"./node"}}
1+
{"component":true,"usingComponents":{"node":"./node","copy":"../../copy/index"}}
Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,43 @@
1-
<wxs module="isInline">var e={abbr:!0,b:!0,big:!0,code:!0,del:!0,em:!0,i:!0,ins:!0,label:!0,q:!0,small:!0,span:!0,strong:!0,sub:!0,sup:!0};module.exports=function(n,i){return e[n]||-1!==(i||"").indexOf("inline")};</wxs><template name="el"><block wx:if="{{n.name==='img'}}"><rich-text wx:if="{{n.t}}" style="display:{{n.t}}" nodes="<img class='_img' style='{{n.attrs.style}}' src='{{n.attrs.src}}'>" data-i="{{i}}" catchtap="imgTap"/><block wx:else><image wx:if="{{(opts[1]&&!ctrl[i])||ctrl[i]<0}}" class="_img" style="{{n.attrs.style}}" src="{{ctrl[i]<0?opts[2]:opts[1]}}" mode="widthFix"/><image id="{{n.attrs.id}}" class="_img {{n.attrs.class}}" style="{{ctrl[i]===-1?'display:none;':''}}width:{{ctrl[i]||1}}px;height:1px;{{n.attrs.style}}" src="{{n.attrs.src}}" mode="{{!n.h?'widthFix':(!n.w?'heightFix':(n.m||'scaleToFill'))}}" lazy-load="{{opts[0]}}" webp="{{n.webp}}" show-menu-by-longpress="{{opts[3]&&!n.attrs.ignore}}" data-i="{{i}}" bindload="imgLoad" binderror="mediaError" catchtap="imgTap" bindlongpress="noop"/></block></block><text wx:elif="{{n.text}}" user-select="{{opts[4]=='force'&&isiOS}}" decode>{{n.text}}</text><text wx:elif="{{n.name==='br'}}">{{'\n'}}</text><view wx:elif="{{n.name==='a'}}" id="{{n.attrs.id}}" class="{{n.attrs.href?'_a ':''}}{{n.attrs.class}}" hover-class="_hover" style="display:inline;{{n.attrs.style}}" data-i="{{i}}" catchtap="linkTap"><node childs="{{n.children}}" opts="{{opts}}" style="display:inherit"/></view><video wx:elif="{{n.name==='video'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" autoplay="{{n.attrs.autoplay}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" muted="{{n.attrs.muted}}" object-fit="{{n.attrs['object-fit']}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError"/><audio wx:elif="{{n.name==='audio'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" author="{{n.attrs.author}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" name="{{n.attrs.name}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError"/><rich-text wx:else id="{{n.attrs.id}}" style="{{n.f}}" user-select="{{opts[4]}}" nodes="{{[n]}}"/></template><block wx:for="{{childs}}" wx:for-item="n1" wx:for-index="i1" wx:key="i1"><template wx:if="{{!n1.c&&(!n1.children||n1.name==='a'||!isInline(n1.name,n1.attrs.style))}}" is="el" data="{{n:n1,i:''+i1,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n1.attrs.id}}" class="_{{n1.name}} {{n1.attrs.class}}" style="{{n1.attrs.style}}"><block wx:for="{{n1.children}}" wx:for-item="n2" wx:for-index="i2" wx:key="i2"><template wx:if="{{!n2.c&&(!n2.children||n2.name==='a'||!isInline(n2.name,n2.attrs.style))}}" is="el" data="{{n:n2,i:i1+'_'+i2,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n2.attrs.id}}" class="_{{n2.name}} {{n2.attrs.class}}" style="{{n2.attrs.style}}"><block wx:for="{{n2.children}}" wx:for-item="n3" wx:for-index="i3" wx:key="i3"><template wx:if="{{!n3.c&&(!n3.children||n3.name==='a'||!isInline(n3.name,n3.attrs.style))}}" is="el" data="{{n:n3,i:i1+'_'+i2+'_'+i3,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n3.attrs.id}}" class="_{{n3.name}} {{n3.attrs.class}}" style="{{n3.attrs.style}}"><block wx:for="{{n3.children}}" wx:for-item="n4" wx:for-index="i4" wx:key="i4"><template wx:if="{{!n4.c&&(!n4.children||n4.name==='a'||!isInline(n4.name,n4.attrs.style))}}" is="el" data="{{n:n4,i:i1+'_'+i2+'_'+i3+'_'+i4,opts:opts,ctrl:ctrl}}"/><view wx:else id="{{n4.attrs.id}}" class="_{{n4.name}} {{n4.attrs.class}}" style="{{n4.attrs.style}}"><block wx:for="{{n4.children}}" wx:for-item="n5" wx:for-index="i5" wx:key="i5"><template wx:if="{{!n5.c&&(!n5.children||n5.name==='a'||!isInline(n5.name,n5.attrs.style))}}" is="el" data="{{n:n5,i:i1+'_'+i2+'_'+i3+'_'+i4+'_'+i5,opts:opts,ctrl:ctrl}}"/><node wx:else id="{{n5.attrs.id}}" class="_{{n5.name}} {{n5.attrs.class}}" style="{{n5.attrs.style}}" childs="{{n5.children}}" opts="{{opts}}"/></block></view></block></view></block></view></block></view></block>
1+
<wxs module="isInline">
2+
var e = { abbr: !0, b: !0, big: !0, code: !0, del: !0, em: !0, i: !0, ins: !0, label: !0, q: !0, small: !0, span: !0, strong: !0, sub: !0, sup: !0 }; module.exports = function (n, i) { return e[n] || -1 !== (i || "").indexOf("inline") };
3+
</wxs>
4+
<template name="el">
5+
<block wx:if="{{n.name==='img'}}">
6+
<rich-text wx:if="{{n.t}}" style="display:{{n.t}}" nodes="<img class='_img' style='{{n.attrs.style}}' src='{{n.attrs.src}}'>" data-i="{{i}}" catchtap="imgTap" />
7+
<block wx:else>
8+
<image wx:if="{{(opts[1]&&!ctrl[i])||ctrl[i]<0}}" class="_img" style="{{n.attrs.style}}" src="{{ctrl[i]<0?opts[2]:opts[1]}}" mode="widthFix" />
9+
<image id="{{n.attrs.id}}" class="_img {{n.attrs.class}}" style="{{ctrl[i]===-1?'display:none;':''}}width:{{ctrl[i]||1}}px;height:1px;{{n.attrs.style}}" src="{{n.attrs.src}}" mode="{{!n.h?'widthFix':(!n.w?'heightFix':(n.m||'scaleToFill'))}}" lazy-load="{{opts[0]}}" webp="{{n.webp}}" show-menu-by-longpress="{{opts[3]&&!n.attrs.ignore}}" data-i="{{i}}" bindload="imgLoad" binderror="mediaError" catchtap="imgTap" bindlongpress="noop" />
10+
</block>
11+
</block>
12+
<text wx:elif="{{n.text}}" user-select="{{opts[4]=='force'&&isiOS}}" decode>{{n.text}}</text><text wx:elif="{{n.name==='br'}}">{{'\n'}}</text>
13+
<view wx:elif="{{n.name==='a'}}" id="{{n.attrs.id}}" class="{{n.attrs.href?'_a ':''}}{{n.attrs.class}}" hover-class="_hover" style="display:inline;{{n.attrs.style}}" data-i="{{i}}" catchtap="linkTap">
14+
<block wx:if="{{n.attrs.class==='__preCodeCopyWrap'}}">
15+
<copy dataClipboardText="{{n.attrs.href}}"></copy>
16+
</block>
17+
<block wx:else>
18+
<node childs="{{n.children}}" opts="{{opts}}" style="display:inherit" />
19+
</block>
20+
</view>
21+
<video wx:elif="{{n.name==='video'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" autoplay="{{n.attrs.autoplay}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" muted="{{n.attrs.muted}}" object-fit="{{n.attrs['object-fit']}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError" />
22+
<audio wx:elif="{{n.name==='audio'}}" id="{{n.attrs.id}}" class="{{n.attrs.class}}" style="{{n.attrs.style}}" author="{{n.attrs.author}}" controls="{{n.attrs.controls}}" loop="{{n.attrs.loop}}" name="{{n.attrs.name}}" poster="{{n.attrs.poster}}" src="{{n.src[ctrl[i]||0]}}" data-i="{{i}}" bindplay="play" binderror="mediaError" />
23+
<rich-text wx:else id="{{n.attrs.id}}" style="{{n.f}}" user-select="{{opts[4]}}" nodes="{{[n]}}" />
24+
</template>
25+
<block wx:for="{{childs}}" wx:for-item="n1" wx:for-index="i1" wx:key="i1"><template wx:if="{{!n1.c&&(!n1.children||n1.name==='a'||!isInline(n1.name,n1.attrs.style))}}" is="el" data="{{n:n1,i:''+i1,opts:opts,ctrl:ctrl}}" />
26+
<view wx:else id="{{n1.attrs.id}}" class="_{{n1.name}} {{n1.attrs.class}}" style="{{n1.attrs.style}}">
27+
<block wx:for="{{n1.children}}" wx:for-item="n2" wx:for-index="i2" wx:key="i2"><template wx:if="{{!n2.c&&(!n2.children||n2.name==='a'||!isInline(n2.name,n2.attrs.style))}}" is="el" data="{{n:n2,i:i1+'_'+i2,opts:opts,ctrl:ctrl}}" />
28+
<view wx:else id="{{n2.attrs.id}}" class="_{{n2.name}} {{n2.attrs.class}}" style="{{n2.attrs.style}}">
29+
<block wx:for="{{n2.children}}" wx:for-item="n3" wx:for-index="i3" wx:key="i3"><template wx:if="{{!n3.c&&(!n3.children||n3.name==='a'||!isInline(n3.name,n3.attrs.style))}}" is="el" data="{{n:n3,i:i1+'_'+i2+'_'+i3,opts:opts,ctrl:ctrl}}" />
30+
<view wx:else id="{{n3.attrs.id}}" class="_{{n3.name}} {{n3.attrs.class}}" style="{{n3.attrs.style}}">
31+
<block wx:for="{{n3.children}}" wx:for-item="n4" wx:for-index="i4" wx:key="i4"><template wx:if="{{!n4.c&&(!n4.children||n4.name==='a'||!isInline(n4.name,n4.attrs.style))}}" is="el" data="{{n:n4,i:i1+'_'+i2+'_'+i3+'_'+i4,opts:opts,ctrl:ctrl}}" />
32+
<view wx:else id="{{n4.attrs.id}}" class="_{{n4.name}} {{n4.attrs.class}}" style="{{n4.attrs.style}}">
33+
<block wx:for="{{n4.children}}" wx:for-item="n5" wx:for-index="i5" wx:key="i5"><template wx:if="{{!n5.c&&(!n5.children||n5.name==='a'||!isInline(n5.name,n5.attrs.style))}}" is="el" data="{{n:n5,i:i1+'_'+i2+'_'+i3+'_'+i4+'_'+i5,opts:opts,ctrl:ctrl}}" />
34+
<node wx:else id="{{n5.attrs.id}}" class="_{{n5.name}} {{n5.attrs.class}}" style="{{n5.attrs.style}}" childs="{{n5.children}}" opts="{{opts}}" />
35+
</block>
36+
</view>
37+
</block>
38+
</view>
39+
</block>
40+
</view>
41+
</block>
42+
</view>
43+
</block>

apps/miniprogram-agent-ui/miniprogram/components/agent-ui/wd-markdown/utils/plugin.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,26 @@ export function addCustomClassPlugin(md) {
3030
};
3131
});
3232
}
33+
function renderCode(origRule) {
34+
return (...args) => {
35+
const [tokens, idx] = args;
36+
const content = tokens[idx].content
37+
.replaceAll('"', '&quot;')
38+
.replaceAll("'", "&apos;");
39+
const origRendered = origRule(...args);
40+
41+
if (content.length === 0)
42+
return origRendered;
43+
44+
return `
45+
<div style="position: relative" >
46+
${origRendered}
47+
<a class="__preCodeCopyWrap" href="${content}"></a>
48+
</div>
49+
`;
50+
};
51+
}
52+
export const copy = (md) => {
53+
md.renderer.rules.code_block = renderCode(md.renderer.rules.code_block);
54+
md.renderer.rules.fence = renderCode(md.renderer.rules.fence);
55+
};

0 commit comments

Comments
 (0)