feat: 增加模式选择

share-code
xjs 2026-05-28 11:45:48 +08:00
parent 14bd6d0ea8
commit a4249f95c3
99 changed files with 5705 additions and 66 deletions

View File

@ -8,6 +8,10 @@ export default defineUniPages({
navigationBarBackgroundColor: '#FFFFFF',
navigationBarTextStyle: 'black',
backgroundColor: '#FFFFFF',
// 全局注册 markdown 渲染组件,自定义聊天 UI 使用
usingComponents: {
'markdown-preview': '/wxcomponents/agent-ui/wd-markdown/index',
},
},
easycom: {
autoscan: true,
@ -23,7 +27,7 @@ export default defineUniPages({
preloadRule: {
'pages/index/index': {
network: 'all',
packages: ['chart-sub'],
packages: ['chart-sub', 'pages-ai'],
},
},
})

View File

@ -18,17 +18,13 @@ definePage({
})
const agentConfig = reactive<AgentConfig>({ ...defaultAgentConfig })
// model 使 bot
const _modelConfig = reactive<ModelConfig>({ ...defaultModelConfig })
const modelConfig = reactive<ModelConfig>({ ...defaultModelConfig })
const aiStore = useAiStore()
const paging = ref<any>(null)
const messages = ref<AiMessage[]>([])
const loading = ref(false)
/** 当前轮回复结束后由 getRecommendQuestions 返回的追问建议 */
const recommendQuestions = ref<string[]>([])
// controller cancelled
let cancelFlag = false
@ -44,6 +40,15 @@ onLoad(() => {
// #endif
aiStore.ensureThreadId()
wx.cloud.extend.AI.bot.getRecommendQuestions({
data: {
botId: 'agent-wxai-4gl75um61026324f',
msg: '你是谁',
},
}).then((resp) => {
console.log(resp)
})
})
// z-paging store
@ -66,8 +71,6 @@ async function handleSend(text: string) {
}
cancelFlag = false
loading.value = true
//
recommendQuestions.value = []
const userMsg: AiMessage = {
id: generateMessageId(),
@ -84,19 +87,21 @@ async function handleSend(text: string) {
createdAt: Date.now() + 1,
}
// store z-paging
// queryList user ai
// z-paging addChatRecordData +
// totalData = [aiMsg, userMsg, ...] 0 = = aiMsg
// userMsg aiMsg " AI "
// store z-paging addChatRecordData +
// totalData = [aiMsg, userMsg, ...] 0 = " AI "
aiStore.addMessage(userMsg)
aiStore.addMessage(aiMsg)
paging.value?.addChatRecordData([userMsg, aiMsg])
try {
await streamMessage({
chatMode: agentConfig.chatMode,
// bot
botId: agentConfig.botId,
threadId: aiStore.ensureThreadId(),
// model
modelProvider: modelConfig.modelProvider,
quickResponseModel: modelConfig.quickResponseModel,
// aiMsg
history: aiStore.messages.slice(0, -1),
prompt: text,
@ -117,10 +122,11 @@ async function handleSend(text: string) {
aiStore.updateMessage(aiMsg.id, { pending: false })
//
if (!cancelFlag) {
void loadRecommendQuestions(text)
}
// V2 agent getRecommendQuestions 404
// bot-xxx agent
// if (!cancelFlag) {
// void loadRecommendQuestions(aiMsg.id, text)
// }
}
catch (err) {
aiStore.updateMessage(aiMsg.id, {
@ -150,23 +156,20 @@ function handleRetry(id: string) {
if (failedIdx <= 0) {
return
}
// ai
const userMsg = aiStore.messages[failedIdx - 1]
if (!userMsg || userMsg.role !== 'user') {
return
}
//
aiStore.removeMessage(id)
handleSend(userMsg.content)
}
function handleClickQuestion(question: string) {
recommendQuestions.value = []
handleSend(question)
}
async function loadRecommendQuestions(prompt: string) {
// user / assistant
/** 请求追问建议,结果挂到对应 AI 消息的 recommendQuestions */
async function loadRecommendQuestions(aiMsgId: string, prompt: string) {
const last = aiStore.messages.slice(-2).map(m => ({
role: m.role === 'user' ? ('user' as const) : ('assistant' as const),
content: m.content,
@ -178,27 +181,25 @@ async function loadRecommendQuestions(prompt: string) {
prompt,
max: 3,
onProgress: (qs) => {
recommendQuestions.value = qs
aiStore.updateMessage(aiMsgId, { recommendQuestions: qs })
},
})
recommendQuestions.value = questions
aiStore.updateMessage(aiMsgId, { recommendQuestions: questions })
}
catch (error) {
console.error('[recommend]', error)
recommendQuestions.value = []
}
}
function handleClear() {
aiStore.clear()
recommendQuestions.value = []
paging.value?.reload()
}
</script>
<template>
<view class="h-screen w-full flex flex-col bg-[#F4F6FA]">
<!-- 顶部清空按钮 -->
<!-- 顶部 -->
<view class="flex items-center justify-between bg-white px-[24rpx] py-[20rpx] shadow-[0_2rpx_8rpx_rgba(0,0,0,0.03)]">
<view class="text-[30rpx] text-[#1F2329] font-500">
{{ agentConfig.botName }}
@ -227,7 +228,7 @@ function handleClear() {
:paging-style="{ backgroundColor: '#F4F6FA' }"
@query="queryList"
>
<!-- 推荐问题 -->
<!-- 首屏推荐问题 -->
<template v-if="messages.length <= 1 && agentConfig.initQuestions.length" #top>
<view class="flex flex-col gap-[16rpx] px-[24rpx] py-[20rpx]">
<view class="text-[24rpx] text-[#999] leading-[1.4]">
@ -245,6 +246,7 @@ function handleClear() {
</view>
</view>
</template>
<template #default>
<agent-message
v-for="item in messages"
@ -252,28 +254,11 @@ function handleClear() {
:message="item"
:bot-name="agentConfig.botName"
@retry="handleRetry"
@pick-recommend="handleClickQuestion"
/>
</template>
<template #bottom>
<!-- 一轮对话结束后的追问建议 -->
<view
v-if="recommendQuestions.length"
class="flex flex-wrap gap-[12rpx] bg-[#F4F6FA] px-[24rpx] pb-[16rpx] pt-[8rpx]"
>
<view class="w-full text-[24rpx] text-[#999] leading-[1.4]">
你可能还想问
</view>
<view
v-for="q in recommendQuestions"
:key="q"
class="border-1 border-[#1580FF] rounded-[24rpx] border-solid bg-white px-[20rpx] py-[10rpx] text-[24rpx] text-[#1580FF] active:opacity-60"
@click="handleClickQuestion(q)"
>
{{ q }}
</view>
</view>
<agent-input
:placeholder="agentConfig.placeholder"
:loading="loading"

View File

@ -8,6 +8,7 @@ const props = defineProps<{
defineEmits<{
(event: 'retry', id: string): void
(event: 'pickRecommend', question: string): void
}>()
</script>
@ -62,6 +63,21 @@ defineEmits<{
>
生成失败点击重试
</view>
<!-- 追问建议 AI 消息且生成结束后展示 -->
<view
v-if="props.message.role === 'assistant' && !props.message.pending && props.message.recommendQuestions && props.message.recommendQuestions.length"
class="mt-[8rpx] flex flex-col gap-[12rpx]"
>
<view
v-for="q in props.message.recommendQuestions"
:key="q"
class="self-start border-1 border-[#1580FF] rounded-[24rpx] border-solid bg-white px-[20rpx] py-[10rpx] text-[24rpx] text-[#1580FF] active:opacity-60"
@click="$emit('pickRecommend', q)"
>
{{ q }}
</view>
</view>
</view>
<!-- 用户头像 -->

View File

@ -1,9 +1,14 @@
// AI Agent 相关运行时配置(页面、组件共享)
/** 组件对接的 AI 类型 */
export type ChatMode = 'bot' | 'model'
export interface AgentConfig {
/** 必填:组件对接的 AI 类型;'bot' 走 agent 能力,'model' 走大模型能力 */
chatMode: ChatMode
/** 微信云开发环境 ID用于 wx.cloud.init */
cloudEnvId: string
/** Agent ID对应 wx.cloud.extend.AI.bot.sendMessage 的 botId */
/** Agent ID对应 wx.cloud.extend.AI.bot.sendMessage 的 botIdchatMode=bot 必填) */
botId: string
/** 首屏欢迎语 */
welcomeMsg: string
@ -25,6 +30,7 @@ export interface ModelConfig {
}
export const defaultAgentConfig: AgentConfig = {
chatMode: 'bot',
cloudEnvId: 'cloud1-d3g5q6bq61a240786',
botId: 'agent-wxai-4gl75um61026324f',
welcomeMsg: '你好,我是 AI 助手,有什么可以帮你?',

View File

@ -1,6 +1,8 @@
// 与 wx.cloud.extend.AI.bot 通讯的服务层
// 把流式接收逻辑收敛到一个 streamMessage 函数UI 只负责消费 onDelta
// 与 wx.cloud.extend.AI 通讯的服务层
// 根据 chatMode 自动分流:'bot' 走 ai.bot.sendMessage'model' 走 ai.createModel().streamText
// UI 层只关心 onDelta 增量与最终错误,不感知具体走哪条链路
import type { ChatMode } from './agent-config'
import type { AiMessage } from '@/store/ai'
import { generateMessageId } from './agent-config'
@ -11,10 +13,22 @@ interface BotEventData {
[key: string]: unknown
}
interface ModelEventData {
id?: string
choices?: {
delta?: {
content?: string
reasoning_content?: string
role?: string
}
finish_reason?: string
}[]
}
export interface SendMessageOptions {
botId: string
threadId: string
/** 历史消息(最近若干轮),按 wx.cloud.extend.AI.bot 协议传 */
/** 'bot' | 'model' */
chatMode: ChatMode
/** 历史消息(最近若干轮) */
history: AiMessage[]
/** 当前用户输入 */
prompt: string
@ -22,21 +36,38 @@ export interface SendMessageOptions {
onDelta: (delta: string) => void
/** 错误回调,会拿到服务端返回的 message 字段 */
onError?: (message: string) => void
/** chatMode = 'bot' 时必传 */
botId?: string
/** chatMode = 'bot' 时必传 */
threadId?: string
/** chatMode = 'model' 时必传 */
modelProvider?: string
/** chatMode = 'model' 时必传 */
quickResponseModel?: string
}
export async function streamMessage(options: SendMessageOptions): Promise<string> {
if (options.chatMode === 'model') {
return streamModel(options)
}
return streamBot(options)
}
// ---------- bot 模式wx.cloud.extend.AI.bot.sendMessage ----------
async function streamBot(options: SendMessageOptions): Promise<string> {
const { botId, threadId, history, prompt, onDelta, onError } = options
// wx.cloud.extend.AI.bot 协议要求传入完整 messages 列表
// 这里把 store 里的历史拼到一起,最后追加当前用户消息
if (!botId || !threadId) {
throw new Error('chatMode=bot 时必须提供 botId 与 threadId')
}
const messages = [
...history
.filter(m => !m.error && (m.role === 'user' || m.role === 'assistant'))
.map(m => ({
id: m.id,
role: m.role,
content: m.content,
})),
.map(m => ({ id: m.id, role: m.role, content: m.content })),
{
id: generateMessageId(),
role: 'user',
@ -82,7 +113,6 @@ export async function streamMessage(options: SendMessageOptions): Promise<string
break
}
}
return response
// #endif
@ -91,6 +121,68 @@ export async function streamMessage(options: SendMessageOptions): Promise<string
// #endif
}
// ---------- model 模式wx.cloud.extend.AI.createModel().streamText ----------
async function streamModel(options: SendMessageOptions): Promise<string> {
const { modelProvider, quickResponseModel, history, prompt, onDelta, onError } = options
if (!modelProvider || !quickResponseModel) {
throw new Error('chatMode=model 时必须提供 modelProvider 与 quickResponseModel')
}
const messages = [
...history
.filter(m => !m.error && (m.role === 'user' || m.role === 'assistant'))
.map(m => ({ role: m.role, content: m.content })),
{ role: 'user', content: prompt },
]
// #ifdef MP-WEIXIN
const ai = wx.cloud.extend.AI
const aiModel = ai.createModel(modelProvider)
const res = await aiModel.streamText({
data: {
model: quickResponseModel,
messages,
},
})
let response = ''
try {
for await (const event of res.eventStream) {
let data: ModelEventData
try {
data = JSON.parse(event.data) as ModelEventData
}
catch {
continue
}
const choice = data.choices?.[0]
if (choice?.finish_reason === 'stop') {
break
}
const content = choice?.delta?.content
if (content) {
response += content
onDelta(content)
}
}
return response
}
catch (err) {
const message = err instanceof Error ? err.message : '请求出错,请稍后再试'
onError?.(message)
throw err
}
// #endif
// #ifndef MP-WEIXIN
throw new Error('AI 助手仅在微信小程序内可用')
// #endif
}
// ---------- 追问建议(仅 bot 模式且后端支持时使用) ----------
interface RecommendOptions {
botId: string
/** 最近一对 user/assistant 消息,用于上下文 */
@ -104,8 +196,8 @@ interface RecommendOptions {
}
/**
* getRecommendQuestions
* agent "智能体追问"
* wx.cloud.extend.AI.bot.getRecommendQuestions
* bot-xxx agent-xxx 404
*/
export async function fetchRecommendQuestions(options: RecommendOptions): Promise<string[]> {
const { botId, lastPair, prompt, max = 3, onProgress } = options
@ -115,10 +207,7 @@ export async function fetchRecommendQuestions(options: RecommendOptions): Promis
const res = await wx.cloud.extend.AI.bot.getRecommendQuestions({
data: {
botId,
history: lastPair.map(item => ({
role: item.role,
content: item.content,
})),
history: lastPair.map(item => ({ role: item.role, content: item.content })),
msg: prompt,
agentSetting: '',
introduction: '',

View File

@ -11,6 +11,8 @@ export interface AiMessage {
pending?: boolean
/** 标记本条消息是否出错UI 显示重试按钮 */
error?: boolean
/** 仅 assistant 消息使用:本轮回答结束后由大模型给出的追问建议 */
recommendQuestions?: string[]
createdAt: number
}

View File

@ -0,0 +1,231 @@
// components/agent-ui-new/chatFIle/chatFile.js
import { getCloudInstance, compareVersions, commonRequest } from "../tools";
Component({
lifetimes: {
attached: async function () {
console.log("enableDel", this.data.enableDel);
const { tempFileName, rawFileName, rawType, tempPath, fileId, botId, status } = this.data.fileData;
const type = this.getFileType(rawFileName || tempFileName);
console.log("type", type);
if (!fileId) {
this.setData({
iconPath: "../imgs/" + type + ".svg",
});
this.triggerEvent("changeChild", { tempId: this.data.fileData.tempId, status: "uploading" });
}
if (fileId && status === "parsed") {
this.setData({
iconPath: "../imgs/" + type + ".svg",
});
return;
}
const cloudInstance = await getCloudInstance();
// console.log('file', cloudInstance)
// 上传云存储获取 fileId
// console.log('rawFileName tempFileName tempPath', rawFileName, tempFileName, tempPath)
cloudInstance.uploadFile({
cloudPath: this.generateCosUploadPath(
botId,
rawFileName ? rawFileName.split(".")[0] + "-" + tempFileName : tempFileName
), // 云上文件路径
filePath: tempPath,
success: async (res) => {
const appBaseInfo = wx.getAppBaseInfo();
const fileId = res.fileID;
console.log("当前版本", appBaseInfo.SDKVersion);
if (botId.startsWith("ibot")) {
this.triggerEvent("changeChild", { tempId: this.data.fileData.tempId, fileId, status: "parsed" });
} else {
this.triggerEvent("changeChild", { tempId: this.data.fileData.tempId, status: "parsing" });
commonRequest({
path: `bots/${botId}/files`,
data: {
fileList: [
{
fileName: rawFileName || tempFileName,
fileId,
type: rawType,
},
],
}, // any
method: "POST",
timeout: 60000,
success: (res) => {
console.log("resolve agent file res", res);
this.triggerEvent("changeChild", { tempId: this.data.fileData.tempId, fileId, status: "parsed" });
},
fail: (e) => {
console.log("e", e);
this.triggerEvent("changeChild", { tempId: this.data.fileData.tempId, fileId, status: "parseFailed" });
},
complete: () => {},
header: {},
});
}
},
fail: (err) => {
console.error("上传失败:", err);
},
});
},
},
observers: {
"fileData.status": function (status) {
this.setData({
statusTxt: this.getFormatStatusText(status),
});
},
},
/**
* 组件的属性列表
*/
properties: {
enableDel: {
type: Boolean,
value: false,
},
fileData: {
type: Object,
value: {
tempId: "",
rawType: "",
tempFileName: "",
rawFileName: "",
tempPath: "",
fileSize: 0,
fileUrl: "",
fileId: "",
status: "",
},
},
},
/**
* 组件的初始数据
*/
data: {
formatSize: "",
iconPath: "../imgs/file.svg",
statusTextMap: {
uploading: "上传中",
parsing: "解析中",
parseFailed: "解析失败",
},
statusTxt: "",
},
/**
* 组件的方法列表
*/
methods: {
getFormatStatusText: function (status) {
if (status === "parsed") {
return this.transformSize(this.data.fileData.fileSize);
}
return this.data.statusTextMap[status] || "";
},
generateCosUploadPath: function (botId, fileName) {
return `agent_file/${botId}/${fileName}`;
},
// 提取文件后缀
getFileType: function (fileName) {
let index = fileName.lastIndexOf(".");
const fileExt = fileName.substring(index + 1);
if (fileExt === "docx" || fileExt === "doc") {
return "word";
}
if (fileExt === "xlsx" || fileExt === "xls" || fileExt === "csv") {
return "excel";
}
if (fileExt === "png" || fileExt === "jpg" || fileExt === "jpeg" || fileExt === "svg") {
return "image";
}
if (fileExt === "ppt" || fileExt === "pptx") {
return "ppt";
}
if (fileExt === "pdf") {
return "pdf";
}
return "file";
},
// 转换文件大小原始单位为B
transformSize: function (size) {
if (size < 1024) {
return size + "B";
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + "KB";
} else {
return (size / 1024 / 1024).toFixed(2) + "MB";
}
},
removeFileFromParents: function () {
console.log("remove", this.data.fileData);
this.triggerEvent("removeChild", { tempId: this.data.fileData.tempId });
},
openFileByWx: function (tempPath) {
const fileExt = tempPath.split(".")[1];
if (["doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf"].includes(fileExt)) {
wx.openDocument({
filePath: tempPath,
success: function (res) {
console.log("打开文档成功");
},
fail: function (err) {
console.log("打开文档失败", err);
},
});
} else {
wx.showModal({
content: "当前支持预览文件类型为 pdf、doc、docx、ppt、pptx、xls、xlsx",
showCancel: false,
confirmText: "确定",
});
}
},
previewImageByWx: function (fileId) {
wx.previewImage({
urls: [fileId],
showmenu: true,
success: function (res) {
console.log("previewImage res", res);
},
fail: function (e) {
console.log("previewImage e", e);
},
});
},
openFile: async function () {
if (this.data.fileData.tempPath) {
// 本地上传的文件
if (this.data.fileData.rawType === "file") {
this.openFileByWx(this.data.fileData.tempPath);
} else {
console.log("fileId", this.data.fileData.fileId);
if (this.data.fileData.fileId) {
this.previewImageByWx(this.data.fileData.fileId);
}
}
} else if (this.data.fileData.fileId) {
// 针对历史记录中带cloudID的处理历史记录中附带的文件
const cloudInsatnce = await getCloudInstance();
cloudInsatnce.downloadFile({
fileID: this.data.fileData.fileId,
success: (res) => {
console.log("download res", res);
if (this.data.fileData.rawType === "file") {
this.openFileByWx(res.tempFilePath);
} else {
this.previewImageByWx(this.data.fileData.fileId);
}
},
fail: (err) => {
console.log("download err", err);
},
});
}
},
},
});

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1,14 @@
<!--components/agent-ui-new/chatFIle/chatFile.wxml-->
<!-- <text>components/agent-ui-new/chatFIle/chatFile.wxml</text> -->
<view class="chat_file" bind:tap="openFile">
<view class="chat_file__content">
<image class="chat_file__icon" src="{{iconPath}}" />
<view class="chat_file__info">
<view class="chat_file__name">{{fileData.rawFileName || fileData.tempFileName}}</view>
<view class="chat_file__size">{{statusTxt}}
<image wx:if="{{fileData.status === 'uploading' || fileData.status === 'parsing'}}" style="width: 15px;height:15px;margin-left: 5px" src="../imgs/loading.svg" mode=""/>
</view>
</view>
</view>
<image wx:if="{{enableDel}}" bind:tap="removeFileFromParents" style="width: 15px;height: 15px;position: absolute;top: -7px;right: -7px" src="../imgs/close-filled.png" mode="aspectFill"/>
</view>

View File

@ -0,0 +1,49 @@
/* components/agent-ui-new/chatFIle/chatFile.wxss */
.chat_file {
padding: 16rpx 24rpx;
background: #ffffff;
border-radius: 12rpx;
/* box-shadow: 0 1px 8px rgba(0, 0, 0, 0.253); */
/* margin: 0rpx 5rpx; */
/* max-width: 110px; */
width: 110px;
position: relative;
background-color: #f3f4f6;
}
.chat_file:active {
background: #f9f9f9;
}
.chat_file__content {
display: flex;
align-items: center;
gap: 24rpx;
}
.chat_file__icon {
width: 60rpx;
height: 60rpx;
flex-shrink: 0;
}
.chat_file__info {
flex: 1;
min-width: 0;
}
.chat_file__name {
font-size: 28rpx;
color: #333333;
margin-bottom: 8rpx;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.chat_file__size {
font-size: 24rpx;
color: #999999;
display: flex;
align-items: center;
}

View File

@ -0,0 +1,44 @@
// components/agent-ui/collapsibleCard/index.js
Component({
/**
* 组件的属性列表
*/
properties: {
initStatus: {
type: Boolean,
value: false
},
showBgColor:{
type: Boolean,
value: false
},
showExpandIcon: {
type: Boolean,
value: true
}
},
/**
* 组件的初始数据
*/
data: {
collapsedStatus: false
},
lifetimes: {
attached() {
this.setData({ collapsedStatus: this.properties.initStatus })
}
},
/**
* 组件的方法列表
*/
methods: {
changeCollapsedStatus: function () {
this.setData({ collapsedStatus: !this.data.collapsedStatus })
}
},
options: {
multipleSlots: true
}
})

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1,10 @@
<!--components/agent-ui/collapsibleCard/index.wxml-->
<view class="collapse" style="{{collapsedStatus&&showBgColor?'background-color: #f5f5f5;':''}}">
<view class="collapse-header" bind:tap="changeCollapsedStatus">
<image wx:if="{{showExpandIcon}}" src="../imgs/arrow.svg" mode="aspectFill" style="width: 16px;height: 16px;transform: rotate({{collapsedStatus?360:270}}deg);" />
<slot name="title"></slot>
</view>
<block wx:if="{{collapsedStatus}}">
<slot name="content"></slot>
</block>
</view>

View File

@ -0,0 +1,14 @@
/* components/agent-ui/collapsibleCard/index.wxss */
.collapse{
border-radius: 8px;
margin-bottom: 12px;
}
.collapse-header {
display: inline-flex;
align-items: center;
gap: 8px;
background-color: #f5f5f5;
justify-content: space-between;
padding: 18rpx 26rpx;
border-radius: 8px;
}

View File

@ -0,0 +1,18 @@
Component({
properties: {
name: {
type: String,
value: "",
},
toolParams: {
type: Object,
value: {},
},
toolData: {
type: Object,
value: {},
},
},
data: {},
lifetimes: {},
});

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1,27 @@
<!--components/agent-ui-new/chatFIle/chatFile.wxml-->
<!-- <text>components/agent-ui-new/chatFIle/chatFile.wxml</text> -->
<!-- <block>
<view wx:if="{{name === 'maps_geo' || name === 'maps_direction_driving'}}">
<custom-map name="{{name}}" toolData="{{toolData}}"></custom-map>
</view>
<view wx:if="{{name === 'maps_weather'}}">
<custom-weather name="{{name}}" toolData="{{toolData}}"></custom-weather>
</view>
<view wx:if="{{name === 'map_search_places'}}">
<custom-business-list name="{{name}}" toolData="{{toolData}}"></custom-business-list>
<custom-food-list name="{{name}}" toolData="{{toolData}}"></custom-food-list>
</view>
</block> -->
<block>
<view class="customCard">
<custom-map wx:if="{{name === 'geocoder' || name === 'placeSearchNearby' || 'directionDriving'}}" name="{{name}}" toolParams="{{toolParams}}" toolData="{{toolData}}"></custom-map>
</view>
<view class="customCard">
<custom-weather wx:if="{{name === 'weather'}}" name="{{name}}" toolData="{{toolData}}"></custom-weather>
</view>
<view class="customCard" wx:if="{{name === 'placeSearchNearby'}}">
<custom-business-list name="{{name}}" toolData="{{toolData}}"></custom-business-list>
</view>
<!-- 用户可类似添加自定义组件 -->
</block>

View File

@ -0,0 +1,3 @@
.customCard {
margin: 15px 0px;
}

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.0003 0.630371L14.9029 8.98093L23.7417 9.16105L16.6969 14.5021L19.2569 22.964L12.0003 17.9144L4.74363 22.964L7.30367 14.5021L0.258789 9.16105L9.09761 8.98093L12.0003 0.630371ZM12.0003 6.72181L10.5298 10.9522L6.05209 11.0434L9.62099 13.7492L8.32409 18.0359L12.0003 15.4778L15.6764 18.0359L14.3795 13.7492L17.9484 11.0434L13.4707 10.9522L12.0003 6.72181Z" fill="#f2db4a" />
</svg>

After

Width:  |  Height:  |  Size: 473 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M12.0003 0.630371L14.9029 8.98093L23.7417 9.16105L16.6969 14.5021L19.2569 22.964L12.0003 17.9144L4.74363 22.964L7.30367 14.5021L0.258789 9.16105L9.09761 8.98093L12.0003 0.630371ZM12.0003 6.72181L10.5298 10.9522L6.05209 11.0434L9.62099 13.7492L8.32409 18.0359L12.0003 15.4778L15.6764 18.0359L14.3795 13.7492L17.9484 11.0434L13.4707 10.9522L12.0003 6.72181Z" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 471 B

View File

@ -0,0 +1,277 @@
// pages/components/feedback/index.js
Component({
/**
* 组件的属性列表
*/
properties: {
isShowFeedback: {
type: Boolean,
value: false
},
feedbackRecordId: {
type: String,
value: ''
},
feedbackType: {
type: String,
value: ''
},
botId: {
type: String,
value: ''
},
input: {
type: String,
value: ""
},
aiAnswer: {
type: String,
value: ''
}
},
/**
* 组件的初始数据
*/
data: {
upVote: [
{
"selected": false,
"value": "准确有效"
},
{
"selected": false,
"value": "回答全面"
},
{
"selected": false,
"value": "立场正确"
},
{
"selected": false,
"value": "格式规范"
},
{
"selected": false,
"value": "专业性强"
},
{
"selected": false,
"value": "富有创意"
},
{
"selected": false,
"value": "表达清晰"
},
{
"selected": false,
"value": "值得信赖"
},
{
"selected": false,
"value": "高效"
},
{
"selected": false,
"value": "满意"
}
],
downVote: [
{
"selected": false,
"value": "理解错误"
},
{
"selected": false,
"value": "未识别问题"
},
{
"selected": false,
"value": "事实错误"
},
{
"selected": false,
"value": "推理错误"
},
{
"selected": false,
"value": "内容不完整"
},
{
"selected": false,
"value": "不专业"
},
{
"selected": false,
"value": "违法有害"
},
{
"selected": false,
"value": "格式错误"
},
{
"selected": false,
"value": "乱码"
},
{
"selected": false,
"value": "内容重复"
}
],
score: 5,
message: ""
},
observers:{
"feedbackType":function (value) {
this.setData({score:value==='upvote'?5:1})
}
},
/**
* 组件的方法列表
*/
methods: {
reset: function () {
this.setData({
upVote: [
{
"selected": false,
"value": "准确有效"
},
{
"selected": false,
"value": "回答全面"
},
{
"selected": false,
"value": "立场正确"
},
{
"selected": false,
"value": "格式规范"
},
{
"selected": false,
"value": "专业性强"
},
{
"selected": false,
"value": "富有创意"
},
{
"selected": false,
"value": "表达清晰"
},
{
"selected": false,
"value": "值得信赖"
},
{
"selected": false,
"value": "高效"
},
{
"selected": false,
"value": "满意"
}
],
downVote: [
{
"selected": false,
"value": "理解错误"
},
{
"selected": false,
"value": "未识别问题"
},
{
"selected": false,
"value": "事实错误"
},
{
"selected": false,
"value": "推理错误"
},
{
"selected": false,
"value": "内容不完整"
},
{
"selected": false,
"value": "不专业"
},
{
"selected": false,
"value": "违法有害"
},
{
"selected": false,
"value": "格式错误"
},
{
"selected": false,
"value": "乱码"
},
{
"selected": false,
"value": "内容重复"
}
],
score: 5,
message: ""
})
},
onChangeScore: function (e) {
const { score } = e.currentTarget.dataset
this.setData({ score })
},
onSelect: function (e) {
const { item } = e.currentTarget.dataset
const newArr = [...this.data.feedbackType === 'upvote' ? this.data.upVote : this.data.downVote]
const [selectedItem] = newArr.filter(i => i.value === item.value)
selectedItem.selected = !selectedItem.selected
if (this.data.feedbackType === 'upvote') {
this.setData({ upVote: newArr })
} else {
this.setData({ downVote: newArr })
}
},
inputChange: function (e) {
const value = e.detail.value
this.setData({ message: value })
},
closeShowFeedback: function () {
this.triggerEvent('close')
},
submitFeedback: async function () {
const res = await wx.cloud.extend.AI.bot.sendFeedback({
userFeedback: {
botId: this.data.botId,
recordId: this.data.feedbackRecordId,
comment: this.data.message,
rating: this.data.score,
tags: this.data.feedbackType === 'upvote' ? this.data.upVote.filter(item => item.selected).map(item => item.value) : this.data.downVote.filter(item => item.selected).map(item => item.value),
aiAnswer: this.data.aiAnswer,
input: this.data.input,
type: this.data.feedbackType === 'upvote' ? "upvote" : 'downvote',
},
botId: this.data.botId
});
if (res.status === 'success') {
wx.showToast({
title: "感谢反馈",
icon: "success",
});
} else {
wx.showToast({
title: "反馈失败",
icon: "fail",
});
}
this.reset();
// console.log(res)
this.triggerEvent("close")
}
}
})

View File

@ -0,0 +1,4 @@
{
"component": true,
"usingComponents": {}
}

View File

@ -0,0 +1,35 @@
<view class="feedback-modal" wx:if="{{isShowFeedback}}">
<view class="feedback">
<view class="feedback-header">
感谢您的宝贵反馈,我们会不断改进服务
</view>
<view class="feedback-body">
<view class="item-box">
<view class="item-title">评分</view>
<view style="display: flex; gap: 14rpx;">
<block wx:for="{{[1,2,3,4,5]}}" wx:key="*this">
<image src="{{item<=score?'./imgs/star-highlight.svg':'./imgs/star.svg'}}" mode="aspectFill" class="star" bind:touchend="onChangeScore" data-score="{{item}}" />
</block>
</view>
</view>
<view class="item-box">
<view class="item-title">回答内容</view>
<view>
<block wx:for="{{feedbackType==='upvote'?upVote:downVote}}" wx:key="value">
<view class="{{item.selected?'vote-item-highlight':'vote-item-normal'}}" bind:tap="onSelect" data-item="{{item}}">{{item.value}}</view>
</block>
</view>
</view>
<view class="item-box">
<view class="item-title">反馈建议</view>
<view>
<textarea value="{{message}}" class="feedback-textarea" maxlength="140" bindinput="inputChange"/>
</view>
</view>
</view>
<view class="feedback-footer">
<view class="btn-cancel" bind:tap="closeShowFeedback">取消</view>
<view class="btn-submit" bind:tap="submitFeedback">提交反馈</view>
</view>
</view>
</view>

View File

@ -0,0 +1,91 @@
/* pages/components/feedback/index.wxss */
.feedback-modal {
position: fixed;
top: 0px;
left: 0px;
width: 750rpx;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
}
.feedback {
width: 520rpx;
max-height: 70%;
overflow-y: auto;
background-color: #fff;
border-radius: 24rpx;
padding: 40rpx;
}
.feedback-header{
font-weight: 500;
font-size: 32rpx;
text-align: justify;
}
.feedback-body{
font-size: 28rpx;
}
.item-box{
padding: 28rpx 0px;
}
.item-title{
font-size: 28rpx;
padding-bottom: 28rpx;
}
.star{
width: 40rpx;
height: 40rpx;
}
.vote-item-normal{
display: inline-block;
background-color: rgba(243, 243, 243, 1);
height: 48rpx;
line-height: 48rpx;
border-radius: 24rpx;
padding: 4rpx 24rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
}
.vote-item-highlight{
display: inline-block;
background-color: rgba(0, 82, 217, 0.1);
height: 48rpx;
line-height: 48rpx;
border-radius: 24rpx;
padding: 4rpx 24rpx;
margin-right: 16rpx;
margin-bottom: 16rpx;
color: rgb(0, 82, 217);
}
.feedback-textarea{
width: 100%;
height: 150rpx;
border-radius: 16rpx;
border: 1px solid #ccc;
box-sizing: border-box;
padding: 16rpx;
}
.feedback-footer{
font-size: 28rpx;
display: flex;
justify-content: flex-end;
gap: 24rpx;
}
.btn-cancel{
box-sizing: border-box;
background-color: #fff;
border: 1px solid #eee;
padding: 6rpx 24rpx;
border-radius: 6rpx;
line-height: 48rpx;
}
.btn-submit{
box-sizing: border-box;
padding: 6rpx 24rpx;
border-radius: 6rpx;
color: #fff;
background-color: #0052d9;
line-height: 48rpx;
}

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.5001 8.08575L12.0002 13.5858L6.50015 8.08576L5.08594 9.49997L12.0002 16.4142L18.9144 9.49997L17.5001 8.08575Z" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 244 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.88197 1.99988H16.118L17.618 4.99988H23V20.9999H1V4.99988H6.38197L7.88197 1.99988ZM9.11803 3.99988L7.61803 6.99988H3V18.9999H21V6.99988H16.382L14.882 3.99988H9.11803ZM12 9.49988C10.3431 9.49988 9 10.843 9 12.4999C9 14.1567 10.3431 15.4999 12 15.4999C13.6569 15.4999 15 14.1567 15 12.4999C15 10.843 13.6569 9.49988 12 9.49988ZM7 12.4999C7 9.73845 9.23858 7.49988 12 7.49988C14.7614 7.49988 17 9.73845 17 12.4999C17 15.2613 14.7614 17.4999 12 17.4999C9.23858 17.4999 7 15.2613 7 12.4999Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 630 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><rect width="2.8" height="12" x="1" y="6" fill="#e84f50"><animate attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="5.8" y="6" fill="#e84f50"><animate attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="10.6" y="6" fill="#e84f50"><animate id="svgSpinnersBarsScaleMiddle0" attributeName="y" begin="0;svgSpinnersBarsScaleMiddle1.end-0.1s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="0;svgSpinnersBarsScaleMiddle1.end-0.1s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="15.4" y="6" fill="#e84f50"><animate attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="20.2" y="6" fill="#e84f50"><animate id="svgSpinnersBarsScaleMiddle1" attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.02944 3 3 7.02944 3 12C3 14.3966 3.93542 16.5725 5.46305 18.1862L5.96701 18.7185L4.69951 21H12C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23H1.30049L3.51936 19.006C1.94632 17.1038 1 14.6615 1 12ZM13 8V11H16V13H13V16H11V13H8V11H11V8H13Z" fill="#4d6bfe" />
</svg>

After

Width:  |  Height:  |  Size: 470 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.02944 3 3 7.02944 3 12C3 14.3966 3.93542 16.5725 5.46305 18.1862L5.96701 18.7185L4.69951 21H12C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23H1.30049L3.51936 19.006C1.94632 17.1038 1 14.6615 1 12ZM13 8V11H16V13H13V16H11V13H8V11H11V8H13Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 480 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.02944 3 3 7.02944 3 12C3 14.3966 3.93542 16.5725 5.46305 18.1862L5.96701 18.7185L4.69951 21H12C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23H1.30049L3.51936 19.006C1.94632 17.1038 1 14.6615 1 12ZM13 5.5V11.5858L16.4142 15L15 16.4142L11 12.4142V5.5H13Z" fill="rgb(160, 160, 160)" />
</svg>

After

Width:  |  Height:  |  Size: 497 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M20.985 7.37845L10.3784 17.985L4.0144 11.6211L5.42862 10.2069L10.3784 15.1566L19.5708 5.96423L20.985 7.37845Z" fill="green" />
</svg>

After

Width:  |  Height:  |  Size: 237 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9 1L15 1L15 9.5L21 9.5L21 23L3 23L3 9.5L9 9.5L9 1ZM11 3L11 11.5L5 11.5V14L19 14L19 11.5H13L13 3L11 3ZM19 16L5 16L5 21H14V18L16 18V21H19V16Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 400 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.0502 5.63611L11.9999 10.5859L16.9497 5.63611L18.3639 7.05032L13.4142 12.0001L18.3639 16.9498L16.9497 18.364L11.9999 13.4143L7.0502 18.364L5.63599 16.9498L10.5857 12.0001L5.63599 7.05032L7.0502 5.63611Z" fill="red" />
</svg>

After

Width:  |  Height:  |  Size: 333 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.0502 5.63611L11.9999 10.5859L16.9497 5.63611L18.3639 7.05032L13.4142 12.0001L18.3639 16.9498L16.9497 18.364L11.9999 13.4143L7.0502 18.364L5.63599 16.9498L10.5857 12.0001L5.63599 7.05032L7.0502 5.63611Z" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 335 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2 2H15V7.5H13V4H4V13H7.5V15H2V2ZM9 9H22V22H9V9ZM11 11V20H20V11H11Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 197 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16.4278 1.96289L22.0381 7.57319L7.61066 22.0007L2.00037 22.0007L2.00037 16.3904L16.4278 1.96289ZM16.4278 4.79132L13.646 7.57319L16.4278 10.3551L19.2097 7.57319L16.4278 4.79132ZM15.0136 11.7693L12.2318 8.9874L4.00037 17.2188L4.00037 20.0007H6.78224L15.0136 11.7693ZM22.2252 22.0007H12.6821V20.0007L22.2252 20.0007V22.0007Z" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 453 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.0001 3C7.02956 3 3.00012 7.02944 3.00012 12C3.00012 16.9706 7.02956 21 12.0001 21C16.9707 21 21.0001 16.9706 21.0001 12C21.0001 7.02944 16.9707 3 12.0001 3ZM1.00012 12C1.00012 5.92487 5.92499 1 12.0001 1C18.0753 1 23.0001 5.92487 23.0001 12C23.0001 18.0751 18.0753 23 12.0001 23C5.92499 23 1.00012 18.0751 1.00012 12ZM13.0001 6.5V14H11.0001V6.5H13.0001ZM11.0001 15.5H13.004V17.5039H11.0001V15.5Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 532 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 32 32"><path fill="#20744a" fill-rule="evenodd" d="M28.781 4.405h-10.13V2.018L2 4.588v22.527l16.651 2.868v-3.538h10.13A1.16 1.16 0 0 0 30 25.349V5.5a1.16 1.16 0 0 0-1.219-1.095m.16 21.126H18.617l-.017-1.889h2.487v-2.2h-2.506l-.012-1.3h2.518v-2.2H18.55l-.012-1.3h2.549v-2.2H18.53v-1.3h2.557v-2.2H18.53v-1.3h2.557v-2.2H18.53v-2h10.411Z"/><path fill="#20744a" d="M22.487 7.439h4.323v2.2h-4.323zm0 3.501h4.323v2.2h-4.323zm0 3.501h4.323v2.2h-4.323zm0 3.501h4.323v2.2h-4.323zm0 3.501h4.323v2.2h-4.323z"/><path fill="#fff" fill-rule="evenodd" d="m6.347 10.673l2.146-.123l1.349 3.709l1.594-3.862l2.146-.123l-2.606 5.266l2.606 5.279l-2.269-.153l-1.532-4.024l-1.533 3.871l-2.085-.184l2.422-4.663z"/></svg>

After

Width:  |  Height:  |  Size: 773 B

View File

@ -0,0 +1,3 @@
<svg width="20px" height="20px" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M4 4C4 2.89543 4.89543 2 6 2H10.5858C11.1162 2 11.6249 2.21071 12 2.58579L15.4142 6C15.7893 6.37507 16 6.88378 16 7.41421V16C16 17.1046 15.1046 18 14 18H6C4.89543 18 4 17.1046 4 16V4ZM6 10C6 9.44772 6.44772 9 7 9H13C13.5523 9 14 9.44772 14 10C14 10.5523 13.5523 11 13 11H7C6.44772 11 6 10.5523 6 10ZM7 13C6.44772 13 6 13.4477 6 14C6 14.5523 6.44772 15 7 15H13C13.5523 15 14 14.5523 14 14C14 13.4477 13.5523 13 13 13H7Z" fill="#3895FB"/>
</svg>

After

Width:  |  Height:  |  Size: 598 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 16 16"><g fill="none"><path fill="url(#fluentColorImage162)" d="M2 4.5A2.5 2.5 0 0 1 4.5 2h7A2.5 2.5 0 0 1 14 4.5v7a2.5 2.5 0 0 1-2.5 2.5h-7A2.5 2.5 0 0 1 2 11.5z"/><path fill="url(#fluentColorImage160)" d="M13.586 12.879A2.5 2.5 0 0 1 11.5 14h-7a2.5 2.5 0 0 1-2.086-1.121l4.384-4.384a1.7 1.7 0 0 1 2.404 0z"/><path fill="url(#fluentColorImage161)" d="M11.5 5.502a1.002 1.002 0 1 1-2.004 0a1.002 1.002 0 0 1 2.004 0"/><defs><linearGradient id="fluentColorImage160" x1="6.286" x2="7.572" y1="7.997" y2="14.347" gradientUnits="userSpaceOnUse"><stop stop-color="#b3e0ff"/><stop offset="1" stop-color="#8cd0ff"/></linearGradient><linearGradient id="fluentColorImage161" x1="10.097" x2="10.829" y1="4.277" y2="6.913" gradientUnits="userSpaceOnUse"><stop stop-color="#fdfdfd"/><stop offset="1" stop-color="#b3e0ff"/></linearGradient><radialGradient id="fluentColorImage162" cx="0" cy="0" r="1" gradientTransform="matrix(20.57146 26.03575 -23.68122 18.71109 -2.714 -4.75)" gradientUnits="userSpaceOnUse"><stop offset=".338" stop-color="#0fafff"/><stop offset=".529" stop-color="#367af2"/></radialGradient></defs></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2.00003 4V6H22V4H2.00003Z" fill="black" /><path d="M8.00003 11V13H22V11H8.00003Z" fill="black" /><path d="M2.00003 18H22V20H2.00003V18Z" fill="black" /><path d="M1.58582 11.9998L4.7678 15.1818L6.18201 13.7676L4.41424 11.9998L6.18201 10.232L4.7678 8.81783L1.58582 11.9998Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M2.99997 4H1.99997V6H2.99997H21H22V4H21H2.99997ZM8.99997 11H7.99997V13H8.99997H21H22V11H21H8.99997ZM1.99997 18H2.99997H21H22V20H21H2.99997H1.99997V18ZM5.80474 12.7073L6.51184 12.0002L5.80474 11.2931L4.03697 9.52532L3.32986 8.81821L1.91565 10.2324L2.62276 10.9395L3.68342 12.0002L2.62276 13.0608L1.91565 13.768L3.32986 15.1822L4.03697 14.4751L5.80474 12.7073Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 501 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M3.05493 11C3.45261 7.40254 5.97062 4.44413 9.33156 3.40217C8.00851 5.65483 7.1892 8.23957 7.02895 11H3.05493ZM10.9922 1.04555C5.38944 1.55442 1 6.26461 1 12C1 17.7354 5.3894 22.4455 10.9922 22.9545L11 22.9643L11.4254 22.9853C11.4932 22.9887 11.5611 22.9916 11.6292 22.9939C11.7523 22.9979 11.8759 23 12 23C12.1187 23 12.2369 22.9981 12.3546 22.9944C12.4281 22.9921 12.5015 22.989 12.5746 22.9853L13 22.9643L13.0078 22.9545C18.6106 22.4455 23 17.7354 23 12C23 6.26461 18.6106 1.55443 13.0078 1.04555L12.9999 1.03571L12.5736 1.0147C12.4767 1.00972 12.3795 1.006 12.2819 1.00354C12.1882 1.00119 12.0942 1 12 1C11.9051 1 11.8104 1.0012 11.7161 1.00359C11.6192 1.00605 11.5226 1.00976 11.4263 1.0147L11.0001 1.03571L10.9922 1.04555ZM12.0011 3C13.6972 5.25767 14.7704 8.00828 14.9672 11H9.03278C9.22955 8.00828 10.3028 5.25767 11.9989 3C11.9992 3 11.9996 3 12 3C12.0004 3 12.0008 3 12.0011 3ZM7.02894 13C7.18917 15.7604 8.00847 18.3452 9.3315 20.5978C5.97059 19.5558 3.45261 16.5974 3.05493 13H7.02894ZM11.9988 21C10.3028 18.7423 9.22953 15.9917 9.03277 13H14.9672C14.7705 15.9917 13.6972 18.7423 12.0012 21C12.0008 21 12.0004 21 12 21C11.9996 21 11.9992 21 11.9988 21ZM14.6685 20.5978C15.9915 18.3452 16.8108 15.7604 16.9711 13H20.9451C20.5474 16.5974 18.0294 19.5558 14.6685 20.5978ZM16.9711 11C16.8108 8.23957 15.9915 5.65483 14.6684 3.40217C18.0294 4.44413 20.5474 7.40254 20.9451 11H16.9711Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="rgb(77, 107, 254)" xmlns="http://www.w3.org/2000/svg"><path d="M3.05493 11C3.45261 7.40254 5.97062 4.44413 9.33156 3.40217C8.00851 5.65483 7.1892 8.23957 7.02895 11H3.05493ZM10.9922 1.04555C5.38944 1.55442 1 6.26461 1 12C1 17.7354 5.3894 22.4455 10.9922 22.9545L11 22.9643L11.4254 22.9853C11.4932 22.9887 11.5611 22.9916 11.6292 22.9939C11.7523 22.9979 11.8759 23 12 23C12.1187 23 12.2369 22.9981 12.3546 22.9944C12.4281 22.9921 12.5015 22.989 12.5746 22.9853L13 22.9643L13.0078 22.9545C18.6106 22.4455 23 17.7354 23 12C23 6.26461 18.6106 1.55443 13.0078 1.04555L12.9999 1.03571L12.5736 1.0147C12.4767 1.00972 12.3795 1.006 12.2819 1.00354C12.1882 1.00119 12.0942 1 12 1C11.9051 1 11.8104 1.0012 11.7161 1.00359C11.6192 1.00605 11.5226 1.00976 11.4263 1.0147L11.0001 1.03571L10.9922 1.04555ZM12.0011 3C13.6972 5.25767 14.7704 8.00828 14.9672 11H9.03278C9.22955 8.00828 10.3028 5.25767 11.9989 3C11.9992 3 11.9996 3 12 3C12.0004 3 12.0008 3 12.0011 3ZM7.02894 13C7.18917 15.7604 8.00847 18.3452 9.3315 20.5978C5.97059 19.5558 3.45261 16.5974 3.05493 13H7.02894ZM11.9988 21C10.3028 18.7423 9.22953 15.9917 9.03277 13H14.9672C14.7705 15.9917 13.6972 18.7423 12.0012 21C12.0008 21 12.0004 21 12 21C11.9996 21 11.9992 21 11.9988 21ZM14.6685 20.5978C15.9915 18.3452 16.8108 15.7604 16.9711 13H20.9451C20.5474 16.5974 18.0294 19.5558 14.6685 20.5978ZM16.9711 11C16.8108 8.23957 15.9915 5.65483 14.6684 3.40217C18.0294 4.44413 20.5474 7.40254 20.9451 11H16.9711Z" fill="rgb(77, 107, 254)" />
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1 3H23V21H1V3ZM3 5V19H21V5H3ZM4.99609 7.5H7V9.50391H4.99609V7.5ZM8.99609 7.5H11V9.50391H8.99609V7.5ZM12.9961 7.5H15V9.50391H12.9961V7.5ZM16.9961 7.5H19V9.50391H16.9961V7.5ZM4.99609 10.5H7V12.5039H4.99609V10.5ZM8.99609 10.5H11V12.5039H8.99609V10.5ZM12.9961 10.5H15V12.5039H12.9961V10.5ZM16.9961 10.5H19V12.5039H16.9961V10.5ZM5 15H19V17H5V15Z" fill="black" />
</svg>

After

Width:  |  Height:  |  Size: 472 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><path fill="rgb(95, 114, 146)" d="M12,4a8,8,0,0,1,7.89,6.7A1.53,1.53,0,0,0,21.38,12h0a1.5,1.5,0,0,0,1.48-1.75,11,11,0,0,0-21.72,0A1.5,1.5,0,0,0,2.62,12h0a1.53,1.53,0,0,0,1.49-1.3A8,8,0,0,1,12,4Z"><animateTransform attributeName="transform" dur="0.75s" repeatCount="indefinite" type="rotate" values="0 12 12;360 12 12"/></path></svg>

After

Width:  |  Height:  |  Size: 417 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12ZM10.5 7V17H8.5V7H10.5ZM15.5 7V17H13.5V7H15.5Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 402 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" viewBox="0 0 32 32"><path fill="#909090" d="m24.1 2.072l5.564 5.8v22.056H8.879V30h20.856V7.945z"/><path fill="#f4f4f4" d="M24.031 2H8.808v27.928h20.856V7.873z"/><path fill="#7a7b7c" d="M8.655 3.5h-6.39v6.827h20.1V3.5z"/><path fill="#dd2025" d="M22.472 10.211H2.395V3.379h20.077z"/><path fill="#464648" d="M9.052 4.534H7.745v4.8h1.028V7.715L9 7.728a2 2 0 0 0 .647-.117a1.4 1.4 0 0 0 .493-.291a1.2 1.2 0 0 0 .335-.454a2.1 2.1 0 0 0 .105-.908a2.2 2.2 0 0 0-.114-.644a1.17 1.17 0 0 0-.687-.65a2 2 0 0 0-.409-.104a2 2 0 0 0-.319-.026m-.189 2.294h-.089v-1.48h.193a.57.57 0 0 1 .459.181a.92.92 0 0 1 .183.558c0 .246 0 .469-.222.626a.94.94 0 0 1-.524.114m3.671-2.306c-.111 0-.219.008-.295.011L12 4.538h-.78v4.8h.918a2.7 2.7 0 0 0 1.028-.175a1.7 1.7 0 0 0 .68-.491a1.9 1.9 0 0 0 .373-.749a3.7 3.7 0 0 0 .114-.949a4.4 4.4 0 0 0-.087-1.127a1.8 1.8 0 0 0-.4-.733a1.6 1.6 0 0 0-.535-.4a2.4 2.4 0 0 0-.549-.178a1.3 1.3 0 0 0-.228-.017m-.182 3.937h-.1V5.392h.013a1.06 1.06 0 0 1 .6.107a1.2 1.2 0 0 1 .324.4a1.3 1.3 0 0 1 .142.526c.009.22 0 .4 0 .549a3 3 0 0 1-.033.513a1.8 1.8 0 0 1-.169.5a1.1 1.1 0 0 1-.363.36a.67.67 0 0 1-.416.106m5.08-3.915H15v4.8h1.028V7.434h1.3v-.892h-1.3V5.43h1.4v-.892"/><path fill="#dd2025" d="M21.781 20.255s3.188-.578 3.188.511s-1.975.646-3.188-.511m-2.357.083a7.5 7.5 0 0 0-1.473.489l.4-.9c.4-.9.815-2.127.815-2.127a14 14 0 0 0 1.658 2.252a13 13 0 0 0-1.4.288Zm-1.262-6.5c0-.949.307-1.208.546-1.208s.508.115.517.939a10.8 10.8 0 0 1-.517 2.434a4.4 4.4 0 0 1-.547-2.162Zm-4.649 10.516c-.978-.585 2.051-2.386 2.6-2.444c-.003.001-1.576 3.056-2.6 2.444M25.9 20.895c-.01-.1-.1-1.207-2.07-1.16a14 14 0 0 0-2.453.173a12.5 12.5 0 0 1-2.012-2.655a11.8 11.8 0 0 0 .623-3.1c-.029-1.2-.316-1.888-1.236-1.878s-1.054.815-.933 2.013a9.3 9.3 0 0 0 .665 2.338s-.425 1.323-.987 2.639s-.946 2.006-.946 2.006a9.6 9.6 0 0 0-2.725 1.4c-.824.767-1.159 1.356-.725 1.945c.374.508 1.683.623 2.853-.91a23 23 0 0 0 1.7-2.492s1.784-.489 2.339-.623s1.226-.24 1.226-.24s1.629 1.639 3.2 1.581s1.495-.939 1.485-1.035"/><path fill="#909090" d="M23.954 2.077V7.95h5.633z"/><path fill="#f4f4f4" d="M24.031 2v5.873h5.633z"/><path fill="#fff" d="M8.975 4.457H7.668v4.8H8.7V7.639l.228.013a2 2 0 0 0 .647-.117a1.4 1.4 0 0 0 .493-.291a1.2 1.2 0 0 0 .332-.454a2.1 2.1 0 0 0 .105-.908a2.2 2.2 0 0 0-.114-.644a1.17 1.17 0 0 0-.687-.65a2 2 0 0 0-.411-.105a2 2 0 0 0-.319-.026m-.189 2.294h-.089v-1.48h.194a.57.57 0 0 1 .459.181a.92.92 0 0 1 .183.558c0 .246 0 .469-.222.626a.94.94 0 0 1-.524.114m3.67-2.306c-.111 0-.219.008-.295.011l-.235.006h-.78v4.8h.918a2.7 2.7 0 0 0 1.028-.175a1.7 1.7 0 0 0 .68-.491a1.9 1.9 0 0 0 .373-.749a3.7 3.7 0 0 0 .114-.949a4.4 4.4 0 0 0-.087-1.127a1.8 1.8 0 0 0-.4-.733a1.6 1.6 0 0 0-.535-.4a2.4 2.4 0 0 0-.549-.178a1.3 1.3 0 0 0-.228-.017m-.182 3.937h-.1V5.315h.013a1.06 1.06 0 0 1 .6.107a1.2 1.2 0 0 1 .324.4a1.3 1.3 0 0 1 .142.526c.009.22 0 .4 0 .549a3 3 0 0 1-.033.513a1.8 1.8 0 0 1-.169.5a1.1 1.1 0 0 1-.363.36a.67.67 0 0 1-.416.106m5.077-3.915h-2.43v4.8h1.028V7.357h1.3v-.892h-1.3V5.353h1.4v-.892"/></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g opacity="0.9"> <path d="M12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12ZM8.5 6.37083L18.25 12L8.5 17.6292L8.5 6.37083ZM10.5 9.83494L10.5 14.1651L14.25 12L10.5 9.83494Z" fill="#8b8b8b" /></g>
</svg>

After

Width:  |  Height:  |  Size: 485 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><rect width="2.8" height="12" x="1" y="6" fill="#8b8b8b"><animate id="svgSpinnersBarsScale0" attributeName="y" begin="0;svgSpinnersBarsScale1.end-0.1s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="6;1;6"/><animate attributeName="height" begin="0;svgSpinnersBarsScale1.end-0.1s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="12;22;12"/></rect><rect width="2.8" height="12" x="5.8" y="6" fill="#8b8b8b"><animate attributeName="y" begin="svgSpinnersBarsScale0.begin+0.1s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScale0.begin+0.1s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="12;22;12"/></rect><rect width="2.8" height="12" x="10.6" y="6" fill="#8b8b8b"><animate attributeName="y" begin="svgSpinnersBarsScale0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScale0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="12;22;12"/></rect><rect width="2.8" height="12" x="15.4" y="6" fill="#8b8b8b"><animate attributeName="y" begin="svgSpinnersBarsScale0.begin+0.3s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScale0.begin+0.3s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="12;22;12"/></rect><rect width="2.8" height="12" x="20.2" y="6" fill="#8b8b8b"><animate id="svgSpinnersBarsScale1" attributeName="y" begin="svgSpinnersBarsScale0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScale0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".36,.61,.3,.98;.36,.61,.3,.98" values="12;22;12"/></rect></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 32 32"><path fill="#d33922" d="M18.536 2.321v2.863c3.4.019 7.357-.035 10.754.016c.642 0 .67.568.678 1.064c.054 5.942-.013 12.055.032 18c-.012.234-.006 1.1-.013 1.346c-.022.823-.434.859-1.257.884c-.132 0-.52.006-.648.012c-3.181-.016-6.362-.009-9.546-.009v3.182L2 27.134V4.873z"/><path fill="#fff" d="M18.536 6.138h10.5v19.4h-10.5V23h7.634v-1.275h-7.634v-1.59h7.634v-1.272h-7.631q.002-.936-.006-1.87a4.47 4.47 0 0 0 3.82-.375a4.35 4.35 0 0 0 1.959-3.474c-1.4-.01-2.793-.006-4.186-.006c0-1.384.016-2.767-.029-4.148c-.522.1-1.043.21-1.562.321V6.139"/><path fill="#d33922" d="M20.766 8.324a4.476 4.476 0 0 1 4.186 4.167c-1.4.016-2.793.01-4.189.01V8.324"/><path fill="#fff" d="M7.1 10.726c1.727.083 3.82-.684 5.252.611c1.371 1.664 1.008 4.724-1.024 5.719A4.7 4.7 0 0 1 9 17.348c0 1.244-.006 2.488 0 3.731q-.947-.082-1.893-.159c-.029-3.4-.035-6.8 0-10.2"/><path fill="#d33922" d="M8.993 12.446c.627-.029 1.4-.143 1.826.445a2.3 2.3 0 0 1 .041 2.087c-.363.655-1.183.592-1.816.668c-.067-1.066-.06-2.131-.051-3.2"/></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.0961 5.90381C12.5577 3.3654 8.44209 3.3654 5.90368 5.90381C3.36528 8.44221 3.36528 12.5578 5.90368 15.0962C8.44209 17.6346 12.5577 17.6346 15.0961 15.0962C17.6345 12.5578 17.6345 8.44221 15.0961 5.90381ZM4.48947 4.48959C7.80893 1.17014 13.1908 1.17014 16.5103 4.48959C19.5905 7.56982 19.8125 12.4259 17.1762 15.7621L22.5207 21.1066L21.1065 22.5208L15.762 17.1764C12.4258 19.8126 7.5697 19.5906 4.48947 16.5104C1.17001 13.191 1.17001 7.80905 4.48947 4.48959Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 604 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_100396_60187)"> <path d="M0.291748 1.66449L24.0026 12L0.291748 22.3355L3.93958 12L0.291748 1.66449ZM5.70755 13L3.70832 18.6645L18.9974 12L3.70832 5.33551L5.70755 11H11V13H5.70755Z" fill="#fff" /></g><defs> <clipPath id="clip0_100396_60187"> <rect width="24" height="24" fill="white" /> </clipPath></defs>
</svg>

After

Width:  |  Height:  |  Size: 458 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 24 24"><rect width="2.8" height="12" x="1" y="6" fill="#68c692"><animate attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="5.8" y="6" fill="#68c692"><animate attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="10.6" y="6" fill="#68c692"><animate id="svgSpinnersBarsScaleMiddle0" attributeName="y" begin="0;svgSpinnersBarsScaleMiddle1.end-0.1s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="0;svgSpinnersBarsScaleMiddle1.end-0.1s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="15.4" y="6" fill="#68c692"><animate attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.2s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect><rect width="2.8" height="12" x="20.2" y="6" fill="#68c692"><animate id="svgSpinnersBarsScaleMiddle1" attributeName="y" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="6;1;6"/><animate attributeName="height" begin="svgSpinnersBarsScaleMiddle0.begin+0.4s" calcMode="spline" dur="0.6s" keySplines=".14,.73,.34,1;.65,.26,.82,.45" values="12;22;12"/></rect></svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12.0001 3.00488C7.02956 3.00488 3.00012 7.03432 3.00012 12.0049C3.00012 16.9754 7.02956 21.0049 12.0001 21.0049C16.9707 21.0049 21.0001 16.9754 21.0001 12.0049C21.0001 7.03432 16.9707 3.00488 12.0001 3.00488ZM1.00012 12.0049C1.00012 5.92975 5.92499 1.00488 12.0001 1.00488C18.0753 1.00488 23.0001 5.92975 23.0001 12.0049C23.0001 18.08 18.0753 23.0049 12.0001 23.0049C5.92499 23.0049 1.00012 18.08 1.00012 12.0049ZM13.0001 6.50488L13.0001 11.0049H17.5001V13.0049H13.0001L13.0001 17.5049H11.0001L11.0001 13.0049H6.50012V11.0049H11.0001L11.0001 6.50488H13.0001Z" fill="#333" />
</svg>

After

Width:  |  Height:  |  Size: 689 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.5001 1.85059L23.5526 12L11.5001 22.1495V15.9233C7.30565 16.1238 4.4268 17.6231 2.31385 20.5813L0.519531 19.8039C1.04297 17.1867 2.10079 14.5092 3.99754 12.3415C5.75937 10.328 8.20695 8.79947 11.5001 8.15506L11.5001 1.85059ZM13.5001 6.14948L13.5001 9.86733L12.6415 9.98998C9.37204 10.4571 7.09103 11.8433 5.50269 13.6585C4.79919 14.4625 4.22297 15.3609 3.75752 16.3174C6.09576 14.6658 8.97868 13.9 12.5001 13.9H13.5001V17.8506L20.4476 12L13.5001 6.14948Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 590 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M15.0001 1.29053V22.71L5.73703 17.5003L1.00013 17.5003L1.00012 6.50025H5.73703L15.0001 1.29053ZM4.99894 8.50025H3.00012L3.00012 15.5003L4.99894 15.5003L4.99894 8.50025ZM6.99894 15.9154L13.0001 19.2905V4.70998L6.99894 8.08514V15.9154ZM20.9793 6.98204L21.5819 7.78005C22.5 8.99571 22.9964 10.4777 22.9959 12.001C22.9953 13.5244 22.4979 15.006 21.579 16.2211L20.9758 17.0186L19.3806 15.8122L19.9838 15.0146C20.6402 14.1468 20.9955 13.0885 20.9959 12.0004C20.9963 10.9122 20.6417 9.85368 19.9859 8.98535L19.3832 8.18734L20.9793 6.98204ZM18.1865 9.09117L18.7892 9.88918C19.2482 10.497 19.4964 11.238 19.4962 11.9997C19.4959 12.7614 19.2472 13.5022 18.7877 14.1097L18.1845 14.9073L16.5893 13.7009L17.1925 12.9033C17.3895 12.6429 17.4961 12.3254 17.4962 11.999C17.4963 11.6725 17.3899 11.355 17.1932 11.0945L16.5905 10.2965L18.1865 9.09117Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 966 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3ZM1 12C1 5.92487 5.92487 1 12 1C18.0751 1 23 5.92487 23 12C23 18.0751 18.0751 23 12 23C5.92487 23 1 18.0751 1 12Z" fill="#d54941" /><path d="M8 8H16V16H8V8Z" fill="#d54941" />
</svg>

After

Width:  |  Height:  |  Size: 400 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M13.5266 5.69361C14.3427 6.35808 15.1567 7.09207 15.9514 7.88684C16.746 8.68139 17.4798 9.49511 18.1441 10.3111C18.7149 9.43842 19.1779 8.59599 19.5225 7.81267C19.9773 6.77901 20.2042 5.89778 20.2328 5.21464C20.2615 4.53265 20.093 4.1556 19.8875 3.95017C19.6821 3.74474 19.305 3.57623 18.6231 3.60485C17.9399 3.63353 17.0587 3.86037 16.025 4.31518C15.2417 4.65985 14.3992 5.12284 13.5266 5.69361ZM11.8389 4.41997C13.0019 3.61089 14.1454 2.95715 15.2195 2.48455C16.3866 1.97103 17.5214 1.64933 18.5392 1.60661C19.5581 1.56385 20.5669 1.80109 21.3017 2.53596C22.0366 3.27082 22.2738 4.27958 22.2311 5.29851C22.1884 6.31628 21.8667 7.45107 21.3531 8.61814C20.8806 9.69221 20.2269 10.8357 19.4178 11.9986C20.2271 13.1619 20.881 14.3056 21.3537 15.38C21.8672 16.547 22.1889 17.6818 22.2317 18.6996C22.2744 19.7185 22.0372 20.7273 21.3023 21.4621C20.5675 22.197 19.5587 22.4342 18.5398 22.3915C17.522 22.3488 16.3872 22.0271 15.2201 21.5136C14.1459 21.0409 13.0021 20.387 11.8389 19.5777C10.6758 20.387 9.53203 21.0409 8.45774 21.5136C7.29067 22.0271 6.15588 22.3488 5.13811 22.3915C4.11918 22.4342 3.11042 22.197 2.37556 21.4621C1.64069 20.7273 1.40345 19.7185 1.44621 18.6996C1.48893 17.6818 1.81063 16.547 2.32414 15.38C2.79685 14.3056 3.45076 13.1619 4.26006 11.9986C3.45103 10.8357 2.79732 9.69221 2.32473 8.61814C1.81122 7.45107 1.48952 6.31628 1.4468 5.29851C1.40403 4.27958 1.64128 3.27082 2.37614 2.53596C3.11101 1.80109 4.11976 1.56385 5.13869 1.60661C6.15647 1.64933 7.29126 1.97103 8.45833 2.48455C9.53243 2.95715 10.676 3.61089 11.8389 4.41997ZM5.53375 10.3111C6.19807 9.49511 6.93189 8.68139 7.72644 7.88684C8.5212 7.09207 9.33514 6.35808 10.1513 5.69361C9.27865 5.12284 8.43619 4.65985 7.65285 4.31518C6.6192 3.86037 5.73796 3.63353 5.05482 3.60485C4.37284 3.57623 3.99578 3.74474 3.79036 3.95017C3.58493 4.1556 3.41641 4.53265 3.44504 5.21464C3.47371 5.89778 3.70055 6.77901 4.15536 7.81267C4.50002 8.59599 4.963 9.43842 5.53375 10.3111ZM6.74564 11.9987C7.44705 12.8959 8.24907 13.8049 9.14123 14.697C10.0332 15.589 10.942 16.3908 11.8389 17.0921C12.7359 16.3908 13.6447 15.589 14.5366 14.697C15.4288 13.8049 16.2308 12.8959 16.9322 11.9987C16.231 11.1017 15.4291 10.193 14.5372 9.30105C13.6451 8.40891 12.7361 7.60691 11.8389 6.90552C10.9418 7.60691 10.0328 8.40891 9.14065 9.30105C8.24873 10.193 7.44691 11.1017 6.74564 11.9987ZM5.53368 13.6862C4.9627 14.5592 4.49954 15.4019 4.15477 16.1854C3.69997 17.2191 3.47313 18.1003 3.44445 18.7835C3.41583 19.4654 3.58434 19.8425 3.78977 20.0479C3.9952 20.2534 4.37225 20.4219 5.05424 20.3932C5.73738 20.3646 6.61861 20.1377 7.65227 19.6829C8.4358 19.3382 9.27848 18.875 10.1514 18.3041C9.33538 17.6397 8.52161 16.9059 7.72702 16.1113C6.93221 15.3165 6.19818 14.5025 5.53368 13.6862ZM13.5265 18.3041C14.3994 18.875 15.2421 19.3382 16.0256 19.6829C17.0593 20.1377 17.9405 20.3646 18.6236 20.3932C19.3056 20.4219 19.6827 20.2534 19.8881 20.0479C20.0935 19.8425 20.2621 19.4654 20.2334 18.7835C20.2048 18.1003 19.9779 17.2191 19.5231 16.1854C19.1783 15.4019 18.7152 14.5592 18.1442 13.6862C17.4797 14.5025 16.7457 15.3165 15.9509 16.1113C15.1563 16.9059 14.3425 17.6397 13.5265 18.3041ZM11.0001 11.0001H13.004V13.004H11.0001V11.0001Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.8786 21.9999L12.1576 21.7868C14.0863 21.4653 15.5 19.7965 15.5 17.8412V15.3826H20.8195C22.0554 15.3826 22.9955 14.2728 22.7923 13.0538L21.1257 3.05377C20.9649 2.08939 20.1306 1.38257 19.1529 1.38257H7V12.5804L10.8786 21.9999ZM12.1131 19.7451L9 12.1847V3.38257H19.1529L20.8195 13.3826H13.5V17.8412C13.5 18.72 12.9289 19.483 12.1131 19.7451ZM4 13.3826V1.38257H2V13.3826H4Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 507 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M10.8786 1.38257L12.1576 1.59573C14.0863 1.91719 15.5 3.58595 15.5 5.54131V7.99992H20.8195C22.0554 7.99992 22.9955 9.10966 22.7923 10.3287L21.1257 20.3287C20.9649 21.2931 20.1306 21.9999 19.1529 21.9999H7V10.8021L10.8786 1.38257ZM12.1131 3.63742L9 11.1977V19.9999L19.1529 19.9999L20.8195 9.99992H13.5V5.54131C13.5 4.66252 12.9289 3.89951 12.1131 3.63742ZM4 9.99992V21.9999H2V9.99992H4Z" fill="#8b8b8b" />
</svg>

After

Width:  |  Height:  |  Size: 518 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M11.0001 4.5L11.0002 16.0858L6.50015 11.5858L5.08594 13L12.0002 19.9142L18.9144 13L17.5001 11.5858L13.0002 16.0858L13.0001 4.5L11.0001 4.5Z" fill="rgb(128, 128, 128)" />
</svg>

After

Width:  |  Height:  |  Size: 281 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M1.99988 2H21.9999V22H1.99988V2ZM3.99988 20H17.5857L8.99988 11.4142L3.99988 16.4142V20ZM19.9999 19.5858V4H3.99988V13.5858L8.99988 8.58579L19.9999 19.5858ZM15.7968 7.25C15.2445 7.25 14.7968 7.69772 14.7968 8.25C14.7968 8.80228 15.2445 9.25 15.7968 9.25C16.349 9.25 16.7968 8.80228 16.7968 8.25C16.7968 7.69772 16.349 7.25 15.7968 7.25ZM12.7968 8.25C12.7968 6.59315 14.1399 5.25 15.7968 5.25C17.4536 5.25 18.7968 6.59315 18.7968 8.25C18.7968 9.90685 17.4536 11.25 15.7968 11.25C14.1399 11.25 12.7968 9.90685 12.7968 8.25Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 662 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 48 48"><g fill="none"><path stroke="#000" stroke-linejoin="round" stroke-width="4" d="M24 44c11.046 0 20-8.954 20-20S35.046 4 24 4S4 12.954 4 24s8.954 20 20 20Z"/><path fill="#000" d="M17 25.9a2 2 0 1 0 0-4a2 2 0 0 0 0 4"/><path stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="4" d="M21.95 28.85A6.98 6.98 0 0 0 24 23.9a6.98 6.98 0 0 0-2.05-4.95m4.95 14.849a13.96 13.96 0 0 0 4.1-9.9c0-3.866-1.567-7.366-4.1-9.899"/></g></svg>

After

Width:  |  Height:  |  Size: 531 B

View File

@ -0,0 +1,2 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M8.75 4.25C4.85689 4.25 2 6.88401 2 9.79408C2 11.3943 2.83472 12.8796 4.25197 13.9231C4.54488 14.1387 4.69759 14.4964 4.65074 14.8571L4.58136 15.3913L5.41173 14.9745C5.65098 14.8543 5.9284 14.8352 6.1819 14.9212C6.97088 15.1891 7.8375 15.3382 8.75 15.3382C9.00377 15.3382 9.254 15.3266 9.5 15.3042C9.50387 12.0935 12.1736 9.6258 15.4462 9.10286C15.0367 6.47982 12.332 4.25 8.75 4.25ZM17.4568 9.03026C21.0029 9.33461 24 11.9035 24 15.3112C24 16.9476 23.2887 18.413 22.1671 19.5096V21.4591C22.1671 21.8163 21.9765 22.1465 21.6671 22.3251C21.3577 22.5037 20.9765 22.5037 20.6671 22.3251L18.9424 21.3293C18.2488 21.5201 17.5119 21.6224 16.75 21.6224C13.6277 21.6224 10.8262 19.8749 9.85702 17.2784C9.49411 17.3179 9.12461 17.3382 8.75 17.3382C7.77222 17.3382 6.82917 17.2 5.94709 16.9436L3.79583 18.0236C3.4652 18.1896 3.06995 18.1595 2.76828 17.9454C2.46661 17.7312 2.30782 17.368 2.35547 17.0011L2.59463 15.1598C1.0185 13.8152 0 11.9258 0 9.79408C0 5.47576 4.0827 2.25 8.75 2.25C13.1377 2.25 17.0088 5.10087 17.4568 9.03026ZM5.24609 7.49609C5.24609 6.94381 5.69381 6.49609 6.24609 6.49609H6.25C6.80228 6.49609 7.25 6.94381 7.25 7.49609V7.5C7.25 8.05228 6.80228 8.5 6.25 8.5H6.24609C5.69381 8.5 5.24609 8.05228 5.24609 7.5V7.49609ZM10.25 7.50732C10.25 6.95504 10.6977 6.50732 11.25 6.50732H11.2539C11.8062 6.50732 12.2539 6.95504 12.2539 7.50732V7.51123C12.2539 8.06352 11.8062 8.51123 11.2539 8.51123H11.25C10.6977 8.51123 10.25 8.06352 10.25 7.51123V7.50732ZM16.75 11C16.6763 11 16.6029 11.0013 16.53 11.0037C13.5817 11.1038 11.5 13.1303 11.5 15.3112C11.5 15.5359 11.521 15.7559 11.5612 15.9704C11.9293 17.9298 14.0076 19.6224 16.75 19.6224C17.4593 19.6224 18.1322 19.5066 18.7446 19.2989C19.0172 19.2064 19.3165 19.2359 19.5658 19.3798L20.1671 19.727V19.0687C20.1671 18.7751 20.2962 18.4964 20.52 18.3064C21.4616 17.507 22 16.4444 22 15.3112C22 13.0766 19.8083 11 16.75 11ZM13.5561 13.656C13.5561 13.1037 14.0038 12.656 14.5561 12.656H14.56C15.1123 12.656 15.56 13.1037 15.56 13.656V13.6599C15.56 14.2122 15.1123 14.6599 14.56 14.6599H14.5561C14.0038 14.6599 13.5561 14.2122 13.5561 13.6599V13.656ZM17.9361 13.6599C17.9361 13.1076 18.3838 12.6599 18.9361 12.6599H18.94C19.4923 12.6599 19.94 13.1076 19.94 13.6599V13.6638C19.94 14.2161 19.4923 14.6638 18.94 14.6638H18.9361C18.3838 14.6638 17.9361 14.2161 17.9361 13.6638V13.6599Z" fill="rgb(95, 114, 146)" />
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 32 32"><defs><linearGradient id="vscodeIconsFileTypeWord0" x1="4.494" x2="13.832" y1="-1712.086" y2="-1695.914" gradientTransform="translate(0 1720)" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#2368c4"/><stop offset=".5" stop-color="#1a5dbe"/><stop offset="1" stop-color="#1146ac"/></linearGradient></defs><path fill="#41a5ee" d="M28.806 3H9.705a1.19 1.19 0 0 0-1.193 1.191V9.5l11.069 3.25L30 9.5V4.191A1.19 1.19 0 0 0 28.806 3"/><path fill="#2b7cd3" d="M30 9.5H8.512V16l11.069 1.95L30 16Z"/><path fill="#185abd" d="M8.512 16v6.5l10.418 1.3L30 22.5V16Z"/><path fill="#103f91" d="M9.705 29h19.1A1.19 1.19 0 0 0 30 27.809V22.5H8.512v5.309A1.19 1.19 0 0 0 9.705 29"/><path d="M16.434 8.2H8.512v16.25h7.922a1.2 1.2 0 0 0 1.194-1.191V9.391A1.2 1.2 0 0 0 16.434 8.2" opacity="0.1"/><path d="M15.783 8.85H8.512V25.1h7.271a1.2 1.2 0 0 0 1.194-1.191V10.041a1.2 1.2 0 0 0-1.194-1.191" opacity="0.2"/><path d="M15.783 8.85H8.512V23.8h7.271a1.2 1.2 0 0 0 1.194-1.191V10.041a1.2 1.2 0 0 0-1.194-1.191" opacity="0.2"/><path d="M15.132 8.85h-6.62V23.8h6.62a1.2 1.2 0 0 0 1.194-1.191V10.041a1.2 1.2 0 0 0-1.194-1.191" opacity="0.2"/><path fill="url(#vscodeIconsFileTypeWord0)" d="M3.194 8.85h11.938a1.193 1.193 0 0 1 1.194 1.191v11.918a1.193 1.193 0 0 1-1.194 1.191H3.194A1.19 1.19 0 0 1 2 21.959V10.041A1.19 1.19 0 0 1 3.194 8.85"/><path fill="#fff" d="M6.9 17.988q.035.276.046.481h.028q.015-.195.065-.47c.05-.275.062-.338.089-.465l1.255-5.407h1.624l1.3 5.326a8 8 0 0 1 .162 1h.022a8 8 0 0 1 .135-.975l1.039-5.358h1.477l-1.824 7.748h-1.727l-1.237-5.126q-.054-.222-.122-.578t-.084-.52h-.021q-.021.189-.084.561t-.1.552L7.78 19.871H6.024L4.19 12.127h1.5l1.131 5.418a5 5 0 0 1 .079.443"/></svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,11 @@
{
"component": true,
"usingComponents": {
"markdownPreview": "./wd-markdown/index",
"FoldedCard": "./collapse/index",
"chatFile": "./chatFile/index",
"feedback": "./feedback/index",
"customCard": "./customCard/index",
"tool": "./tool/index"
}
}

View File

@ -0,0 +1,391 @@
<!-- agent ui 组件根容器 -->
<view class="agent-ui" bind:tap="onTapPage">
<!-- 左侧抽屉,只在 bot 模式下展示 -->
<view wx-if="{{chatMode==='bot'&&!isAgent}}" class="drawer-mask {{isDrawerShow ? 'show' : ''}}" bindtap="closeDrawer"></view>
<view wx-if="{{chatMode==='bot'&&!isAgent}}" class="drawer {{isDrawerShow ? 'show' : ''}}">
<view class="drawer-header">
<view class="create-new-chat" bind:tap="clickCreateInDrawer">
<image style="width: 48rpx;height: 48rpx;margin-right: 10rpx" src="./imgs/chat-add.svg" mode="aspectFill" />
<text> 开启新对话 </text>
</view>
<image class="close-icon" src="./imgs/indent-left.svg" bindtap="closeDrawer" />
</view>
<view class="drawer-content">
<scroll-view enhanced="{{true}}" style="height: 100%;" show-scrollbar="{{false}}" scroll-y="true"
bindscrolltolower="scrollConToBottom">
<block wx:if="{{ conversations.length > 0 }}">
<view class="con-block" wx:if="{{transformConversations.todayCon.length}}">
<text class="date-title">今天</text>
<view class="con-container">
<view class="con-item {{item.conversationId === conversation.conversationId ? 'selected-con' : ''}}"
bind:tap="handleClickConversation" bind:longpress="handleLongPressConversation"
data-conversation="{{item}}" wx:for="{{transformConversations.todayCon}}" wx:key="index">
{{item.title}}
</view>
</view>
</view>
<view class="con-block" wx:if="{{transformConversations.curMonthCon.length}}">
<text class="date-title">本月</text>
<view class="con-container">
<view class="con-item {{item.conversationId === conversation.conversationId ? 'selected-con' : ''}}"
bind:tap="handleClickConversation" bind:longpress="handleLongPressConversation"
data-conversation="{{item}}" wx:for="{{transformConversations.curMonthCon}}" wx:key="index">
{{item.title}}
</view>
</view>
</view>
<view class="con-block" wx:if="{{transformConversations.earlyCon.length}}">
<text class="date-title">更早</text>
<view class="con-container">
<view class="con-item" bind:tap="handleClickConversation" bind:longpress="handleLongPressConversation"
data-conversation="{{item}}" wx:for="{{transformConversations.earlyCon}}" wx:key="index">
{{item.title}}
</view>
</view>
</view>
</block>
<block wx:else>
<view
style="width: 100%;height: 100%;display: flex;flex-direction: column;justify-content: center;align-items: center;">
<image src="./imgs/chat-bubble-history.svg" mode="aspectFill"
style="width: 100rpx;height: 100rpx;transform: translateY(-50%);" />
<text style="color: rgb(160, 160, 160)">暂无历史记录</text>
</view>
</block>
</scroll-view>
</view>
</view>
<!-- 标题栏包含会话列表展开按钮agent 名称,开启新会话按钮),只在 bot 模式下展示 -->
<view class="navBar {{showBotName ? 'showBotName' : 'hiddenBotName'}}" wx:if="{{chatMode === 'bot'&&!isAgent}}">
<view class="nav-content {{showBotName ? 'showBotName' : 'hiddenBotName'}}"
style="{{showMultiConversation ? 'justify-content: space-between;' : ''}}">
<image wx:if="{{bot.botId && showMultiConversation}}" bind:tap="openDrawer" class="con-icon"
src="./imgs/indent-right.svg" mode="aspectFill" />
<text wx:if="{{showBotName}}" class="bot-name">{{bot.name}}</text>
<image wx:if="{{bot.botId && showMultiConversation}}" class="con-icon" bind:tap="createNewConversation"
src="./imgs/chat-bubble-add.svg" mode="aspectFill" />
</view>
</view>
<view style="height: 100%;overflow: auto;position: relative;">
<!-- 聊天对话区 -->
<scroll-view bindwheel="onWheel" enhanced="{{true}}" bindscroll="onScroll" binddragstart="handleScrollStart"
class="main" style="height: 100%;" scroll-y="{{true}}" scroll-top="{{viewTop}}" scroll-into-view="{{ scrollTo }}"
lower-threshold="1" bindscrolltolower="handleScrollToLower" show-scrollbar="{{false}}"
refresher-enabled="{{showPullRefresh && (bot.multiConversationEnable ? conversation : true)}}"
refresher-threshold="{{80}}" bindrefresherrefresh="handleRefresh" refresher-triggered="{{triggered}}"
bounces="{{false}}">
<view class="contentBox" style="margin-bottom: 30px;">
<!-- 下拉刷新按钮,只在 bot 模式下展示 -->
<view
wx:if="{{chatMode === 'bot'&& !isAgent && bot.botId && showPullRefresh && (bot.multiConversationEnable ? conversation : true)}}"
class="tips">
{{refreshText}}
</view>
<!-- model 模式下的头像,只在 model 模式下展示 -->
<view wx:if="{{chatMode === 'model'}}" class="nav">
<image src="{{modelConfig.logo}}" mode="aspectFill" class="avatar" />
<view style="line-height: 47px; font-size: 20px; font-weight: 500;">{{modelConfig.modelProvider}}</view>
<view style="line-height: 26px;padding: 0px 16px; font-size: 32rpx;">{{modelConfig.welcomeMsg}}</view>
</view>
<block wx-if="{{!isAgent}}" wx:for="{{chatRecords}}" wx:key="record_id">
<!-- 系统聊天 -->
<view class="system" style="padding-left: {{showBotAvatar?80:0}}rpx;" wx:if="{{item.role==='assistant'}}">
<view class="avatar-left" wx:if="{{showBotAvatar}}">
<image src="{{chatMode==='bot'?bot.avatar:modelConfig.logo}}" mode="aspectFill"
style="width: 56rpx;height: 56rpx; border-radius: 28rpx;" />
</view>
<view>
<!-- 最后一条消息,并且是发送状态显示发送中 -->
<block wx:if="{{(chatRecords.length-1)===index&&chatStatus===1}}">
<view style="display: flex;align-items: center; gap: 4px; font-size: 32rpx;line-height: 1.8;">
<image src="./imgs/loading.svg" mode="aspectFill" style="width: 14px;height: 14px;" /> 请稍等,正在卖力思考中 🤔
</view>
</block>
<block wx:else>
<!-- 数据库检索 -->
<view wx:if="{{item.db_len}}"
style="border-radius: 8px;margin-bottom: 12px;background-color: #f5f5f5;padding: 18rpx 26rpx;display: inline-block;opacity: 0.7;font-size: 14px;">
已匹配 {{item.db_len}} 张数据表
</view>
<!-- 联网搜索 -->
<FoldedCard wx:if="{{item.search_info && item.search_info.search_results}}" initStatus="{{false}}"
showBgColor="{{true}}">
<view slot="title" style="opacity: 0.7;font-size: 14px;display: flex; align-items: center; gap: 8px;">
<image src="./imgs/search.svg" mode="aspectFill" style="width: 36rpx;height: 36rpx;" />
<text>已参考 {{item.search_info.search_results.length}} 个网页</text>
</view>
<view slot="content" class="link-box">
<block wx:for="{{item.search_info.search_results}}" wx:key="index">
<view bind:tap="copyUrl" data-url="{{item.url}}"
style="margin-bottom: 3px; font-size: 14px;color: rgb(0, 82, 217); line-height: 24px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;">
{{index+1}}.{{item.title}}
</view>
</block>
</view>
</FoldedCard>
<!-- 知识库 -->
<view wx:if="{{item.knowledge_base&&item.knowledge_base.length}}"
style="border-radius: 8px;margin-bottom: 12px;background-color: #f5f5f5;padding: 18rpx 26rpx;display: inline-block;opacity: 0.7;font-size: 14px;">
已参考 {{item.knowledge_base.length}} 处知识库内容
</view>
<!-- 推理过程 -->
<FoldedCard wx:if="{{!!item.reasoning_content}}" initStatus="{{true}}" showBgColor="{{false}}">
<view slot="title"
style="opacity: 0.7;font-size: 14px; display: flex; align-items: center; gap: 8px;">
<image src="./imgs/system-sum.svg" mode="aspectFill" style="width: 36rpx;height: 36rpx;" />
<block wx:if="{{item.pauseThinking}}">
已停止思考
</block>
<block wx:else>
<text>{{item.reasoning_content&&!item.content?"思考中...":"已深度思考(用时"+item.thinkingTime+"秒)"}}</text>
</block>
</view>
<view style="padding-left: 25rpx;margin-top: 28rpx; border-left: rgba(0,0,0,0.14) solid 2px ;"
slot="content">
<!-- <markdownPreview markdown="{{item.reasoning_content||''}}" fontSize="{{28}}"></markdownPreview> -->
<text user-select="{{true}}"
style="font-size: 14px;line-height: 1.75;color: #8b8b8b">{{item.reasoning_content||''}}</text>
</view>
</FoldedCard>
<!-- 工具调用 -->
<view wx:if="{{item.toolCallList && item.toolCallList.length > 0}}">
<block wx:for="{{item.toolCallList}}" wx:for-item="subItem" wx:key="id">
<markdownPreview markdown="{{subItem.content || ''}}"></markdownPreview>
<FoldedCard showExpandIcon="{{showToolCallDetail}}" initStatus="{{false}}" showBgColor="{{false}}">
<view slot="title"
style="opacity: 0.7;font-size: 14px; display: flex; align-items: center; gap: 8px;">
<block>
调用工具 {{subItem.name}}
<image wx:if="{{!subItem.callResult && !subItem.error}}" src="./imgs/loading.svg"
mode="aspectFill" style="width: 14px;height: 14px;" />
<image wx:if="{{subItem.callResult}}" mode="widthFix" src='./imgs/check.svg'
style="width: 36rpx; height: 36rpx;vertical-align: top;" bind:tap="share" />
<image wx:if="{{subItem.error}}" mode="widthFix" src='./imgs/close-red.svg'
style="width: 36rpx; height: 36rpx;vertical-align: top;" bind:tap="share" />
</block>
<!-- <block wx:else>
<text>{{item.reasoning_content&&!item.content?"思考中...":"已深度思考(用时"+item.thinkingTime+"秒)"}}</text>
</block> -->
</view>
<view wx:if="{{showToolCallDetail}}"
style="padding-left: 25rpx;margin-top: 28rpx; border-left: rgb(165, 164, 164) solid 2px; opacity: 0.7;"
slot="content">
<view>参数:</view>
<markdownPreview markdown="{{subItem.callParams||''}}" fontSize="{{28}}"></markdownPreview>
<view>结果:</view>
<markdownPreview markdown="{{subItem.callResult||''}}" fontSize="{{28}}"></markdownPreview>
</view>
</FoldedCard>
<customCard wx:if="{{subItem.rawResult}}" name="{{subItem.name}}" toolParams="{{subItem.rawParams}}"
toolData="{{subItem.rawResult}}"></customCard>
</block>
</view>
<!-- 正文 -->
<markdownPreview markdown="{{item.content||''}}"></markdownPreview>
<!-- 下面的按钮 -->
<view style="display: flex; gap: 10px;justify-content: flex;" wx:if="{{!item.hiddenBtnGround}}">
<image wx:if="{{item.error}}" mode="widthFix" bind:tap="showErrorMsg" src='./imgs/error-circle.svg'
class="tool_btn" data-content="{{item.error}}" data-reqid="{{item.reqId}}" />
<image mode="widthFix" bind:tap="copyChatRecord" src='./imgs/copy.svg' class="tool_btn"
data-content="{{item.content}}" />
<block wx:if="{{!item.error}}">
<button class="share_btn" open-type="share">
<image mode="widthFix" src='./imgs/share.svg' class="tool_btn" style="vertical-align: top;"
bind:tap="share" />
</button>
<block wx:if="{{chatMode=== 'bot'}}">
<image mode="widthFix" bind:tap="openFeedback" data-feedbackType="upvote"
data-feedbackRecordId="{{item.record_id}}" src='./imgs/thumb-up.svg' class="tool_btn" />
<image mode="widthFix" bind:tap="openFeedback" data-feedbackType="downvote"
data-feedbackRecordId="{{item.record_id}}" src='./imgs/thumb-down.svg' class="tool_btn" />
<block wx:if="{{item.record_id}}">
<image wx:if="{{audioContext.recordId !== item.record_id || audioContext.playStatus === 0}}"
mode="widthFix" bind:tap="handlePlayAudio" data-content="{{item.content}}"
data-recordId="{{item.record_id}}" src='./imgs/sound.svg' class="tool_btn" />
<image wx:elif="{{audioContext.playStatus === 1}}" mode="widthFix" src='./imgs/loading.svg'
class="tool_btn" />
<view wx:else class="playing_btn">
<image style="width: 36rpx;height: 36rpx;" mode="widthFix" bind:tap="handlePauseAudio"
data-recordId="{{item.record_id}}" src='./imgs/pause.svg' />
<image style="width: 30rpx;height: 30rpx" src="./imgs/playing.svg" mode="widthFix" />
<!-- 倍速切换按钮 -->
<view class="speed-switch" bindtap="toggleSpeedList" data-recordId="{{item.record_id}}">
<text class="speed-label">{{audioContext.currentSpeed || '1'}}</text>X
</view>
<!-- 倍速弹窗 -->
<view wx:if="{{audioContext.showSpeedList && audioContext.recordId === item.record_id}}"
class="speed-popup">
<view wx:for="{{speedList}}" wx:key="item" class="speed-option" bindtap="chooseSpeed"
data-speed="{{item}}" data-recordId="{{item.record_id}}">
<text>{{item}}X</text>
<image wx:if="{{audioContext.currentSpeed === item}}" src="./imgs/check.svg"
style="width: 24rpx;height: 24rpx;margin-left:8rpx;" />
</view>
</view>
</view>
</block>
</block>
</block>
</view>
<image wx:if="{{(chatRecords.length - 1) === index && (chatStatus === 2 || chatStatus === 3)}}"
mode="widthFix" src='./imgs/loading.svg' style="width: 14px;height: 14px;" />
</block>
</view>
</view>
<!-- 用户输入 -->
<view class="userContent" wx:if="{{item.role==='user'}}">
<view class="user" style="padding-left: {{showBotAvatar?80:0}}rpx;display: flex;">
<view class="user_content" bind:longpress="handleLongPress" data-content="{{item.content}}"
data-id="{{item.record_id}}">
{{item.content}}
<!-- 长按菜单 -->
<view class="operation-menu" wx:if="{{showMenu && tapMenuRecordId === item.record_id}}">
<view class="menu-item" bind:tap="handleCopyAll" data-content="{{item.content}}">
<image src="./imgs/copy.svg" class="menu-icon" />
<text>复制全文</text>
</view>
<view class="menu-item" bind:tap="handleEdit" data-content="{{item.content}}">
<image src="./imgs/edit.svg" class="menu-icon" />
<text>修改</text>
</view>
</view>
</view>
</view>
<view class="fileBar">
<chatFile enableDel="{{false}}" wx:for="{{item.fileList}}" wx:for-item="innerItem" wx:key="tempPath"
fileData="{{innerItem}}" bind:removeChild="handleRemoveChild" bind:changeChild="handleChangeChild">
</chatFile>
</view>
</view>
</block>
<!-- agentV2 聊天列表 -->
<block wx:if="{{isAgent}}" wx:for="{{messages}}" wx:key="id">
<view class="userContent" wx:if="{{item.role==='user'}}">
<view class="user">
<view class="user_content"> {{item.content}}</view>
</view>
</view>
<view class="system" wx:if="{{item.role==='assistant'}}">
<!-- 渲染 parts -->
<block wx:for="{{item.parts}}" wx:for-item="part" wx:key="id">
<block wx:if="{{part.type==='text'}}">
<markdownPreview markdown="{{part.content||''}}"></markdownPreview>
</block>
<block wx:if="{{part.type==='tool_call'}}">
<tool tool-name="{{part.toolCallName}}" tool-status="{{part.status}}" tool-params="{{part.arguments}}"
toolResult="{{part.result}}">
</tool>
</block>
<block wx:if="{{part.type==='error'}}">
<view>{{part.content||''}}</view>
</block>
</block>
</view>
</block>
<!-- 加载图标 -->
<view wx:if="{{isAgent&&chatStatus!=0}}">
<image src="./imgs/loading.svg" mode="aspectFill" style="width: 14px;height: 14px; margin-left: 32rpx;" />
</view>
<!-- 推荐问题,只在 bot 模式下展示 -->
<block wx-if="{{chatMode==='bot'&&!isAgent}}" wx:for="{{questions}}" wx:key="item">
<view class="questions" style="padding-left: {{showBotAvatar?80:0}}rpx;">
<view class="question_content" bind:tap="handleSendMessage" data-message="{{item}}">{{item}}</view>
</view>
</block>
</view>
<view id="scroll-bottom" style="width: 100%;height: 20px;"></view>
</scroll-view>
<!-- 页面不在底部时候的滚动到底按钮 -->
<image bind:tap="autoToBottom" wx:if="{{manualScroll&&!isAgent}}"
style="width:28px;height:28px;border-radius: 50px;position: absolute;bottom:150px;right: 20px;padding: 5px;background-color: white;box-shadow: rgba(99, 99, 99, 0.2) 0px 2px 8px 0px;"
src="./imgs/toBottom.svg" mode="aspectFit" binderror="" bindload="" />
</view>
<!-- 底部输入区 -->
<view class="footer">
<view class="{{ showFileList ? 'no_feature_list' : 'feature_list'}}" wx:if="{{showFeatureList}}">
<view bind:tap="handleClickWebSearch" class="{{'webSearchSwitch ' + (useWebSearch ? 'feature_enable' : '')}}">
<image src="{{ useWebSearch ? './imgs/internetUse.svg' : './imgs/internet.svg'}}" mode=""
style="width: 40rpx;height:30px;margin-right: 10rpx;" />
<text style="color: {{useWebSearch ? 'rgb(77, 107, 254)' : 'rgb(95, 114, 146)'}}">联网搜索</text>
</view>
</view>
<view class="file_list" wx:if="{{showFileList}}">
<chatFile enableDel="{{true}}" wx:for="{{sendFileList}}" wx:key="tempId" fileData="{{item}}"
bind:removeChild="handleRemoveChild" bind:changeChild="handleChangeChild"></chatFile>
</view>
<view class="foot_function">
<view class="input_box">
<view class="left_btns" wx:if="{{showVoice&&!isAgent}}">
<image wx:if="{{!useVoice}}" src="./imgs/voice.svg" class="set" mode="widthFix"
bind:tap="handleChangeInputType" />
<image wx:else src="./imgs/keyboard.svg" class="set" mode="widthFix" bind:tap="handleChangeInputType" />
</view>
<view hidden="{{useVoice}}" class="input_inner_box">
<textarea class="input" value="{{inputValue}}" maxlength="1024" bindfocus="bindInputFocus"
bindinput="bindKeyInput" placeholder="说点什么吧" bindconfirm="handleSendMessage" confirm-type="send"
adjust-position cursor-spacing="40" auto-height="{{true}}" show-confirm-bar="{{false}}"
bindlinechange="handleLineChange" />
</view>
<text
style="position: absolute;top: -50%;left: 50%;transform: translateX(-50%);font-size: 12px;color: {{sendStatus === 2 ? '#e84f50;' : ''}}">{{sendStatus === 1 ? "松开发送,上滑取消" : (sendStatus === 2 ? "松开取消" : "")}}</text>
<view hidden="{{!useVoice}}" bindtouchstart="handleTouchStart" bindtouchmove="handleTouchMove"
bindtouchend="handleTouchEnd" class="input_inner_box"
style="position: absolute;width: calc(100% - 136rpx);left: 50%;transform: translateX(-50%);opacity: 0;">
</view>
<view hidden="{{!useVoice}}" class="input_inner_box say_box"
style="background-color: {{sendStatus === 1 ? '#e9f6ef' : (sendStatus === 2 ? '#f8ecea' : '')}};"><text
wx:if="{{!longPressTriggered}}">{{voiceRecognizing ? '识别中' : '按住 说话'}}</text>
<image wx:else
src="{{ sendStatus === 1 ? './imgs/sendSaying.svg' : (sendStatus === 2 ? './imgs/cancelSaying.svg' : '')}}"
class="set" mode="widthFix" />
</view>
<view class="right_btns">
<!-- 加号 -->
<image src="./imgs/set.svg" class="set" mode="widthFix" bind:tap="handleClickTools" />
<!-- 发送按钮 -->
<view wx:if="{{!!inputValue&&chatStatus===0}}" class="set"
style="display: flex;justify-content: center;align-items: center;background-color: #436af4;border-radius: 50px;">
<image src="./imgs/send.svg" class="send-set" mode="widthFix" bind:tap="handleSendMessage"
style="transform-origin: 8px 8px;" />
</view>
<!-- 暂停按钮 -->
<image src="./imgs/stop.svg" class="set" mode="widthFix" wx:if="{{!(chatStatus===0)}}" bind:tap="stop" />
</view>
</view>
</view>
<!-- 底部工具栏 -->
<view class="tool_box" wx:if="{{showTools}}">
<view class="function" bind:tap="handleTapClear">
<image src="./imgs/clear.svg" alt="widthFix" class="icon" />
<text class="text_desc">清除</text>
</view>
<view wx:if="{{showUploadFile && chatMode === 'bot'&&!isAgent}}" class="function" bind:tap="handleUploadMessageFile">
<image src="./imgs/wechat.svg" alt="widthFix" class="icon" />
<text class="text_desc">微信文件</text>
</view>
<view wx:if="{{showUploadImg && chatMode === 'bot'&&!isAgent}}" class="function" bind:tap="handleAlbum">
<image src="./imgs/uploadImg.svg" alt="widthFix" class="icon" />
<text class="text_desc">图片</text>
</view>
<view wx:if="{{showUploadImg && chatMode === 'bot'&&!isAgent}}" class="function" bind:tap="handleCamera">
<image src="./imgs/camera.svg" alt="widthFix" class="icon" />
<text class="text_desc">相机</text>
</view>
</view>
</view>
<feedback input="{{input}}" aiAnswer="{{aiAnswer}}" isShowFeedback="{{isShowFeedback}}" bind:close="closefeedback"
feedbackRecordId="{{feedbackRecordId}}" feedbackType="{{feedbackType}}" botId="{{bot.botId}}"></feedback>
<!-- 底部操作菜单弹窗 -->
<view class="action-menu-modal" wx:if="{{showActionMenu}}" bind:tap="hideActionMenu">
<view class="action-menu" catchtap="">
<view class="action-item" bind:tap="handleDeleteConversation" data-conversation="{{selectedConversation}}">
删除
</view>
<view class="action-item cancel-item" bind:tap="hideActionMenu">
取消
</view>
</view>
</view>
</view>

View File

@ -0,0 +1,730 @@
/* components/agent-ui/index.wxss */
.agent-ui {
width: 750rpx;
height: 100vh;
position: relative;
display: flex;
flex-direction: column;
overflow:hidden;
color: #333;
background-color: #fff;
overflow: hidden;
touch-action: none; /* 增强禁止滚动效果 */
}
.showBotName {
height: 62px;
}
.hiddenBotName {
margin-top: 2px;
margin-bottom: 2px;
}
.nav {
width: 750rpx;
padding: 20px 0px 0px 0px;
display: flex;
flex-direction: column;
align-items: center;
flex-shrink: 0;
}
.navBar {
width: 100%;
box-shadow: 0 16px 16px #fff;
}
.tips {
display: flex;
align-items: center;
gap: 12px;
width: 100%;
color: rgb(128, 128, 128);
font-size: 12px;
height: 32px;
margin-bottom: 16px;
}
.tips::before,
.tips::after {
content: '';
display: inline-block;
height: 1px;
transform: scaleY(.5);
flex-grow: 1;
border-radius: 2px;
}
.tips::before {
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5));
}
.tips::after {
background-image: linear-gradient(to left, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.5));
}
.nav-content {
/* height:62px; */
display: flex;
align-items: center;
justify-content: space-around;
gap: 12px;
}
.bot-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
border: 2px solid rgba(255, 255, 255, 0.8);
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
.bot-name {
font-size: 18px;
font-weight: 500;
color: #333;
}
.main {
background-color: #fff;
flex-grow: 1;
position: relative;
}
.share_btn {
background-color: #fff;
margin: 0px !important;
padding: 0rpx !important;
width: 64rpx !important;
height: 64rpx;
border: none !important;
}
.avatar {
width: 160rpx;
height: 160rpx;
border-radius: 75rpx;
}
.questions {
margin: 0px 16px 10px 16px;
}
.question_content {
background-color: #f5f5f5;
padding: 16rpx 24rpx;
border-radius: 12px;
display: inline-block;
font-size: 14px;
font-weight: 300;
}
.footer {
width: 100%;
min-height: 65px;
max-height: 380px;
flex-shrink: 0;
position: relative;
padding: 0px 16rpx 24px;
box-sizing: border-box;
}
.footer .file_list {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
gap: 16rpx;
overflow-x: scroll;
padding: 20rpx 0px;
}
.img-box {
position: absolute;
top: -100px;
left: 0px;
white-space: nowrap;
width: 100%;
background-color: #fff;
}
.img-preview {
display: inline-block;
width: 80px;
height: 80px;
margin-right: 8px;
position: relative;
margin-top: 10px;
}
.img-preview-image {
width: 80px;
height: 80px;
border-radius: 10px;
}
.img-preview-loading {
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
background-color: #eee;
border-radius: 10px;
}
.img-preview-close {
width: 16px;
height: 16px;
position: absolute;
right: -8px;
top: -8px;
}
.input_box {
display: flex;
align-items: flex-end;
flex-direction: row;
gap: 10rpx;
position: relative;
min-height: 40px;
padding: 0px 0px;
background-color: white;
transition: all 0.3s;
}
.set_panel_modal {
position: fixed;
width: 750rpx;
height: 100vh;
left: 0px;
top: 0px;
background-color: rgba(0, 0, 0, 0.7);
z-index: 1000;
}
.set_panel {
background-color: #f3f3f3;
position: absolute;
left: 0px;
bottom: 0px;
width: 750rpx;
}
.set_panel_funtion {
display: flex;
flex-direction: row;
padding: 10px 16px;
box-sizing: border-box;
gap: 10px;
}
.set_panel_cancel {
height: 60px;
text-align: center;
line-height: 40px;
color: black;
border-top: #cfcdcd solid 1px;
}
.function {
display: flex;
width: 150rpx;
flex-direction: column;
justify-content: center;
align-items: center;
gap: 8px;
background-color: #f3f4f6;
color: black;
padding: 12px 6px;
border-radius: 16px;
}
.icon {
width: 48rpx;
height: 48rpx;
}
.text_desc {
font-weight: 300;
font-size: 24rpx;
color: rgb(95, 114, 146);
}
.input_inner_box {
width: 100%;
min-height: 54px;
display: flex;
align-items: center;
border: #f3f3f3 solid 1px;
border-radius: 16px;
box-sizing: border-box;
background-color: #f3f4f6;
}
.say_box {
font-weight: bold;
justify-content: center;
}
.input {
padding: 8px;
color: black;
width: 100%;
flex: 1;
max-height: 160px;
font-size: 16px;
}
.say_btn {
width: 100%;
height: 100%;
}
.right_btns {
height: 50px;
display: flex;
align-items: center;
gap: 10rpx;
}
.left_btns {
height: 50px;
display: flex;
align-items: center;
gap: 10rpx;
}
.set {
width: 58rpx;
height: 58rpx;
}
.send-set {
width: 38rpx;
height: 38rpx;
}
.system {
margin-left: 24rpx;
margin-right: 24rpx;
border-radius: 12rpx;
margin-top: 12px;
padding-bottom: 16px;
box-sizing: border-box;
position: relative;
}
.avatar-left{
position:absolute;
top: 0px;
left: 0px;
}
.guide_system {
padding-left: 32rpx;
padding-right: 32rpx;
border-radius: 12rpx;
padding-bottom: 16px;
box-sizing: border-box;
}
.bot_intro_system {
padding-left: 32rpx;
padding-right: 32rpx;
border-radius: 12rpx;
padding-bottom: 16px;
box-sizing: border-box;
}
.user {
display: flex;
justify-content: flex-end;
}
.userContent {
margin-top: 12px;
padding-bottom: 16px;
}
.userContent .fileBar {
display: flex;
flex-direction: row;
flex-direction: row-reverse;
flex-wrap: nowrap;
padding: 0px 16px;
overflow-x: scroll;
max-height: 80px;
gap: 10px;
margin-top: 10px;
}
.user .user_content {
background-color: #f3f5fb;
border-radius: 12rpx 0rpx 12rpx 12rpx;
margin-left: 32rpx;
margin-right: 32rpx;
padding: 24rpx;
word-wrap: break-word;
word-break: break-all;
font-size: 32rpx;
position: relative;
}
.operation-menu {
position: absolute;
bottom: -120rpx;
left: 0;
background: rgba(0, 0, 0, 1);
border-radius: 8rpx;
display: flex;
padding: 16rpx 24rpx;
gap: 32rpx;
z-index: 100;
}
/* 添加三角形指示器 */
.operation-menu::before {
content: '';
position: absolute;
top: -16rpx; /* 调整三角形位置 */
left: 30rpx; /* 调整三角形的水平位置,使其指向文本 */
border-left: 16rpx solid transparent;
border-right: 16rpx solid transparent;
border-bottom: 16rpx solid rgba(0, 0, 0, 0.8);
width: 0;
height: 0;
}
.menu-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 8rpx;
}
.menu-item text {
color: #ffffff;
font-size: 24rpx;
}
.menu-icon {
width: 36rpx;
height: 36rpx;
filter: brightness(0) invert(1);
}
.feedback_modal {
position: fixed;
top: 0px;
left: 0px;
width: 750rpx;
height: 100vh;
background-color: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal {
background-color: #fff;
width: 700rpx;
border-radius: 16rpx;
overflow: hidden;
}
.modal_head {
height: 40px;
line-height: 40px;
padding: 0px 10px;
}
.modal_body {
padding: 10px;
}
.modal_footer {
display: flex;
}
.link-box {
padding: 0px 16px 6px 16px;
}
.tool_box {
display: flex;
flex-direction: row;
box-sizing: border-box;
gap: 20rpx;
justify-content: flex-start;
flex-wrap: nowrap;
overflow-x: scroll;
padding: 20rpx 0rpx 0rpx;
}
.webSearchSwitch {
width: 200rpx;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
border-radius: 25px;
border: 1px solid rgba(0, 0, 0, 0.08);
font-size: 14px;
background-color: #fff;
}
.feature_enable {
background-color: rgb(219, 234, 254);
color: rgb(77, 107, 254);
border-color: rgba(0, 122, 255, 0.15);
}
.feature_list {
position: absolute;
background-color: transparent;
bottom: calc(100% + 20rpx);
}
.no_feature_list {
position: absolute;
background-color: transparent;
bottom: calc(100%);
}
/* 抽屉遮罩层 */
.drawer-mask {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
z-index: 998;
opacity: 0;
visibility: hidden;
transition: all 0.3s ease;
}
.drawer-mask.show {
opacity: 1;
visibility: visible;
}
/* 抽屉主体 */
.drawer {
position: fixed;
top: 0;
left: -80%;
width: 80%;
height: 100vh;
background: #f9fbff;
z-index: 999;
transition: all 0.3s ease;
display: flex;
flex-direction: column;
}
.drawer.show {
left: 0;
}
.drawer-header {
padding: 16rpx 32rpx 16rpx;
display: flex;
justify-content: space-between;
align-items: center;
}
.close-icon {
width: 24px;
height: 24px;
}
.drawer-content {
flex: 1;
display: flex;
flex-direction: column;
overflow: hidden; /* 防止内容溢出 */
height: 0;
margin-bottom: 20px;
margin-left:32rpx;
margin-right:32rpx;
}
.con-icon {
width: 24px;
height: 24px;
margin-left: 16rpx;
margin-right: 16rpx;
}
.create-new-chat {
border-radius: 8px;
background: #dee9fc;
color: #4d6bfe;
cursor: pointer;
padding: 16rpx 24rpx;
display: flex;
justify-content: center;
align-items: center;
}
.date-title {
font-size: 16px;
color: rgb(128, 128, 128);
font-weight: 400;
}
.con-container {
margin-top: 12px;
}
.con-block {
margin-top: 16px;
}
.con-item {
padding: 12px 8px;
margin-bottom: 2px;
border-radius: 8px;
}
.con-item:active {
transition: filter 0.4s;
cursor: pointer;
background-color: rgb(249, 251, 255);
filter: brightness(0.95);
}
.selected-con {
background-color: rgb(249, 251, 255);
filter: brightness(95%);
transition: filter 0.4s;
}
.tool_btn {
width: 36rpx;
height: 36rpx;
padding: 10rpx;
border: 1rpx solid #cfcdcd;
border-radius: 14rpx;
}
.playing_btn {
height: 36rpx;
padding: 10rpx;
border: 1rpx solid #cfcdcd;
border-radius: 14rpx;
display: flex;
align-items: center;
gap: 10rpx;
position: relative;
}
.speed-switch {
display: flex;
align-items: center;
margin-left: 0rpx;
padding: 4rpx 12rpx;
border-radius: 20rpx;
/* background: #f5f5f7; */
font-size: 26rpx;
color: #222;
cursor: pointer;
}
.speed-label {
margin-left: 6rpx;
}
.speed-popup {
position: absolute;
bottom: 48rpx;
right: 0;
background: #fff;
border-radius: 12rpx;
box-shadow: 0 4rpx 16rpx rgba(0,0,0,0.08);
z-index: 99;
padding: 8rpx 0;
min-width: 80rpx;
}
.speed-option {
padding: 16rpx 32rpx;
font-size: 28rpx;
color: #222;
display: flex;
align-items: center;
justify-content: flex-start;
}
.speed-option:active {
background: #f0f0f0;
}
/* 底部操作菜单弹窗 */
.action-menu-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.4);
z-index: 1001;
display: flex;
flex-direction: column;
justify-content: flex-end;
animation: fadeIn 0.3s ease-out;
}
.action-menu {
background: #ffffff;
border-radius: 24rpx 24rpx 0 0;
overflow: hidden;
animation: slideUp 0.3s ease-out;
margin: 0 20rpx 20rpx 20rpx;
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.1);
}
.action-item {
padding: 32rpx 0;
text-align: center;
font-size: 32rpx;
color: #333333;
background: #ffffff;
border-bottom: 1rpx solid #f0f0f0;
position: relative;
}
.action-item:last-child {
border-bottom: none;
}
.action-item:active {
background: #f8f8f8;
}
.cancel-item {
margin-top: 20rpx;
border-radius: 24rpx;
border-bottom: none;
color: #666666;
}
/* 动画效果 */
@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slideUp {
from {
transform: translateY(100%);
}
to {
transform: translateY(0);
}
}

View File

@ -0,0 +1,2 @@
!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d(function(n,t){return n<<t|n>>>32-t}(d(d(t,n),d(e,u)),o),r)}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function i(n,t){var r,e,o,u,c;n[t>>5]|=128<<t%32,n[14+(t+64>>>9<<4)]=t;var f=1732584193,i=-271733879,a=-1732584194,h=271733878;for(r=0;r<n.length;r+=16)i=m(i=m(i=m(i=m(i=v(i=v(i=v(i=v(i=g(i=g(i=g(i=g(i=l(i=l(i=l(i=l(o=i,a=l(u=a,h=l(c=h,f=l(e=f,i,a,h,n[r],7,-680876936),i,a,n[r+1],12,-389564586),f,i,n[r+2],17,606105819),h,f,n[r+3],22,-1044525330),a=l(a,h=l(h,f=l(f,i,a,h,n[r+4],7,-176418897),i,a,n[r+5],12,1200080426),f,i,n[r+6],17,-1473231341),h,f,n[r+7],22,-45705983),a=l(a,h=l(h,f=l(f,i,a,h,n[r+8],7,1770035416),i,a,n[r+9],12,-1958414417),f,i,n[r+10],17,-42063),h,f,n[r+11],22,-1990404162),a=l(a,h=l(h,f=l(f,i,a,h,n[r+12],7,1804603682),i,a,n[r+13],12,-40341101),f,i,n[r+14],17,-1502002290),h,f,n[r+15],22,1236535329),a=g(a,h=g(h,f=g(f,i,a,h,n[r+1],5,-165796510),i,a,n[r+6],9,-1069501632),f,i,n[r+11],14,643717713),h,f,n[r],20,-373897302),a=g(a,h=g(h,f=g(f,i,a,h,n[r+5],5,-701558691),i,a,n[r+10],9,38016083),f,i,n[r+15],14,-660478335),h,f,n[r+4],20,-405537848),a=g(a,h=g(h,f=g(f,i,a,h,n[r+9],5,568446438),i,a,n[r+14],9,-1019803690),f,i,n[r+3],14,-187363961),h,f,n[r+8],20,1163531501),a=g(a,h=g(h,f=g(f,i,a,h,n[r+13],5,-1444681467),i,a,n[r+2],9,-51403784),f,i,n[r+7],14,1735328473),h,f,n[r+12],20,-1926607734),a=v(a,h=v(h,f=v(f,i,a,h,n[r+5],4,-378558),i,a,n[r+8],11,-2022574463),f,i,n[r+11],16,1839030562),h,f,n[r+14],23,-35309556),a=v(a,h=v(h,f=v(f,i,a,h,n[r+1],4,-1530992060),i,a,n[r+4],11,1272893353),f,i,n[r+7],16,-155497632),h,f,n[r+10],23,-1094730640),a=v(a,h=v(h,f=v(f,i,a,h,n[r+13],4,681279174),i,a,n[r],11,-358537222),f,i,n[r+3],16,-722521979),h,f,n[r+6],23,76029189),a=v(a,h=v(h,f=v(f,i,a,h,n[r+9],4,-640364487),i,a,n[r+12],11,-421815835),f,i,n[r+15],16,530742520),h,f,n[r+2],23,-995338651),a=m(a,h=m(h,f=m(f,i,a,h,n[r],6,-198630844),i,a,n[r+7],10,1126891415),f,i,n[r+14],15,-1416354905),h,f,n[r+5],21,-57434055),a=m(a,h=m(h,f=m(f,i,a,h,n[r+12],6,1700485571),i,a,n[r+3],10,-1894986606),f,i,n[r+10],15,-1051523),h,f,n[r+1],21,-2054922799),a=m(a,h=m(h,f=m(f,i,a,h,n[r+8],6,1873313359),i,a,n[r+15],10,-30611744),f,i,n[r+6],15,-1560198380),h,f,n[r+13],21,1309151649),a=m(a,h=m(h,f=m(f,i,a,h,n[r+4],6,-145523070),i,a,n[r+11],10,-1120210379),f,i,n[r+2],15,718787259),h,f,n[r+9],21,-343485551),f=d(f,e),i=d(i,o),a=d(a,u),h=d(h,c);return[f,i,a,h]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function h(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function e(n){var t,r,e="0123456789abcdef",o="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),o+=e.charAt(t>>>4&15)+e.charAt(15&t);return o}function r(n){return unescape(encodeURIComponent(n))}function o(n){return function(n){return a(i(h(n),8*n.length))}(r(n))}function u(n,t){return function(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,16<o.length&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}(r(n),r(t))}function t(n,t,r){return t?r?u(t,n):function(n,t){return e(u(n,t))}(t,n):r?o(n):function(n){return e(o(n))}(n)}"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:n.md5=t}(this);
//# sourceMappingURL=md5.min.js.map

View File

@ -0,0 +1,92 @@
Component({
/**
* 组件的属性列表
*/
properties: {
// 工具名称
toolName: {
type: String,
value: "",
},
// 工具状态success/failed/running
toolStatus: {
type: String,
value: "success",
},
// 工具参数
toolParams: {
type: String,
value: "",
},
toolResult: {
type: String,
value: "",
},
// 是否默认展开
defaultExpanded: {
type: Boolean,
value: false,
},
},
/**
* 组件的初始数据
*/
data: {
isExpanded: false,
parsedParams: "", // 解析后的参数对象
parsedResult: "", // 解析后的结果对象
},
observers: {
toolParams: function (toolParams) {
if (toolParams) {
try {
const parsed = JSON.stringify(JSON.parse(toolParams), null, 2);
console.log(parsed);
this.setData({ parsedParams: parsed });
} catch (e) {
// 解析失败返回原字符串
this.setData({ parsedParams: toolParams });
}
} else {
this.setData({ parsedParams: "" });
}
},
toolResult: function (toolResult) {
if (toolResult) {
try {
const parsed = JSON.stringify(JSON.parse(toolResult), null, 2);
console.log(parsed);
this.setData({ parsedResult: parsed });
} catch (e) {
// 解析失败返回原字符串
this.setData({ parsedResult: toolResult });
}
} else {
this.setData({ parsedResult: "" });
}
},
},
/**
* 组件的方法列表
*/
methods: {
// 切换展开/收起
toggleExpand() {
this.setData({
isExpanded: !this.data.isExpanded,
});
},
},
/**
* 生命周期函数
*/
attached() {
// 初始化展开状态
this.setData({
isExpanded: this.properties.defaultExpanded,
});
},
});

View File

@ -0,0 +1,5 @@
{
"component": true,
"usingComponents": {
}
}

View File

@ -0,0 +1,17 @@
<view class="tool">
<view class="header" bind:tap="toggleExpand">
<image wx:if="{{toolStatus==='running'}}" class="icon" src="../imgs/loading.svg" mode="aspectFill" />
<image wx:if="{{toolStatus==='success'}}" class="icon" src="../imgs/check.svg" mode="aspectFill" />
<image wx:if="{{toolStatus==='failed'}}" class="icon" src="../imgs/close-red.svg" mode="aspectFill" />
<view class="title">调用工具:{{toolName}}</view>
<image class="arrow" style="transform: rotate({{isExpanded?0:-90}}deg);" src="../imgs/arrow.svg"
mode="aspectFill" />
</view>
<view class="content" style='display: {{isExpanded?"block":"none"}}'>
<view class="content-title">参数:</view>
<view>{{parsedParams}}</view>
<view class="divider"></view>
<view class="content-title">调用结果:</view>
<view>{{parsedResult}}</view>
</view>
</view>

View File

@ -0,0 +1,45 @@
.tool {
background-color: #f5f5f5;
border-radius: 10rpx;
overflow: hidden;
margin-bottom: 10rpx;
}
.header {
display: flex;
align-items: center;
padding: 20rpx;
}
.title {
flex: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.icon {
width: 48rpx;
height: 48rpx;
margin-right: 10px;
}
.arrow {
width: 48rpx;
height: 48rpx;
margin-left: 10rpx;
}
.content {
background-color: #333333;
padding: 20rpx;
color: #f5f5f5;
white-space: pre-wrap;
font-family: monospace;
}
.content-title{
margin-bottom: 10rpx;
}
.divider{
height: 20px;
}

View File

@ -0,0 +1,141 @@
export const checkConfig = (chatMode, agentConfig, modelConfig) => {
const { botId } = agentConfig || {};
const { modelProvider, quickResponseModel, deepReasoningModel } = modelConfig || {};
// 检测不在微信环境,提示用户
const appBaseInfo = wx.getAppBaseInfo();
try {
const systemInfo = wx.getSystemInfoSync();
if (systemInfo.environment === "wxwork") {
return [false, "请前往微信客户端扫码打开小程序"];
}
} catch (e) {
if (appBaseInfo.host.env === "SDK") {
return [false, "请前往微信客户端扫码打开小程序"];
}
}
// 检测AI能力不存在提示用户
if (compareVersions(appBaseInfo.SDKVersion, "3.7.7") < 0) {
return [false, "使用AI能力需基础库为3.7.7及以上,请升级基础库版本或微信客户端"];
}
if (!["bot", "model"].includes(chatMode)) {
return [false, "chatMode 不正确值应为“bot”或“model”"];
}
if (chatMode === "bot" && !botId) {
return [false, "当前chatMode值为bot请配置botId"];
}
if (chatMode === "model" && (!modelProvider || !quickResponseModel)) {
return [false, "当前chatMode值为model请配置modelProvider和quickResponseModel"];
}
return [true, ""];
};
// 随机选取三个问题
export function randomSelectInitquestion(question = [], num = 3) {
if (question.length <= num) {
return [...question];
}
const set = new Set();
while (set.size < num) {
const randomIndex = Math.floor(Math.random() * question.length);
set.add(question[randomIndex]);
}
return Array.from(set);
}
export const getCloudInstance = (function () {
let cloudInstance = null;
return async function (envShareConfig) {
if (cloudInstance) {
return cloudInstance;
}
// 如果开启了环境共享走环境共享的ai实例
if (envShareConfig && envShareConfig.resourceAppid && envShareConfig.resourceEnv) {
let instance = new wx.cloud.Cloud({
// 资源方 AppID
resourceAppid: envShareConfig.resourceAppid,
// 资源方环境 ID
resourceEnv: envShareConfig.resourceEnv,
});
await instance.init();
// 烦环境共享时创建实例没有把环境id挂在instance上这里手动挂上去如果你发现instance上有个env那么这个insatnce就是环境共享的云开发实例
instance.env = envShareConfig.resourceEnv;
cloudInstance = instance;
return cloudInstance;
} else {
cloudInstance = wx.cloud;
return cloudInstance;
}
};
})();
export const compareVersions = (version1, version2) => {
const v1Parts = version1.split(".").map(Number);
const v2Parts = version2.split(".").map(Number);
const maxLength = Math.max(v1Parts.length, v2Parts.length);
for (let i = 0; i < maxLength; i++) {
const num1 = v1Parts[i] || 0;
const num2 = v2Parts[i] || 0;
if (num1 > num2) {
return 1;
} else if (num1 < num2) {
return -1;
}
}
return 0;
};
let isDomainWarn = false;
export const commonRequest = async (options) => {
const cloudInstance = await getCloudInstance();
const self = this;
// 判断 当前sdk 版本是否 小于 3.8.1
const appBaseInfo = wx.getAppBaseInfo();
const { path } = options;
if (compareVersions(appBaseInfo.SDKVersion, "3.8.1") < 0) {
console.log("走wx request");
const cloudInstance = await getCloudInstance();
const { token } = await cloudInstance.extend.AI.bot.tokenManager.getToken();
const envId = cloudInstance.env || cloudInstance.extend.AI.bot.context.env;
return wx.request({
...options,
path: undefined,
url: `https://${envId}.api.tcloudbasegateway.com/v1/aibot/${path}`,
header: {
...options.header,
Authorization: `Bearer ${token}`,
},
fail: (e) => {
if (options.fail) {
options.fail.bind(self)(e);
if (e.errno === 600002 || e.errMsg.includes("url not in domain list")) {
let msg = `请前往微信公众平台 request 合法域名配置中添加云开发域名 https://${envId}.api.tcloudbasegateway.com`;
if (!isDomainWarn) {
isDomainWarn = true;
wx.showModal({
title: "提示",
content: msg,
complete: () => {
isDomainWarn = false;
},
});
}
}
}
},
});
} else {
const ai = cloudInstance.extend.AI;
return ai.request(options);
}
};
export const sleep = (timeout) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve();
}, timeout);
});
};

View File

@ -0,0 +1,26 @@
Component({
options: {
virtualHost: true,
},
data: {
},
properties: {
dataClipboardText: {
type: String,
value: '',
},
},
methods: {
// 复制到剪贴板
copyClipBoard: function () {
wx.setClipboardData({
data: this.data.dataClipboardText,
// success() {
// wx.getClipboardData({
// success() {},
// });
// },
});
},
},
});

View File

@ -0,0 +1,6 @@
{
"component": true,
"styleIsolation": "shared",
"usingComponents": {
}
}

View File

@ -0,0 +1,3 @@
<view class="markdown-it-code-copy" bindtap="copyClipBoard">
<image src="../../imgs/copy.svg" style="width: 32rpx !important;height: 32rpx !important" mode="aspectFill" />
</view>

View File

@ -0,0 +1,9 @@
.markdown-it-code-copy {
position: absolute;
top: 7.5px;
right: 6px;
cursor: pointer;
outline: none;
}

View File

@ -0,0 +1,105 @@
import MarkdownIt from './utils/markdown-it.min.js';
import highlight from './utils/highlight.min.js';
import hljsJs from './utils/hljs_javascript.min.js';
import hljsCss from './utils/hljs_css.min.js';
import { addCustomClassPlugin,copy } from './utils/plugin'
Component({
options: {
virtualHost: true,
},
properties: {
className: {
type: String,
value: '',
},
style: {
type: String,
value: '',
},
id: {
type: String,
value: '',
},
markdown: {
type: String,
value: '',
},
fontSize: {
type: Number,
value: 32
},
options: {
type: Object,
value: {},
},
},
data: {
__html: '',
mdInstance: null,
},
methods: {
init() {
const { options } = this.data;
const hljs = highlight();
const javascript = hljsJs();
const css = hljsCss();
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('css', css);
const md = new MarkdownIt({
// 默认开启高亮
highlight: function (str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return (
'<pre class="_pre"><code class="hljs">' +
hljs.highlight(str, { language: lang, ignoreIllegals: true }).value +
'</code></pre>'
);
} catch (__) { }
}
return '<pre class="_pre"><code class="hljs">' + str + '</code></pre>';
},
...options,
});
// console.log(md.renderer.rules)
md.use(copy);
addCustomClassPlugin(md)
this.setData({ mdInstance: md });
this.triggerEvent('onReady', { markdownInstance: md });
this.setData({
__html: md.render(this.data.markdown),
});
},
updateWidgetAPI() {
this.setReadonlyAttributes &&
this.setReadonlyAttributes({
value: this.properties.markdown,
markdownInstance: this.data.mdInstance,
updateMarkdownInstance: ({ markdownInstance }) => this.setData({ mdInstance: markdownInstance }),
});
},
},
observers: {
markdown: function () {
const { mdInstance } = this.data;
if (!mdInstance) return;
const html = mdInstance.render(this.data.markdown)
this.setData({
__html: html,
});
},
options: function () {
this.init();
},
'markdown,mdInstance': function () {
this.updateWidgetAPI();
},
},
lifetimes: {
attached() {
this.init();
this.updateWidgetAPI();
},
},
});

View File

@ -0,0 +1,7 @@
{
"component": true,
"styleIsolation": "shared",
"usingComponents": {
"mp-html":"./mp-html/index"
}
}

View File

@ -0,0 +1,3 @@
<view class="wd-markdown" style="font-size: {{fontSize}}rpx;">
<mp-html content="{{__html}}" scroll-table="{{true}}" selectable="{{true}}"/>
</view>

View File

@ -0,0 +1,235 @@
/*
markdown 样式
*/
.wd-markdown {
word-wrap: break-word;
word-break: normal;
text-align: justify;
}
.wd-markdown ._p {
margin-bottom: 10rpx;
line-height: 1.8;
word-break: break-all;
}
.wd-markdown ._ol {
margin-bottom: 30rpx;
padding-left: 1.2em;
}
.wd-markdown ._ul {
margin-bottom: 30rpx;
padding-left: 1.2em;
}
.wd-markdown ._hr {
border: none;
border-top: 3px solid #eee;
margin-bottom: 10rpx;
}
.wd-markdown ._pre {
max-width: 100%;
padding: 32rpx;
overflow-x: auto;
background-color: rgb(246, 248, 250);
border-radius: 12rpx;
font-family: monospace;
font-size: 1em;
line-height: 1.14285em;
border-radius: 12rpx;
margin-bottom: 10rpx;
}
.wd-markdown ._h1 {
border-bottom-style: double;
border-bottom-width: 6rpx;
font-size: 42rpx;
padding-bottom: 10rpx;
margin-bottom: 20rpx;
}
.wd-markdown ._h2 {
border-bottom-style: solid;
border-bottom-width: 1rpx;
font-size: 40rpx;
padding-bottom: 8rpx;
margin-bottom: 18rpx;
}
.wd-markdown ._h3 {
font-size: 38rpx;
padding-bottom: 6rpx;
margin-bottom: 12rpx;
}
.wd-markdown ._h4 {
font-size: 36rpx;
padding-bottom: 4rpx;
margin-bottom: 12rpx;
}
.wd-markdown ._h5 {
font-size: 34rpx;
padding-bottom: 2rpx;
margin-bottom: 12rpx;
}
.wd-markdown ._h6 {
margin-bottom: 12rpx;
}
.wd-markdown ._a {
margin: 0 8rpx;
border-bottom-width: 1rpx;
border-bottom-style: solid;
line-height: 1;
color: #0000ee;
}
.wd-markdown ._blockquote {
margin: 0 0 10px;
padding: 15px 20px;
background-color: #f1f2f3;
border-left: 5px solid #ccc;
color: #666;
font-style: italic;
}
.wd-markdown ._tableParent {
width: 100%;
overflow-x: auto;
}
.wd-markdown ._table {
min-width: fit-content;
border-collapse: collapse;
margin: 0;
overflow: hidden;
}
.wd-markdown ._table ._th,
.wd-markdown ._table ._td {
box-sizing: border-box;
position: relative;
min-width: 70px;
padding: 0px 5px;
border: 1px solid #e1e6f0;
vertical-align: top;
background-clip: padding-box;
}
.wd-markdown ._table ._th {
font-weight: bold;
background-color: #f5f7fa;
}
.wd-markdown ._table ._td {
background-color: white;
}
.wd-markdown ._table ._th > ._p,
.wd-markdown ._table ._td > ._p {
min-height: 1em;
}
.wd-markdown image {
width: 480rpx !important;
height: 480rpx !important;
}
/*!
Theme: GitHub
Description: Light theme as seen on github.com
Author: github.com
Maintainer: @Hirse
Updated: 2021-05-15
Outdated base version: https://github.com/primer/github-syntax-light
Current colors taken from GitHub's CSS
*/
.hljs {
color: #24292e;
/* background: #ffffff; */
}
.hljs-doctag,
.hljs-keyword,
.hljs-meta .hljs-keyword,
.hljs-template-tag,
.hljs-template-variable,
.hljs-type,
.hljs-variable.language_ {
/* prettylights-syntax-keyword */
color: #d73a49;
}
.hljs-title,
.hljs-title.class_,
.hljs-title.class_.inherited__,
.hljs-title.function_ {
/* prettylights-syntax-entity */
color: #6f42c1;
}
.hljs-attr,
.hljs-attribute,
.hljs-literal,
.hljs-meta,
.hljs-number,
.hljs-operator,
.hljs-variable,
.hljs-selector-attr,
.hljs-selector-class,
.hljs-selector-id {
/* prettylights-syntax-constant */
color: #005cc5;
}
.hljs-regexp,
.hljs-string,
.hljs-meta .hljs-string {
/* prettylights-syntax-string */
color: #032f62;
}
.hljs-built_in,
.hljs-symbol {
/* prettylights-syntax-variable */
color: #e36209;
}
.hljs-comment,
.hljs-code,
.hljs-formula {
/* prettylights-syntax-comment */
color: #6a737d;
}
.hljs-name,
.hljs-quote,
.hljs-selector-tag,
.hljs-selector-pseudo {
/* prettylights-syntax-entity-tag */
color: #22863a;
}
.hljs-subst {
/* prettylights-syntax-storage-modifier-import */
color: #24292e;
}
.hljs-section {
/* prettylights-syntax-markup-heading */
color: #005cc5;
font-weight: bold;
}
.hljs-bullet {
/* prettylights-syntax-markup-list */
color: #735c0f;
}
.hljs-emphasis {
/* prettylights-syntax-markup-italic */
color: #24292e;
font-style: italic;
}
.hljs-strong {
/* prettylights-syntax-markup-bold */
color: #24292e;
font-weight: bold;
}
.hljs-addition {
/* prettylights-syntax-markup-inserted */
color: #22863a;
background-color: #f0fff4;
}
.hljs-deletion {
/* prettylights-syntax-markup-deleted */
color: #b31d28;
background-color: #ffeef0;
}
.hljs-char.escape_,
.hljs-link,
.hljs-params,
.hljs-property,
.hljs-punctuation,
.hljs-tag {
/* purposely ignored */
}

View File

@ -0,0 +1,8 @@
"use strict";function e(t){"@babel/helpers - typeof";return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t,o){return(t=n(t))in e?Object.defineProperty(e,t,{value:o,enumerable:!0,configurable:!0,writable:!0}):e[t]=o,e}function n(t){var n=o(t,"string");return"symbol"==e(n)?n:n+""}function o(t,n){if("object"!=e(t)||!t)return t;var o=t[Symbol.toPrimitive];if(void 0!==o){var i=o.call(t,n||"default");if("object"!=e(i))return i;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===n?String:Number)(t)}/*!
* mp-html v2.5.0
* https://github.com/jin-yufeng/mp-html
*
* Released under the MIT license
* Author: Jin Yufeng
*/
var i=require("./parser"),r=[];Component({data:{nodes:[]},properties:{containerStyle:String,content:{type:String,value:"",observer:function(e){this.setContent(e)}},copyLink:{type:Boolean,value:!0},domain:String,errorImg:String,lazyLoad:Boolean,loadingImg:String,pauseVideo:{type:Boolean,value:!0},previewImg:{type:null,value:!0},scrollTable:Boolean,selectable:null,setTitle:{type:Boolean,value:!0},showImgMenu:{type:Boolean,value:!0},tagStyle:Object,useAnchor:null},created:function(){this.plugins=[];for(var e=r.length;e--;)this.plugins.push(new r[e](this))},detached:function(){this._hook("onDetached")},methods:{in:function(e,t,n){e&&t&&n&&(this._in={page:e,selector:t,scrollTop:n})},navigateTo:function(e,n){var o=this;return new Promise(function(i,r){if(!o.data.useAnchor)return void r(Error("Anchor is disabled"));var a=wx.createSelectorQuery().in(o._in?o._in.page:o).select((o._in?o._in.selector:"._root")+(e?"".concat(">>>","#").concat(e):"")).boundingClientRect();o._in?a.select(o._in.selector).scrollOffset().select(o._in.selector).boundingClientRect():a.selectViewport().scrollOffset(),a.exec(function(e){if(!e[0])return void r(Error("Label not found"));var a=e[1].scrollTop+e[0].top-(e[2]?e[2].top:0)+(n||parseInt(o.data.useAnchor)||0);o._in?o._in.page.setData(t({},o._in.scrollTop,a)):wx.pageScrollTo({scrollTop:a,duration:300}),i()})})},getText:function(e){var t="";return function e(n){for(var o=0;o<n.length;o++){var i=n[o];if("text"===i.type)t+=i.text.replace(/&amp;/g,"&");else if("br"===i.name)t+="\n";else{var r="p"===i.name||"div"===i.name||"tr"===i.name||"li"===i.name||"h"===i.name[0]&&i.name[1]>"0"&&i.name[1]<"7";r&&t&&"\n"!==t[t.length-1]&&(t+="\n"),i.children&&e(i.children),r&&"\n"!==t[t.length-1]?t+="\n":"td"!==i.name&&"th"!==i.name||(t+="\t")}}}(e||this.data.nodes),t},getRect:function(){var e=this;return new Promise(function(t,n){wx.createSelectorQuery().in(e).select("._root").boundingClientRect().exec(function(e){return e[0]?t(e[0]):n(Error("Root label not found"))})})},pauseMedia:function(){for(var e=(this._videos||[]).length;e--;)this._videos[e].pause()},setPlaybackRate:function(e){this.playbackRate=e;for(var t=(this._videos||[]).length;t--;)this._videos[t].playbackRate(e)},setContent:function(e,t){var n=this;this.imgList&&t||(this.imgList=[]),this._videos=[];var o={},r=new i(this).parse(e);if(t)for(var a=this.data.nodes.length,s=r.length;s--;)o["nodes[".concat(a+s,"]")]=r[s];else o.nodes=r;if(this.setData(o,function(){n._hook("onLoad"),n.triggerEvent("load")}),this.data.lazyLoad||this.imgList._unloadimgs<this.imgList.length/2){var l=0,c=function(e){e&&e.height||(e={}),e.height===l?n.triggerEvent("ready",e):(l=e.height,setTimeout(function(){n.getRect().then(c).catch(c)},350))};this.getRect().then(c).catch(c)}else this.imgList._unloadimgs||this.getRect().then(function(e){n.triggerEvent("ready",e)}).catch(function(){n.triggerEvent("ready",{})})},_hook:function(e){for(var t=r.length;t--;)this.plugins[t][e]&&this.plugins[t][e]()},_add:function(e){e.detail.root=this}}});

View File

@ -0,0 +1 @@
{"component":true,"usingComponents":{"node":"./node/node"}}

View File

@ -0,0 +1 @@
<view class="_root {{selectable?'_select':''}}" style="{{containerStyle}}"><slot wx:if="{{!nodes[0]}}"/><node id="_root" childs="{{nodes}}" opts="{{[lazyLoad,loadingImg,errorImg,showImgMenu,selectable]}}" catchadd="_add"/></view>

View File

@ -0,0 +1,11 @@
._root {
/* padding: 1px 0;
overflow-x: auto;
overflow-y: hidden; */
/* -webkit-overflow-scrolling: touch */
}
._select {
-webkit-user-select: text;
user-select: text
}

View File

@ -0,0 +1 @@
"use strict";function t(e){"@babel/helpers - typeof";return(t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(e)}function e(t,e){var r=Object.keys(t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(t);e&&(i=i.filter(function(e){return Object.getOwnPropertyDescriptor(t,e).enumerable})),r.push.apply(r,i)}return r}function r(t){for(var r=1;r<arguments.length;r++){var o=null!=arguments[r]?arguments[r]:{};r%2?e(Object(o),!0).forEach(function(e){i(t,e,o[e])}):Object.getOwnPropertyDescriptors?Object.defineProperties(t,Object.getOwnPropertyDescriptors(o)):e(Object(o)).forEach(function(e){Object.defineProperty(t,e,Object.getOwnPropertyDescriptor(o,e))})}return t}function i(t,e,r){return(e=o(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}function o(e){var r=s(e,"string");return"symbol"==t(r)?r:r+""}function s(e,r){if("object"!=t(e)||!e)return e;var i=e[Symbol.toPrimitive];if(void 0!==i){var o=i.call(e,r||"default");if("object"!=t(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===r?String:Number)(e)}Component({data:{ctrl:{},isiOS:wx.getSystemInfoSync().system.includes("iOS")},properties:{childs:Array,opts:Array},options:{addGlobalClass:!0},attached:function(){this.triggerEvent("add",this,{bubbles:!0,composed:!0})},methods:{noop:function(){},getNode:function(t){try{for(var e=t.split("_"),r=this.data.childs[e[0]],i=1;i<e.length;i++)r=r.children[e[i]];return r}catch(t){return{text:"",attrs:{},children:[]}}},play:function(t){var e=t.target.dataset.i,i=this.getNode(e);if(this.root.triggerEvent("play",{source:i.name,attrs:r(r({},i.attrs),{},{src:i.src[this.data.ctrl[e]||0]})}),this.root.data.pauseVideo){for(var o=!1,s=t.target.id,n=this.root._videos.length;n--;)this.root._videos[n].id===s?o=!0:this.root._videos[n].pause();if(!o){var a=wx.createVideoContext(s,this);a.id=s,this.root.playbackRate&&a.playbackRate(this.root.playbackRate),this.root._videos.push(a)}}},imgTap:function(t){var e=this.getNode(t.target.dataset.i);if(e.a)return this.linkTap(e.a);if(!e.attrs.ignore&&(this.root.triggerEvent("imgtap",e.attrs),this.root.data.previewImg)){var r=this.root.imgList[e.i];wx.previewImage({showmenu:this.root.data.showImgMenu,current:r,urls:this.root.imgList})}},imgLoad:function(t){var e,r=t.target.dataset.i,o=this.getNode(r);o.w?(this.data.opts[1]&&!this.data.ctrl[r]||-1===this.data.ctrl[r])&&(e=1):e=t.detail.width,e&&this.setData(i({},"ctrl."+r,e)),this.checkReady()},checkReady:function(){var t=this;this.root.data.lazyLoad||(this.root.imgList._unloadimgs-=1,this.root.imgList._unloadimgs||setTimeout(function(){t.root.getRect().then(function(e){t.root.triggerEvent("ready",e)}).catch(function(){t.root.triggerEvent("ready",{})})},350))},linkTap:function(t){var e=t.currentTarget?this.getNode(t.currentTarget.dataset.i):{},r=e.attrs||t,i=r.href;this.root.triggerEvent("linktap",Object.assign({innerText:this.root.getText(e.children||[])},r)),i&&("#"===i[0]?this.root.navigateTo(i.substring(1)).catch(function(){}):i.split("?")[0].includes("://")?this.root.data.copyLink&&wx.setClipboardData({data:i,success:function(){return wx.showToast({title:"链接已复制"})}}):wx.navigateTo({url:i,fail:function(){wx.switchTab({url:i,fail:function(){}})}}))},mediaError:function(t){var e=t.target.dataset.i,r=this.getNode(e);if("video"===r.name||"audio"===r.name){var o=(this.data.ctrl[e]||0)+1;if(o>r.src.length&&(o=0),o<r.src.length)return this.setData(i({},"ctrl."+e,o))}else"img"===r.name&&(this.data.opts[2]&&this.setData(i({},"ctrl."+e,-1)),this.checkReady());this.root&&this.root.triggerEvent("error",{source:r.name,attrs:r.attrs,errMsg:t.detail.errMsg})}}});

View File

@ -0,0 +1 @@
{"component":true,"usingComponents":{"node":"./node","copy":"../../copy/index"}}

View File

@ -0,0 +1,43 @@
<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">
<block wx:if="{{n.attrs.class==='__preCodeCopyWrap'}}">
<copy dataClipboardText="{{n.attrs.href}}"></copy>
</block>
<block wx:else>
<node childs="{{n.children}}" opts="{{opts}}" style="display:inherit" />
</block>
</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>

View File

@ -0,0 +1,156 @@
/* ._a {
padding: 1.5px 0 1.5px 0;
color: #366092;
word-break: break-all
}
._hover {
text-decoration: underline;
opacity: .7
}
._img {
max-width: 100%;
-webkit-touch-callout: none
}
._b,
._strong {
font-weight: 700
}
._code {
font-family: monospace
}
._del {
text-decoration: line-through
}
._em,
._i {
font-style: italic
}
._h1 {
font-size: 2em
}
._h2 {
font-size: 1.5em
}
._h3 {
font-size: 1.17em
}
._h5 {
font-size: .83em
}
._h6 {
font-size: .67em
}
._h1,
._h2,
._h3,
._h4,
._h5,
._h6 {
display: block;
font-weight: 700
}
._ins {
text-decoration: underline
}
._li {
display: list-item
}
._ol {
list-style-type: decimal
}
._ol,
._ul {
display: block;
padding-left: 40px;
margin: 1em 0
}
._q::before {
content: '"'
}
._q::after {
content: '"'
}
._sub {
font-size: smaller;
vertical-align: sub
}
._sup {
font-size: smaller;
vertical-align: super
}
._tbody,
._tfoot,
._thead {
display: table-row-group
}
._tr {
display: table-row
}
._td,
._th {
display: table-cell;
vertical-align: middle
}
._th {
font-weight: 700;
text-align: center
}
._ul {
list-style-type: disc
}
._ul ._ul {
margin: 0;
list-style-type: circle
}
._ul ._ul ._ul {
list-style-type: square
}
._abbr,
._b,
._code,
._del,
._em,
._i,
._ins,
._label,
._q,
._span,
._strong,
._sub,
._sup {
display: inline
}
._blockquote,
._div,
._p {
display: block
} */

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,55 @@
const options = {
paragraph_open: "_p",
bullet_list_open: "_ul",
ordered_list_open: "_ol",
hr: "_hr",
link_open: "_a",
blockquote_open: "_blockquote",
table_open: "_table",
thead_open: "_thead",
tr_open: "_tr",
th_open: "_th",
td_open: "_td",
};
export function addCustomClassPlugin(md) {
md.renderer.rules.heading_open = (tokens, idx, options, env, self) => {
const token = tokens[idx];
// console.log(token)
// 判断当前标签是否为 h1
if (["h1", "h2", "h3", "h4", "h5", "h6"].includes(token.tag)) {
// 给 h1 标签添加 class 属性
token.attrJoin("class", `_${token.tag}`);
}
return self.renderToken(tokens, idx, options);
};
Object.keys(options).forEach((key) => {
const className = options[key];
md.renderer.rules[key] = (tokens, idx, options, env, self) => {
tokens[idx].attrPush(["class", className]);
return self.renderToken(tokens, idx, options);
};
});
}
function renderCode(origRule) {
return (...args) => {
const [tokens, idx] = args;
const content = tokens[idx].content
.replaceAll('"', '&quot;')
.replaceAll("'", "&apos;");
const origRendered = origRule(...args);
if (content.length === 0)
return origRendered;
return `
<div style="position: relative" >
${origRendered}
<a class="__preCodeCopyWrap" href="${content}"></a>
</div>
`;
};
}
export const copy = (md) => {
md.renderer.rules.code_block = renderCode(md.renderer.rules.code_block);
md.renderer.rules.fence = renderCode(md.renderer.rules.fence);
};