chore: initialize qiming workspace repository

This commit is contained in:
Codex
2026-05-29 14:22:48 +08:00
commit bfd67a0f2c
10750 changed files with 1885711 additions and 0 deletions

View File

@@ -0,0 +1,506 @@
<template>
<view class="msg-root">
<text v-if="msg.error_msg != null" class="error-msg">
{{ msg.error_msg }}
</text>
<template v-else>
<!-- AI 思考模式 -->
<view class="think-container" v-if="!!msg.thinkContent || !!msg.think">
<view class="think-header">
<view class="think-header-left" @tap="changeThinkContent">
<text class="iconfont icon-BulbOutlined thinking-icon"></text>
<text class="thinking-title">
{{
isThinkingFinished
? t("Mobile.Chat.thought")
: t("Mobile.Chat.thinking")
}}
</text>
<text
class="iconfont icon-a-Chevrondown expand-icon"
:class="{ 'is-expanded': !hideThinkContent }"
></text>
</view>
</view>
<view
class="think-content"
:class="{ 'hide-think-content': hideThinkContent }"
>
<view class="text-box">
<mp-html
:content="msg.thinkContent || msg.think"
:markdown="true"
:selectable="true"
:container-style="`font-size: 28rpx; color: #888; line-height: 1.6;`"
/>
</view>
</view>
</view>
<!-- AI 答复内容 -->
<view class="answer-container">
<!-- AI校验通过后需要水平滚动表格时需要设置 scroll-table="true" -->
<mp-html
:content="processedText"
:processing-list="msg.processingList"
:conversation-id="msg.chat_id"
:markdown="true"
:selectable="true"
:container-style="`width: 100%;`"
:tag-style="tagStyle"
:scroll-table="true"
/>
</view>
</template>
<image
v-if="
isConversationActive && isLastMsg && taskStatus !== TaskStatus.EXECUTING
"
class="icon-loading-image"
src="@/static/assets/icon_loading.svg"
:show-menu-by-longpress="false"
@longtap.stop.prevent
@contextmenu.stop.prevent="true"
mode="widthFix"
/>
<msg-tool-bar
v-if="
((!isConversationActive || !isLastMsg) && (msg.body || msg.text)) ||
msg.state === 3
"
:msg="msg"
/>
</view>
</template>
<script lang="uts" setup>
import { MsgItem } from "@/uni_modules/uni-ai-x/sdk";
import msgToolBar from "@/uni_modules/uni-ai-x/components/msg-tool-bar.uvue";
import mpHtml from "@/subpackages/uni_modules/mp-html/components/mp-html/mp-html.vue";
import {
replaceMathBracket,
groupMarkdownContainers,
} from "@/utils/markdown.uts";
import { TaskStatus } from "@/types/enums/agent";
import { useI18n } from "@/utils/i18n";
const { t } = useI18n();
const props = defineProps<{
msg: MsgItem;
// 会话是否正在进行中(有消息正在处理)
isConversationActive?: boolean;
taskStatus?: TaskStatus;
// 是否是最后一条消息
isLastMsg?: boolean;
}>();
const msg = ref<MsgItem>(props.msg as MsgItem); // 转化内部状态为响应式
const isLastMsg = computed(() => props.isLastMsg);
const isConversationActive = computed(() => props.isConversationActive);
// 思考内容是否隐藏(默认隐藏)
const hideThinkContent = ref<boolean>(true);
// 思考是否已完成:如果正文已经有内容,或者会话已结束,或者不是最后一条消息,则认为思考已完成
const isThinkingFinished = computed((): boolean => {
return (
msg.value.body.trim().length > 0 ||
!props.isConversationActive ||
!props.isLastMsg
);
});
// 标签自定义样式,解决长文本换行问题
const tagStyle = {
p: "word-break: break-all; overflow-wrap: break-word;",
li: "word-break: break-all; overflow-wrap: break-word;",
div: "word-break: break-all; overflow-wrap: break-word;",
span: "word-break: break-all; overflow-wrap: break-word;",
};
const emit = defineEmits<{
changeThinkContent: [hideThinkContent: boolean];
}>();
const getRenderKey = (...args: any[]) => {
return msg.value.chat_id + "-" + args.join("-");
};
const genImageHtml = (src: string) => {
return `<img src="${src}" />`;
};
const changeThinkContent = () => {
hideThinkContent.value = !hideThinkContent.value;
emit("changeThinkContent", hideThinkContent.value);
};
// 添加updateMessage方法支持动态更新消息内容
const updateMessage = (newData: any) => {
try {
// 使用响应式数据而不是直接操作props
if (newData) {
const updatedMsg = {
...msg.value,
...newData,
};
msg.value = updatedMsg;
// console.log('更新消息成功:', newData);
}
} catch (error) {
console.error("updateMessage 执行失败:", error);
}
};
// 处理文本内容,应用数学公式格式转换及组件合并
const processedText = computed(() => {
if (!msg.value || (msg.value.body || "").trim().length === 0) {
return "";
}
const groupedText = groupMarkdownContainers(msg.value.body);
return replaceMathBracket(groupedText);
});
// 暴露方法给父组件
defineExpose({
updateMessage,
});
</script>
<style lang="scss">
.msg-root {
flex-direction: row;
flex-wrap: wrap;
// #ifdef WEB || MP-WEIXIN
user-select: text;
-webkit-user-select: text;
// #endif
padding: 0 32rpx;
min-height: 90rpx;
.think-container {
width: 100%;
// margin-bottom: 24rpx;
.think-header {
display: flex;
flex-direction: row;
align-items: center;
padding: 8rpx 0;
.think-header-left {
display: flex;
flex-direction: row;
align-items: center;
.thinking-icon {
font-size: 36rpx;
color: #999;
margin-right: 12rpx;
}
.thinking-title {
color: #999;
font-size: 28rpx;
}
.expand-icon {
margin-left: 12rpx;
font-size: 28rpx;
color: #999;
transition: transform 0.3s ease;
&.is-expanded {
transform: rotate(180deg);
}
}
}
}
.think-content {
overflow: hidden;
transition: all 0.3s ease;
padding-top: 8rpx;
&.hide-think-content {
height: 0;
padding-top: 0;
opacity: 0;
}
.text-box {
border-left: 4rpx solid #efefef;
padding-left: 20rpx;
background-color: rgba(245, 245, 245, 0.3);
border-radius: 0 8rpx 8rpx 0;
padding-top: 8rpx;
padding-bottom: 8rpx;
.text {
font-size: 28rpx;
color: #888;
line-height: 1.6;
white-space: pre-wrap;
word-break: break-all;
}
}
}
}
.answer-container {
width: 100%;
}
.error-msg {
color: #ff4d4f;
font-size: 28rpx;
line-height: 52rpx;
}
.loging-icon {
margin-top: 16rpx;
width: 32rpx;
height: 32rpx;
}
.stop-text {
color: #aaa;
font-size: 28rpx;
padding: 16rpx 0;
}
.need-try {
color: #ff4d4f;
font-size: 28rpx;
padding: 16rpx;
}
.error-msg,
.stop-text,
.need-try {
text-align: left;
width: 100%;
}
}
.text {
color: #15171f;
font-weight: 400;
line-height: 56rpx;
white-space: pre-wrap;
word-break: break-all;
overflow-wrap: anywhere;
max-width: 100%;
}
.strong {
font-weight: bold;
}
.em {
font-style: italic;
}
.del {
text-decoration-line: line-through;
color: #999;
}
.space {
height: 10px;
}
.link {
color: #0066cc !important;
word-break: break-all;
overflow-wrap: anywhere;
// #ifdef WEB
cursor: pointer;
&:hover {
opacity: 0.8;
}
// #endif
}
.paragraph-box {
display: block;
.text {
font-size: 32rpx;
font-weight: 400;
line-height: 56rpx;
// 自动换行并显示 \n
white-space: pre-wrap;
word-break: break-all;
overflow-wrap: anywhere;
max-width: 100%;
/* #ifdef H5 */
width: auto;
word-break: break-all;
/* #endif */
}
}
.image-box {
width: 100%;
}
.blockquote-box {
padding: 5px;
background: #f5f5f5;
border-left: 4px solid #ddd;
}
.container-box {
width: 100%;
}
.heading-box {
.text {
color: #15171f;
font-size: 40rpx;
font-weight: 600;
line-height: 56rpx;
}
.depth-1 {
font-size: 50rpx;
line-height: 60rpx;
}
.depth-2 {
font-size: 42rpx;
line-height: 56rpx;
}
.depth-3 {
font-size: 34rpx;
line-height: 56rpx;
}
.depth-4 {
font-size: 30rpx;
line-height: 56rpx;
}
.depth-5 {
font-size: 26rpx;
line-height: 56rpx;
}
.depth-6 {
font-size: 24rpx;
color: #999;
line-height: 56rpx;
}
}
.hr {
height: 2rpx;
background: #ddd;
margin: 20rpx 0;
}
.br {
width: 100%;
display: block;
}
.list-box {
padding-left: 10rpx;
.list-content {
width: 100%;
}
.text {
line-height: 56rpx;
}
.list-item-content-box {
flex: 1;
.list {
margin-top: 0;
}
}
.list-item-br {
width: 100%;
}
.list-item-index {
width: 40rpx;
&.unordered {
font-size: 28rpx;
color: #000;
}
&.task {
font-size: 28rpx;
color: #666;
}
}
}
.list-inline-image-box {
max-width: 100%;
display: block;
.list-content {
width: 100%;
}
.text {
line-height: 56rpx;
}
.list-item-content-box {
flex: 1;
.list {
margin-top: 0;
}
}
.list-item-br {
width: 100%;
}
.list-item-index {
width: 40rpx;
&.unordered {
font-size: 28rpx;
color: #000;
}
&.task {
font-size: 28rpx;
color: #666;
}
}
}
.hr-box {
background-color: #ddd;
height: 2rpx;
}
.tool-call-box {
width: 100%;
margin: 10rpx 0;
}
.table-box,
.code-box,
.hr-box,
.paragraph-box,
.blockquote-box,
.heading-box,
.list-box,
.loging-icon,
.math-box {
width: 100%;
margin: 10rpx 0;
}
.paragraph-box {
margin-top: 0;
margin-bottom: 0;
}
.space-box {
height: 30rpx;
}
.codespan {
color: #666;
background-color: #f5f5f5;
padding: 4rpx 8rpx;
border-radius: 10rpx;
font-size: 28rpx;
word-break: break-all;
overflow-wrap: anywhere;
}
.icon-loading-image {
width: 48rpx;
height: 48rpx;
margin-right: 10rpx;
-webkit-touch-callout: none !important;
-webkit-user-select: none !important;
user-select: none !important;
}
</style>