chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
<template>
|
||||
<view class="markdown-custom-process-group">
|
||||
<view class="group-header" @tap="toggleExpanded">
|
||||
<view class="header-left">
|
||||
<text class="group-title">{{ getI18nText('Mobile.ThirdParty.MpHtml.toolCall') }}</text>
|
||||
</view>
|
||||
<view class="header-right">
|
||||
<text class="process-count">{{ processCount + ' ' + getI18nText('Mobile.ThirdParty.MpHtml.itemCount') }}</text>
|
||||
<text class="iconfont icon-a-Chevrondown expand-icon" :class="{ 'is-expanded': isExpanded }"></text>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="isExpanded" class="group-content">
|
||||
<slot />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { t } from '@/utils/i18n'
|
||||
|
||||
export default {
|
||||
name: 'MarkdownContainerGroup',
|
||||
props: {
|
||||
// 仅用于计算数量,不再直接渲染
|
||||
childs: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExpanded: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
processCount() {
|
||||
// 过滤掉可能的空白节点,支持原生 container 和 PC 端 HTML 标签名,同时排除隐藏的 Event 类型
|
||||
return (this.childs || []).filter(n =>
|
||||
(n.name === 'container' || n.name === 'markdown-custom-process') &&
|
||||
n.attrs?.type !== 'Event'
|
||||
).length
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getI18nText(key, params) {
|
||||
return t(key, params)
|
||||
},
|
||||
toggleExpanded() {
|
||||
this.isExpanded = !this.isExpanded
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.markdown-custom-process-group {
|
||||
margin: 16rpx 0;
|
||||
border-radius: 12rpx;
|
||||
border: 1rpx solid rgba(0, 0, 0, 0.08);
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
|
||||
.group-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx 24rpx;
|
||||
background-color: rgba(0, 0, 0, 0.02);
|
||||
|
||||
.header-left {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.group-title {
|
||||
font-size: 26rpx;
|
||||
color: #333333;
|
||||
}
|
||||
}
|
||||
|
||||
.header-right {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
|
||||
.process-count {
|
||||
font-size: 24rpx;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
|
||||
.expand-icon {
|
||||
font-size: 24rpx;
|
||||
color: #8c8c8c;
|
||||
transition: transform 0.3s ease;
|
||||
|
||||
&.is-expanded {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group-content {
|
||||
padding: 12rpx 24rpx;
|
||||
border-top: 1rpx solid rgba(0, 0, 0, 0.05);
|
||||
max-height: 500rpx;
|
||||
overflow-y: auto;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,648 @@
|
||||
<template>
|
||||
<view v-if="toolCall?.type !== 'Event'" class="tool-call-status">
|
||||
<!-- Plan 类型:直接显示任务列表 -->
|
||||
<template v-if="isPlanType">
|
||||
<!-- Plan 头部信息 -->
|
||||
<view class="plan-header">
|
||||
<view class="plan-info">
|
||||
<text class="plan-name">{{
|
||||
toolCall.name || getI18nText("Mobile.ThirdParty.MpHtml.executionPlan")
|
||||
}}</text>
|
||||
<!-- <view class="plan-status-display">
|
||||
<view class="status-icon" :class="getStatusIconClass(toolCall.status)">
|
||||
<text :class="getStatusIconType(toolCall.status)" :style="{color: getStatusIconColor(toolCall.status),fontSize: '32rpx'}"></text>
|
||||
</view>
|
||||
<text class="plan-status-text">{{ getStatusText(toolCall.status) }}</text>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="plan-expand-icon" @tap="togglePlanExpanded">
|
||||
<text class="iconfont" :class="planExpanded ? 'icon-MinusOutlined' : 'icon-Plus'"></text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Plan 任务列表(直接展示) -->
|
||||
<view v-if="planExpanded && planTaskList.length > 0" class="plan-task-list">
|
||||
<view v-for="(task, index) in planTaskList" :key="index" class="plan-task-item">
|
||||
<!-- 字体图标实现的状态 -->
|
||||
<view class="task-status-icon" :class="getTaskStatusClass(task.status)">
|
||||
<text class="task-icon iconfont" :class="getTaskStatusIcon(task.status)"></text>
|
||||
</view>
|
||||
<text class="task-content">{{ task.content }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<!-- 非 Plan 类型:显示工具调用状态 -->
|
||||
<template v-else>
|
||||
<!-- 工具调用头部信息 -->
|
||||
<view class="tool-header" @tap="toggleExpanded">
|
||||
<view class="tool-info">
|
||||
<text class="tool-name">{{ toolNameDisplay }}</text>
|
||||
<view class="tool-status-display">
|
||||
<view class="status-icon" :class="getStatusIconClass(toolCall.status)">
|
||||
<text :class="getStatusIconType(toolCall.status)" :style="{color: getStatusIconColor(toolCall.status),fontSize: '32rpx'}"></text>
|
||||
</view>
|
||||
<text class="tool-status-text">{{ getStatusText(toolCall.status) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="tool-actions">
|
||||
<view class="action-icon" @tap.stop.prevent="handleShowDetails(detailData)">
|
||||
<text class="iconfont icon-ProfileOutlined"></text>
|
||||
</view>
|
||||
<!-- <view class="action-icon" @tap.stop.prevent="handleCopyToClipboard">
|
||||
<text class="iconfont icon-Copy"></text>
|
||||
</view> -->
|
||||
<view v-if="isPageType(toolCall)" class="action-icon" @tap.stop.prevent="openPreviewPage(toolCall)">
|
||||
<text class="iconfont icon-eye-open"></text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 展开后的详细信息 调用参数/调用结果-->
|
||||
<!-- <view v-if="expanded" class="tool-details-expanded">
|
||||
<view v-if="detailData.params && Object.keys(detailData.params).length > 0" class="detail-section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">{{
|
||||
getI18nText("Mobile.ThirdParty.MpHtml.callArguments")
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="arguments-content">
|
||||
<text class="arguments-text">{{ formatArguments(detailData.params) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view v-if="detailData.response" class="detail-section">
|
||||
<view class="section-header">
|
||||
<text class="section-title">{{
|
||||
getI18nText("Mobile.ThirdParty.MpHtml.callResult")
|
||||
}}</text>
|
||||
</view>
|
||||
<view class="output-content">
|
||||
<text class="output-text">{{ formatResult(detailData.response) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view> -->
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import uniIcons from '@/uni_modules/uni-icons/components/uni-icons/uni-icons.vue'
|
||||
import { AgentComponentTypeEnum } from '@/types/enums/agent.uts';
|
||||
import { getCurrentPageParams } from '@/utils/common';
|
||||
import { getFileProxyUrlByConversationIdAndFilePath, jumpToFilePreviewPage } from '@/utils/system.uts';
|
||||
import { t } from '@/utils/i18n';
|
||||
|
||||
export default {
|
||||
name: 'Container',
|
||||
components: {
|
||||
uniIcons,
|
||||
// toolDetailsModal
|
||||
},
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// expanded: false,
|
||||
planExpanded: true, // Plan 类型默认展开
|
||||
toolCall: this.data
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
// 判断是否为 Plan 类型
|
||||
isPlanType() {
|
||||
return this.toolCall.type === AgentComponentTypeEnum.Plan || this.toolCall.type === 'Plan'
|
||||
},
|
||||
|
||||
// 格式化显示的工具名称,处理多行代码情况
|
||||
toolNameDisplay() {
|
||||
let name = this.toolCall.name || this.toolCall.type || '';
|
||||
// 还原引号实体
|
||||
name = name.replace(/"/g, '"');
|
||||
// 替换换行符为空格,防止换行符干扰单行省略号显示
|
||||
return name.replace(/\n/g, ' ').trim();
|
||||
},
|
||||
|
||||
// Plan 任务列表
|
||||
planTaskList() {
|
||||
const result = this.toolCall.result || {}
|
||||
const data = result.data
|
||||
|
||||
if (Array.isArray(data)) {
|
||||
return data
|
||||
}
|
||||
|
||||
return []
|
||||
},
|
||||
|
||||
detailData() {
|
||||
const _result = this.toolCall.result || {}
|
||||
return {
|
||||
// 从结果中提取输入参数,如果没有则提供空对象
|
||||
params: _result.input || {},
|
||||
// 使用结果的 data 作为响应数据,如果没有则提供空对象
|
||||
response: _result.data || null,
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
data: {
|
||||
handler(newData) {
|
||||
this.toolCall = newData;
|
||||
},
|
||||
immediate: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getI18nText(key) {
|
||||
return t(key)
|
||||
},
|
||||
|
||||
// 打开页面首页
|
||||
openPreviewPage(data) {
|
||||
uni.$emit('page_preview_executing', data);
|
||||
},
|
||||
|
||||
// 切换展开状态
|
||||
async toggleExpanded() {
|
||||
const result = this.data?.result;
|
||||
|
||||
// 打开预览页面
|
||||
if (result?.kind === 'edit') {
|
||||
const params = getCurrentPageParams();
|
||||
|
||||
const conversationId = params.conversationId;
|
||||
const file_path = result?.input?.file_path;
|
||||
|
||||
const fileProxyUrl = await getFileProxyUrlByConversationIdAndFilePath(conversationId, file_path);
|
||||
jumpToFilePreviewPage(conversationId, fileProxyUrl);
|
||||
return;
|
||||
}
|
||||
|
||||
// this.expanded = !this.expanded
|
||||
},
|
||||
|
||||
// 切换 Plan 展开状态
|
||||
togglePlanExpanded() {
|
||||
this.planExpanded = !this.planExpanded
|
||||
},
|
||||
|
||||
// 显示详情
|
||||
showDetails() {
|
||||
if (!this.toolCall.result) {
|
||||
return uni.showToast({
|
||||
icon: 'none',
|
||||
title: t('Mobile.ThirdParty.MpHtml.emptyResult'),
|
||||
})
|
||||
}
|
||||
// this.expanded = !this.expanded
|
||||
},
|
||||
|
||||
// 处理显示详情点击(阻止冒泡)
|
||||
handleShowDetails() {
|
||||
uni.$emit('page_preview_detail', this.toolCall, this.detailData);
|
||||
},
|
||||
|
||||
// 处理复制到剪贴板点击(阻止冒泡)
|
||||
handleCopyToClipboard(event) {
|
||||
event.stopPropagation()
|
||||
this.copyToClipboard()
|
||||
},
|
||||
|
||||
// 复制结果
|
||||
copyResult() {
|
||||
// 实现复制功能
|
||||
console.log('复制结果')
|
||||
},
|
||||
|
||||
// 复制到剪贴板
|
||||
copyToClipboard() {
|
||||
// 实现复制到剪贴板功能
|
||||
uni.setClipboardData({
|
||||
data: this.formatArguments(this.detailData),
|
||||
success: () => {
|
||||
uni.showToast({
|
||||
title: t('Mobile.Common.copySuccess'),
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
uni.showToast({
|
||||
title: t('Mobile.Common.copyFailed'),
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 获取状态图标类型
|
||||
getStatusIconType(status) {
|
||||
const iconMap = {
|
||||
'EXECUTING': 'icon-Loader', // 执行中显示加载图标
|
||||
'FINISHED': 'icon-Check', // 已完成显示对勾
|
||||
'FAILED': 'icon-waring' // 执行失败显示叉号
|
||||
}
|
||||
return ` iconfont ${iconMap[status] || 'icon-Check'}`
|
||||
},
|
||||
|
||||
// 获取状态图标样式类
|
||||
getStatusIconClass(status) {
|
||||
const statusClassMap = {
|
||||
'EXECUTING': 'status-icon-executing',
|
||||
'FINISHED': 'status-icon-finished',
|
||||
'FAILED': 'status-icon-failed'
|
||||
}
|
||||
return statusClassMap[status] || 'status-icon-default'
|
||||
},
|
||||
|
||||
// 获取状态图标颜色
|
||||
getStatusIconColor(status) {
|
||||
const statusColorMap = {
|
||||
'EXECUTING': '#1890ff',
|
||||
'FINISHED': '#52c41a',
|
||||
// 'FAILED': '#ff4d4f'
|
||||
'FAILED': '#ffcb00'
|
||||
}
|
||||
return statusColorMap[status] || '#999'
|
||||
},
|
||||
|
||||
// 获取状态文本
|
||||
getStatusText(status) {
|
||||
return '';
|
||||
// const statusTextMap = {
|
||||
// 'EXECUTING': '执行中',
|
||||
// 'FINISHED': '已完成',
|
||||
// 'FAILED': '执行失败'
|
||||
// }
|
||||
// return statusTextMap[status] || '未知状态'
|
||||
},
|
||||
|
||||
|
||||
// 获取任务状态样式类
|
||||
getTaskStatusClass(status) {
|
||||
const classMap = {
|
||||
'completed': 'task-status-completed',
|
||||
'pending': 'task-status-pending',
|
||||
'in_progress': 'task-status-in-progress',
|
||||
'failed': 'task-status-failed'
|
||||
}
|
||||
return classMap[status] || 'task-status-pending'
|
||||
},
|
||||
|
||||
// 获取任务状态图标 (使用字体图标unicode)
|
||||
getTaskStatusIcon(status) {
|
||||
const iconMap = {
|
||||
'pending': 'icon-BorderOutlined', // 待处理
|
||||
'in_progress': 'icon-HourglassOutlined', // 进行中
|
||||
'completed': 'icon-CheckSquareOutlined', // 已完成
|
||||
'failed': 'icon-CloseSquareOutlined' // 失败
|
||||
}
|
||||
return iconMap[status] || 'icon-BorderOutlined'
|
||||
},
|
||||
|
||||
// 格式化参数显示
|
||||
formatArguments(args) {
|
||||
try {
|
||||
return JSON.stringify(args, null, 2)
|
||||
} catch (error) {
|
||||
return String(args)
|
||||
}
|
||||
},
|
||||
|
||||
// 格式化结果显示
|
||||
formatResult(result) {
|
||||
if (result && typeof result === 'object') {
|
||||
try {
|
||||
return JSON.stringify(result, null, 2)
|
||||
} catch (error) {
|
||||
return String(result)
|
||||
}
|
||||
}
|
||||
return String(result)
|
||||
},
|
||||
|
||||
// 格式化执行时间
|
||||
formatExecutionTime(time) {
|
||||
if (time < 1000) {
|
||||
return `${time}ms`
|
||||
} else if (time < 60000) {
|
||||
return `${(time / 1000).toFixed(2)}s`
|
||||
} else {
|
||||
return `${(time / 60000).toFixed(2)}min`
|
||||
}
|
||||
},
|
||||
isPageType(toolCall) {
|
||||
return toolCall.type === AgentComponentTypeEnum.Page;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.tool-call-status {
|
||||
width: 100%;
|
||||
margin: 16rpx 0;
|
||||
border-radius: 16rpx;
|
||||
background-color: rgba(12, 20, 102, 0.04);
|
||||
overflow: hidden;
|
||||
|
||||
.iconfont {
|
||||
font-size: 32rpx;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
// Plan 类型样式
|
||||
.plan-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
|
||||
.plan-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
gap: 16rpx;
|
||||
|
||||
.plan-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
|
||||
.plan-status-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 8rpx;
|
||||
|
||||
.status-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.status-icon-executing {
|
||||
animation: spin 1s linear infinite;
|
||||
}
|
||||
}
|
||||
|
||||
.plan-status-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
line-height: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// .plan-expand-icon {
|
||||
// .iconfont {
|
||||
// font-size: 32rpx;
|
||||
// color: #333;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
// Plan 任务列表
|
||||
.plan-task-list {
|
||||
padding: 0 24rpx 24rpx;
|
||||
border-top: 2rpx solid rgba(0, 0, 0, 0.06);
|
||||
margin-top: 0;
|
||||
|
||||
.plan-task-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
gap: 8rpx;
|
||||
padding: 12rpx 0;
|
||||
|
||||
.task-status-icon {
|
||||
flex-shrink: 0;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-top: 4rpx;
|
||||
|
||||
.task-icon {
|
||||
font-family: 'iconfont';
|
||||
font-size: 32rpx;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
color: #8c8c8c;
|
||||
}
|
||||
}
|
||||
|
||||
.task-content {
|
||||
flex: 1;
|
||||
font-size: 26rpx;
|
||||
color: #262626;
|
||||
line-height: 40rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 非 Plan 类型样式(原有样式)
|
||||
.tool-header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 24rpx;
|
||||
|
||||
.tool-info {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
flex: 1;
|
||||
gap: 16rpx;
|
||||
|
||||
.tool-name {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 40rpx;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.tool-status-display {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 8rpx;
|
||||
|
||||
.status-icon {
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
// border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
&.status-icon-executing {
|
||||
animation: spin 1s linear infinite;
|
||||
|
||||
.iconfont {
|
||||
color: #1890ff;
|
||||
}
|
||||
}
|
||||
|
||||
&.status-icon-finished {
|
||||
color: #52c41a;
|
||||
}
|
||||
|
||||
&.status-icon-failed {
|
||||
color: #ff4d4f;
|
||||
}
|
||||
|
||||
&.status-icon-default {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.tool-status-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
line-height: 32rpx;
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tool-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
gap: 16rpx;
|
||||
|
||||
.action-icon {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 6rpx;
|
||||
transition: background-color 0.3s ease;
|
||||
cursor: pointer;
|
||||
|
||||
.iconfont {
|
||||
// font-size: 32rpx;
|
||||
font-weight: 400;
|
||||
// color: #333;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tool-details-expanded {
|
||||
padding: 24rpx;
|
||||
background-color: #f8f9fa;
|
||||
border-top: 2rpx solid #f0f0f0;
|
||||
|
||||
.detail-section {
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.section-header {
|
||||
margin-bottom: 16rpx;
|
||||
|
||||
.section-title {
|
||||
font-size: 26rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 36rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.execute-id-content,
|
||||
.arguments-content,
|
||||
.output-content,
|
||||
.error-content,
|
||||
.execution-time {
|
||||
padding: 16rpx;
|
||||
background-color: #ffffff;
|
||||
border-radius: 8rpx;
|
||||
border: 2rpx solid #e9ecef;
|
||||
|
||||
.execute-id-text,
|
||||
.arguments-text,
|
||||
.output-text,
|
||||
.error-text,
|
||||
.time-text {
|
||||
font-size: 24rpx;
|
||||
line-height: 36rpx;
|
||||
color: #495057;
|
||||
font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
|
||||
&.error-section {
|
||||
.error-content {
|
||||
background-color: #fff5f5;
|
||||
border-color: #ffccc7;
|
||||
|
||||
.error-text {
|
||||
color: #cf1322;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 加载动画
|
||||
@keyframes spin {
|
||||
from {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 750rpx) {
|
||||
.tool-header {
|
||||
padding: 20rpx;
|
||||
|
||||
.tool-info {
|
||||
.tool-name {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
|
||||
.tool-status-display {
|
||||
.tool-status-text {
|
||||
font-size: 22rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tool-details-expanded {
|
||||
padding: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* @fileoverview Container 插件
|
||||
*/
|
||||
function Container(vm) {}
|
||||
|
||||
export default Container;
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* 按优先级从 processingList 中获取数据
|
||||
* 优先级顺序:FINISHED -> FAILED -> EXECUTING
|
||||
* @param executeId 执行ID
|
||||
* @param processingList 处理列表
|
||||
* @returns 按优先级排序后的数据
|
||||
*/
|
||||
export const getProcessingDataByPriority = (executeId, processingList) => {
|
||||
if (!processingList || !Array.isArray(processingList)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// 过滤出匹配 executeId 的项目
|
||||
const matchedItems = processingList.filter(
|
||||
(item) => item.executeId === executeId
|
||||
);
|
||||
|
||||
if (matchedItems.length === 0) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// 定义状态优先级(数字越小优先级越高)
|
||||
const statusPriority = {
|
||||
FINISHED: 1,
|
||||
FAILED: 2,
|
||||
EXECUTING: 3,
|
||||
};
|
||||
|
||||
// 按优先级排序,优先级高的在前
|
||||
const sortedItems = matchedItems.sort((a, b) => {
|
||||
const priorityA = statusPriority[a.status] || 999;
|
||||
const priorityB = statusPriority[b.status] || 999;
|
||||
return priorityA - priorityB;
|
||||
});
|
||||
|
||||
// 返回优先级最高的项目
|
||||
return sortedItems[0] || {};
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
export default {
|
||||
copyByLongPress: true, // 是否需要长按代码块时显示复制代码内容菜单
|
||||
showLanguageName: true, // 是否在代码块右上角显示语言的名称
|
||||
showLineNumber: true, // 是否显示行号
|
||||
};
|
||||
@@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @fileoverview highlight 插件
|
||||
* Include prismjs (https://prismjs.com)
|
||||
*/
|
||||
import prism from "./prism.min";
|
||||
import installLanguages from "./prism-languages";
|
||||
import config from "./config";
|
||||
|
||||
installLanguages(prism);
|
||||
const getCopyButtonText = () => {
|
||||
try {
|
||||
const lang = String(uni.getStorageSync("I18N_LANG") || "zh-CN")
|
||||
.toLowerCase()
|
||||
.trim();
|
||||
return lang.startsWith("en")
|
||||
? "Copy code"
|
||||
: "复制代码";
|
||||
} catch (error) {
|
||||
return "复制代码";
|
||||
}
|
||||
};
|
||||
import Parser from "../parser";
|
||||
|
||||
function Highlight(vm) {
|
||||
this.vm = vm;
|
||||
}
|
||||
|
||||
Highlight.prototype.onParse = function (node, vm) {
|
||||
if (node.name === "pre") {
|
||||
if (vm.options.editable) {
|
||||
node.attrs.class = (node.attrs.class || "") + " hl-pre";
|
||||
return;
|
||||
}
|
||||
let i;
|
||||
for (i = node.children.length; i--; ) {
|
||||
if (node.children[i].name === "code") break;
|
||||
}
|
||||
if (i === -1) return;
|
||||
const code = node.children[i];
|
||||
let className = code.attrs.class + " " + node.attrs.class;
|
||||
i = className.indexOf("language-");
|
||||
if (i === -1) {
|
||||
i = className.indexOf("lang-");
|
||||
if (i === -1) {
|
||||
className = "language-text";
|
||||
i = 9;
|
||||
} else {
|
||||
i += 5;
|
||||
}
|
||||
} else {
|
||||
i += 9;
|
||||
}
|
||||
let j;
|
||||
for (j = i; j < className.length; j++) {
|
||||
if (className[j] === " ") break;
|
||||
}
|
||||
const lang = className.substring(i, j);
|
||||
if (code.children.length) {
|
||||
const text = this.vm.getText(code.children).replace(/&/g, "&")?.trim();
|
||||
if (!text) return;
|
||||
// #ifndef H5
|
||||
// 非 H5 平台:将 pre 节点标记为 c=1,并调用 vm.expose() 向上传播,
|
||||
// 强制整个祖先链使用递归渲染,确保 pre 运在任何嵌套层级中都能被独立渲染
|
||||
node.c = 1;
|
||||
vm.expose();
|
||||
// #endif
|
||||
// #ifdef H5
|
||||
if (node.c) {
|
||||
node.c = undefined;
|
||||
}
|
||||
// #endif
|
||||
if (prism.languages[lang]) {
|
||||
code.children = new Parser(this.vm).parse(
|
||||
// 加一层 pre 保留空白符
|
||||
"<pre>" +
|
||||
prism
|
||||
.highlight(text, prism.languages[lang], lang)
|
||||
.replace(/token /g, "hl-") +
|
||||
"</pre>"
|
||||
)[0].children;
|
||||
}
|
||||
node.attrs.class = "hl-pre";
|
||||
code.attrs.class = "hl-code";
|
||||
// Create hl-body wrapper
|
||||
const hlBody = {
|
||||
name: "div",
|
||||
attrs: { class: "hl-body" },
|
||||
children: []
|
||||
};
|
||||
|
||||
// Create inner hl-container for stretching
|
||||
const hlContainer = {
|
||||
name: "div",
|
||||
attrs: { class: "hl-container" },
|
||||
children: []
|
||||
};
|
||||
|
||||
if (config.showLineNumber) {
|
||||
const line = text.split("\n").length;
|
||||
const children = [];
|
||||
for (let k = 1; k <= line; k++) {
|
||||
children.push({
|
||||
name: "div",
|
||||
attrs: { class: "span" },
|
||||
children: [{ type: "text", text: String(k) }],
|
||||
});
|
||||
}
|
||||
hlContainer.children.push({
|
||||
name: "div",
|
||||
attrs: { class: "line-numbers-rows" },
|
||||
children,
|
||||
});
|
||||
}
|
||||
|
||||
code.name = "div";
|
||||
hlContainer.children.push(code);
|
||||
hlBody.children.push(hlContainer);
|
||||
node.children = [];
|
||||
|
||||
if (config.showLanguageName && vm.options.showHeader) {
|
||||
const langChildren = [{ type: "text", text: lang }];
|
||||
// #ifdef H5
|
||||
// H5: 复制按钮放入 rich-text 内部,通过 srcElement.dataset 实现点击复制
|
||||
langChildren.push({
|
||||
name: "div",
|
||||
attrs: {
|
||||
class: "hl-copy-btn",
|
||||
"data-content": text,
|
||||
"data-action": "copy",
|
||||
},
|
||||
children: [{ type: "text", text: getCopyButtonText() }],
|
||||
});
|
||||
// #endif
|
||||
// #ifndef H5
|
||||
// 非 H5 平台:将代码文本存储到节点上,由 node.vue 渲染真实的可交互复制按钮
|
||||
node._copyText = text;
|
||||
// #endif
|
||||
node.children.push({
|
||||
name: "div",
|
||||
attrs: {
|
||||
class: "hl-language",
|
||||
},
|
||||
children: langChildren,
|
||||
});
|
||||
}
|
||||
if (config.copyByLongPress) {
|
||||
node.attrs.style += (node.attrs.style || "") + ";user-select:none";
|
||||
// node.attrs["data-content"] = text;
|
||||
// vm.expose();
|
||||
}
|
||||
|
||||
node.children.push(hlBody);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default Highlight;
|
||||
@@ -0,0 +1,96 @@
|
||||
/**
|
||||
* @fileoverview Additional Prism grammars for Java, Python, and TypeScript
|
||||
*/
|
||||
export default function (Prism) {
|
||||
// JSON
|
||||
if (!Prism.languages.json) {
|
||||
Prism.languages.json = {
|
||||
'property': {
|
||||
pattern: /"(?:\\.|[^\\"\r\n])*"(?=\s*:)/,
|
||||
greedy: true
|
||||
},
|
||||
'string': {
|
||||
pattern: /"(?:\\.|[^\\"\r\n])*"(?!\s*:)/,
|
||||
greedy: true
|
||||
},
|
||||
'comment': /\/\/.*|\/\*[\s\S]*?\*\//,
|
||||
'number': /-?\d+\.?\d*(?:[eE][+-]?\d+)?/,
|
||||
'punctuation': /[{}[\],]/,
|
||||
'operator': /:/,
|
||||
'boolean': /\b(?:true|false)\b/,
|
||||
'null': /\bnull\b/
|
||||
};
|
||||
}
|
||||
|
||||
// Java
|
||||
if (!Prism.languages.java) {
|
||||
Prism.languages.java = Prism.languages.extend('clike', {
|
||||
'keyword': /\b(?:abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,
|
||||
'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-f]+(?:p[+-]?\d+)?\b|(?:\b\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?[df]?\b/i,
|
||||
'operator': {
|
||||
pattern: /(^|[^.])(?:<<=?|>>>=?|>>=?|==?|!=|&&?|\|\|?|[+*\/%^-]=?|[?:~]|[-+]{1,2})/m,
|
||||
lookbehind: true
|
||||
}
|
||||
});
|
||||
|
||||
Prism.languages.insertBefore('java', 'function', {
|
||||
'annotation': {
|
||||
alias: 'punctuation',
|
||||
pattern: /(^|[^.])@\w+/,
|
||||
lookbehind: true
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Python
|
||||
if (!Prism.languages.python) {
|
||||
Prism.languages.python = {
|
||||
'comment': {
|
||||
pattern: /(^|[^\\])#.*/,
|
||||
lookbehind: true
|
||||
},
|
||||
'string-interpolation': {
|
||||
pattern: /(?:f|rf|fr)(?:"""[\s\S]*?"""|'''[\s\S]*?'''|"(?:\\.|[^\\"\r\n])*"|'(?:\\.|[^\\'\r\n])*')/i,
|
||||
greedy: true,
|
||||
inside: {
|
||||
'interpolation': {
|
||||
pattern: /((?:^|[^{])(?:{{)*){[\s\S]*?}/,
|
||||
lookbehind: true,
|
||||
inside: {
|
||||
'rest': null
|
||||
}
|
||||
},
|
||||
'string': /[\s\S]+/
|
||||
}
|
||||
},
|
||||
'string': {
|
||||
pattern: /(?:[bru]|rb|br)?(?:"""[\s\S]*?"""|'''[\s\S]*?'''|"(?:\\.|[^\\"\r\n])*"|'(?:\\.|[^\\'\r\n])*')/i,
|
||||
greedy: true
|
||||
},
|
||||
'function': {
|
||||
pattern: /((?:^|\s)def\s+)\w+(?=\s*\()/g,
|
||||
lookbehind: true
|
||||
},
|
||||
'class-name': {
|
||||
pattern: /(\bclass\s+)\w+/i,
|
||||
lookbehind: true
|
||||
},
|
||||
'keyword': /\b(?:as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,
|
||||
'builtin': /\b(?:bool|bytearray|bytes|complex|dict|float|frozenset|int|list|set|str|tuple|type|Any|Callable|Dict|List|Optional|Set|Tuple|Union)\b/,
|
||||
'boolean': /\b(?:True|False|None)\b/,
|
||||
'number': /\b(?:\d+\.?\d*(?:[eE][+-]?\d+)?|0x[\da-f]+|0b[01]+|0o[0-7]+)\b/i,
|
||||
'operator': /[-+*/%=<>!&|^~]+/,
|
||||
'punctuation': /[()\[\]{},.:;]/
|
||||
};
|
||||
Prism.languages.python['string-interpolation'].inside['interpolation'].inside.rest = Prism.languages.python;
|
||||
}
|
||||
|
||||
// TypeScript
|
||||
if (!Prism.languages.typescript) {
|
||||
Prism.languages.typescript = Prism.languages.extend('javascript', {
|
||||
'keyword': /\b(?:abstract|as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|is|keyof|let|module|namespace|new|null|of|package|private|protected|public|readonly|return|set|static|super|switch|this|throw|try|type|typeof|var|void|while|with|yield|any|boolean|constructor|declare|never|number|object|string|symbol|unknown)\b/,
|
||||
'operator': /\.[.]{2}|=>|\+\+|--|\*\*|[-+*/%]=?|[!=]=?=?|&&?|\|\|?|[?^%]|~(?!=)/
|
||||
});
|
||||
Prism.languages.ts = Prism.languages.typescript;
|
||||
}
|
||||
}
|
||||
7
qiming-mobile/subpackages/uni_modules/mp-html/components/mp-html/highlight/prism.min.js
vendored
Normal file
7
qiming-mobile/subpackages/uni_modules/mp-html/components/mp-html/highlight/prism.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @fileoverview latex 插件
|
||||
* katex.min.js来源 https://github.com/rojer95/katex-mini
|
||||
*/
|
||||
import parse from "./katex.min";
|
||||
|
||||
function Latex() {}
|
||||
|
||||
Latex.prototype.onParse = function (node, vm) {
|
||||
// $...$包裹的内容为latex公式
|
||||
if (!vm.options.editable && node.type === "text" && node.text.includes("$")) {
|
||||
const part = node.text.split(/(\${1,2})/);
|
||||
const children = [];
|
||||
let status = 0;
|
||||
for (let i = 0; i < part.length; i++) {
|
||||
if (i % 2 === 0) {
|
||||
// 文本内容
|
||||
if (part[i]) {
|
||||
if (status === 0) {
|
||||
children.push({
|
||||
type: "text",
|
||||
text: part[i],
|
||||
});
|
||||
} else {
|
||||
if (status === 1) {
|
||||
// 行内公式
|
||||
const nodes = parse.default(part[i]);
|
||||
children.push({
|
||||
name: "span",
|
||||
attrs: {},
|
||||
l: "T",
|
||||
f: "display:inline-block",
|
||||
children: nodes,
|
||||
});
|
||||
} else {
|
||||
// 块公式
|
||||
const nodes = parse.default(part[i], {
|
||||
displayMode: true,
|
||||
});
|
||||
children.push({
|
||||
name: "div",
|
||||
attrs: {
|
||||
style: "text-align:center",
|
||||
},
|
||||
children: nodes,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 分隔符
|
||||
if (part[i] === "$" && part[i + 2] === "$") {
|
||||
// 行内公式
|
||||
status = 1;
|
||||
part[i + 2] = "";
|
||||
} else if (part[i] === "$$" && part[i + 2] === "$$") {
|
||||
// 块公式
|
||||
status = 2;
|
||||
part[i + 2] = "";
|
||||
} else {
|
||||
if (part[i] && part[i] !== "$$") {
|
||||
// 普通$符号
|
||||
part[i + 1] = part[i] + part[i + 1];
|
||||
}
|
||||
// 重置状态
|
||||
status = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
delete node.type;
|
||||
delete node.text;
|
||||
node.name = "span";
|
||||
node.attrs = {};
|
||||
node.children = children;
|
||||
}
|
||||
};
|
||||
|
||||
export default Latex;
|
||||
1
qiming-mobile/subpackages/uni_modules/mp-html/components/mp-html/latex/katex.min.js
vendored
Normal file
1
qiming-mobile/subpackages/uni_modules/mp-html/components/mp-html/latex/katex.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,129 @@
|
||||
/**
|
||||
* @fileoverview markdown 插件
|
||||
* Include markdown-it (https://github.com/markdown-it/markdown-it)
|
||||
* Include github-markdown-css (https://github.com/sindresorhus/github-markdown-css)
|
||||
*/
|
||||
import MarkdownIt from "markdown-it";
|
||||
import markdownItContainer from "markdown-it-container";
|
||||
let index = 0;
|
||||
|
||||
// 初始化 markdown-it 实例
|
||||
const md = new MarkdownIt({
|
||||
html: true, // 允许 HTML 标签
|
||||
linkify: true, // 自动将 URL 转换为链接
|
||||
typographer: true, // 启用智能排版
|
||||
breaks: false, // 将换行符转换为 <br> 标签
|
||||
langPrefix: "language-",
|
||||
});
|
||||
|
||||
md.use(markdownItContainer, "container", {
|
||||
validate: function (params) {
|
||||
return params.trim().match(/^\s*container\s+(.*)$/);
|
||||
},
|
||||
render: function (tokens, idx) {
|
||||
var m = tokens[idx].info.trim().match(/^container\s+(.*)$/);
|
||||
const data =
|
||||
m?.[1]?.split(" ").reduce((acc, item) => {
|
||||
const [key, value] = item.split("=");
|
||||
// 防止 value 为 undefined 导致 replace 调用失败
|
||||
if (key && value !== undefined) {
|
||||
acc[key] = value.replace(/^"|"$/g, "");
|
||||
}
|
||||
return acc;
|
||||
}, {}) || {};
|
||||
if (tokens[idx].nesting === 1) {
|
||||
// opening tag
|
||||
return `<container data=${JSON.stringify(data)}>`;
|
||||
} else {
|
||||
// closing tag
|
||||
return `</container>`;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
md.use(markdownItContainer, "container-group", {
|
||||
validate: function (params) {
|
||||
return params.trim().match(/^\s*container-group\s*(.*)$/);
|
||||
},
|
||||
render: function (tokens, idx) {
|
||||
if (tokens[idx].nesting === 1) {
|
||||
// opening tag
|
||||
return `<container-group>`;
|
||||
} else {
|
||||
// closing tag
|
||||
return `</container-group>`;
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
md.use(markdownItContainer, "task-result", {
|
||||
validate: function (params) {
|
||||
return params.trim().match(/^task-result\b/);
|
||||
},
|
||||
render: function (tokens, idx) {
|
||||
if (tokens[idx].nesting === 1) {
|
||||
return "<task-result>";
|
||||
} else {
|
||||
return "</task-result>";
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
function Markdown(vm) {
|
||||
this.vm = vm;
|
||||
vm._ids = {};
|
||||
}
|
||||
|
||||
Markdown.prototype.onUpdate = function (content) {
|
||||
if (this.vm.markdown) {
|
||||
// 归一化换行符,防止不同平台下识别失败
|
||||
content = content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
// 解决中文标点符号后粗体失效的问题,增加零宽空格
|
||||
content = content.replace(
|
||||
/\*\*([^*]+)\*\*([,。!?;:])/g,
|
||||
"**$1**​$2"
|
||||
);
|
||||
const result = md.render(content);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
Markdown.prototype.onParse = function (node, vm) {
|
||||
if (vm.options.markdown) {
|
||||
// 中文 id 需要转换,否则无法跳转
|
||||
if (
|
||||
vm.options.useAnchor &&
|
||||
node.attrs &&
|
||||
/[\u4e00-\u9fa5]/.test(node.attrs.id)
|
||||
) {
|
||||
const id = "t" + index++;
|
||||
this.vm._ids[node.attrs.id] = id;
|
||||
node.attrs.id = id;
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
"p",
|
||||
"table",
|
||||
"tr",
|
||||
"th",
|
||||
"td",
|
||||
"blockquote",
|
||||
"pre",
|
||||
"hr",
|
||||
"code",
|
||||
"h1",
|
||||
"h2",
|
||||
"h3",
|
||||
"h4",
|
||||
"h5",
|
||||
"h6",
|
||||
].includes(node.name)
|
||||
) {
|
||||
if (node.name === "table") node.f = "overflow-x: auto;display:block";
|
||||
node.attrs.class = `md-${node.name} ${node.attrs.class || ""}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default Markdown;
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @fileoverview markdown 插件
|
||||
* Include marked (https://github.com/markedjs/marked)
|
||||
* Include github-markdown-css (https://github.com/sindresorhus/github-markdown-css)
|
||||
*/
|
||||
import marked from "./marked.min";
|
||||
let index = 0;
|
||||
|
||||
function Markdown(vm) {
|
||||
this.vm = vm;
|
||||
vm._ids = {};
|
||||
}
|
||||
|
||||
Markdown.prototype.onUpdate = function (content) {
|
||||
if (this.vm.markdown) {
|
||||
// 解决中文标点符号后粗体失效的问题,增加零宽空格
|
||||
content = content.replace(
|
||||
/\*\*([^*]+)\*\*([,。!?;:])/g,
|
||||
"**$1**​$2"
|
||||
);
|
||||
const result = marked(content);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
Markdown.prototype.onParse = function (node, vm) {
|
||||
if (vm.options.markdown) {
|
||||
// 中文 id 需要转换,否则无法跳转
|
||||
if (
|
||||
vm.options.useAnchor &&
|
||||
node.attrs &&
|
||||
/[\u4e00-\u9fa5]/.test(node.attrs.id)
|
||||
) {
|
||||
const id = "t" + index++;
|
||||
this.vm._ids[node.attrs.id] = id;
|
||||
node.attrs.id = id;
|
||||
}
|
||||
if (
|
||||
node.name === "p" ||
|
||||
node.name === "table" ||
|
||||
node.name === "tr" ||
|
||||
node.name === "th" ||
|
||||
node.name === "td" ||
|
||||
node.name === "blockquote" ||
|
||||
node.name === "pre" ||
|
||||
node.name === "code"
|
||||
) {
|
||||
node.attrs.class = `md-${node.name} ${node.attrs.class || ""}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default Markdown;
|
||||
6
qiming-mobile/subpackages/uni_modules/mp-html/components/mp-html/markdown/marked.min.js
vendored
Normal file
6
qiming-mobile/subpackages/uni_modules/mp-html/components/mp-html/markdown/marked.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,523 @@
|
||||
<template>
|
||||
<view id="_root" :class="(selectable ? '_select ' : '') + '_root'" :style="containerStyle">
|
||||
<slot v-if="!nodes[0]" />
|
||||
<!-- #ifndef APP-PLUS-NVUE -->
|
||||
<node v-else :childs="nodes" :processing-list="processingList"
|
||||
:opts="[lazyLoad, loadingImg, errorImg, showImgMenu, selectable]" name="span" />
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-PLUS-NVUE -->
|
||||
<web-view ref="web" src="/static/app-plus/mp-html/local.html" :style="'margin-top:-2px;height:' + height + 'px'"
|
||||
@onPostMessage="_onMessage" />
|
||||
<!-- #endif -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
/**
|
||||
* mp-html v2.5.1
|
||||
* @description 富文本组件
|
||||
* @tutorial https://github.com/jin-yufeng/mp-html
|
||||
* @property {String} container-style 容器的样式
|
||||
* @property {String} content 用于渲染的 html 字符串
|
||||
* @property {Boolean} copy-link 是否允许外部链接被点击时自动复制
|
||||
* @property {String} domain 主域名,用于拼接链接
|
||||
* @property {String} error-img 图片出错时的占位图链接
|
||||
* @property {Boolean} lazy-load 是否开启图片懒加载
|
||||
* @property {string} loading-img 图片加载过程中的占位图链接
|
||||
* @property {Boolean} pause-video 是否在播放一个视频时自动暂停其他视频
|
||||
* @property {Boolean} preview-img 是否允许图片被点击时自动预览
|
||||
* @property {Boolean} scroll-table 是否给每个表格添加一个滚动层使其能单独横向滚动
|
||||
* @property {Boolean | String} selectable 是否开启长按复制
|
||||
* @property {Boolean} set-title 是否将 title 标签的内容设置到页面标题
|
||||
* @property {Boolean} show-img-menu 是否允许图片被长按时显示菜单
|
||||
* @property {Object} tag-style 标签的默认样式
|
||||
* @property {Boolean | Number} use-anchor 是否使用锚点链接
|
||||
* @event {Function} load dom 结构加载完毕时触发
|
||||
* @event {Function} ready 所有图片加载完毕时触发
|
||||
* @event {Function} imgtap 图片被点击时触发
|
||||
* @event {Function} linktap 链接被点击时触发
|
||||
* @event {Function} play 音视频播放时触发
|
||||
* @event {Function} error 媒体加载出错时触发
|
||||
*/
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
import node from './node/node.vue'
|
||||
// #endif
|
||||
import Parser from './parser.js'
|
||||
import markdownIt from './markdown-it/index.js'
|
||||
import highlight from './highlight/index.js'
|
||||
import latex from './latex/index.js'
|
||||
import container from './container/index.js'
|
||||
// import markdown from './markdown/index.js'
|
||||
// const plugins = [markdown, highlight, latex,]
|
||||
const plugins = [markdownIt, highlight, latex, container]
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
const dom = weex.requireModule('dom')
|
||||
// #endif
|
||||
export default {
|
||||
name: 'mp-html',
|
||||
data() {
|
||||
return {
|
||||
nodes: [],
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
height: 3
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
props: {
|
||||
markdown: Boolean,
|
||||
containerStyle: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
processingList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
conversationId: {
|
||||
type: [String, Number],
|
||||
default: ''
|
||||
},
|
||||
copyLink: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
domain: String,
|
||||
errorImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
lazyLoad: {
|
||||
type: [Boolean, String],
|
||||
default: false
|
||||
},
|
||||
loadingImg: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
pauseVideo: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
previewImg: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
scrollTable: [Boolean, String],
|
||||
selectable: [Boolean, String],
|
||||
setTitle: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
showImgMenu: {
|
||||
type: [Boolean, String],
|
||||
default: true
|
||||
},
|
||||
tagStyle: Object,
|
||||
useAnchor: [Boolean, Number],
|
||||
showHeader: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
// #ifdef VUE3
|
||||
emits: ['load', 'ready', 'imgtap', 'linktap', 'play', 'error'],
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
components: {
|
||||
node
|
||||
},
|
||||
// #endif
|
||||
watch: {
|
||||
content(content) {
|
||||
this.setContent(content)
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.plugins = []
|
||||
for (let i = plugins.length; i--;) {
|
||||
this.plugins.push(new plugins[i](this))
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.content && !this.nodes.length) {
|
||||
this.setContent(this.content)
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this._hook('onDetached')
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* @description 将锚点跳转的范围限定在一个 scroll-view 内
|
||||
* @param {Object} page scroll-view 所在页面的示例
|
||||
* @param {String} selector scroll-view 的选择器
|
||||
* @param {String} scrollTop scroll-view scroll-top 属性绑定的变量名
|
||||
*/
|
||||
in(page, selector, scrollTop) {
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
if (page && selector && scrollTop) {
|
||||
this._in = {
|
||||
page,
|
||||
selector,
|
||||
scrollTop
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 锚点跳转
|
||||
* @param {String} id 要跳转的锚点 id
|
||||
* @param {Number} offset 跳转位置的偏移量
|
||||
* @returns {Promise}
|
||||
*/
|
||||
navigateTo(id, offset) {
|
||||
id = this._ids[decodeURI(id)] || id
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.useAnchor) {
|
||||
reject(Error('Anchor is disabled'))
|
||||
return
|
||||
}
|
||||
offset = offset || parseInt(this.useAnchor) || 0
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (!id) {
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset
|
||||
})
|
||||
resolve()
|
||||
} else {
|
||||
this._navigateTo = {
|
||||
resolve,
|
||||
reject,
|
||||
offset
|
||||
}
|
||||
this.$refs.web.evalJs('uni.postMessage({data:{action:"getOffset",offset:(document.getElementById(' + id + ')||{}).offsetTop}})')
|
||||
}
|
||||
// #endif
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
let deep = ' '
|
||||
// #ifdef MP-WEIXIN || MP-QQ || MP-TOUTIAO
|
||||
deep = '>>>'
|
||||
// #endif
|
||||
const selector = uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this._in ? this._in.page : this)
|
||||
// #endif
|
||||
.select((this._in ? this._in.selector : '._root') + (id ? `${deep}#${id}` : '')).boundingClientRect()
|
||||
if (this._in) {
|
||||
selector.select(this._in.selector).scrollOffset()
|
||||
.select(this._in.selector).boundingClientRect()
|
||||
} else {
|
||||
// 获取 scroll-view 的位置和滚动距离
|
||||
selector.selectViewport().scrollOffset() // 获取窗口的滚动距离
|
||||
}
|
||||
selector.exec(res => {
|
||||
if (!res[0]) {
|
||||
reject(Error('Label not found'))
|
||||
return
|
||||
}
|
||||
const scrollTop = res[1].scrollTop + res[0].top - (res[2] ? res[2].top : 0) + offset
|
||||
if (this._in) {
|
||||
// scroll-view 跳转
|
||||
this._in.page[this._in.scrollTop] = scrollTop
|
||||
} else {
|
||||
// 页面跳转
|
||||
uni.pageScrollTo({
|
||||
scrollTop,
|
||||
duration: 300
|
||||
})
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
// #endif
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 获取文本内容
|
||||
* @return {String}
|
||||
*/
|
||||
getText(nodes) {
|
||||
let text = '';
|
||||
(function traversal(nodes) {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
const node = nodes[i]
|
||||
if (node.type === 'text') {
|
||||
text += node.text.replace(/&/g, '&')
|
||||
} else if (node.name === 'br') {
|
||||
text += '\n'
|
||||
} else {
|
||||
// 块级标签前后加换行
|
||||
const isBlock = node.name === 'p' || node.name === 'div' || node.name === 'tr' || node.name === 'li' || (node.name[0] === 'h' && node.name[1] > '0' && node.name[1] < '7')
|
||||
if (isBlock && text && text[text.length - 1] !== '\n') {
|
||||
text += '\n'
|
||||
}
|
||||
// 递归获取子节点的文本
|
||||
if (node.children) {
|
||||
traversal(node.children)
|
||||
}
|
||||
if (isBlock && text[text.length - 1] !== '\n') {
|
||||
text += '\n'
|
||||
} else if (node.name === 'td' || node.name === 'th') {
|
||||
text += '\t'
|
||||
}
|
||||
}
|
||||
}
|
||||
})(nodes || this.nodes)
|
||||
return text
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 获取内容大小和位置
|
||||
* @return {Promise}
|
||||
*/
|
||||
getRect() {
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.createSelectorQuery()
|
||||
// #ifndef MP-ALIPAY
|
||||
.in(this)
|
||||
// #endif
|
||||
.select('#_root').boundingClientRect().exec(res => res[0] ? resolve(res[0]) : reject(Error('Root label not found')))
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 暂停播放媒体
|
||||
*/
|
||||
pauseMedia() {
|
||||
for (let i = (this._videos || []).length; i--;) {
|
||||
this._videos[i].pause()
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].pause()'
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
let page = this.$parent
|
||||
while (!page.$scope) page = page.$parent
|
||||
page.$scope.$getAppWebview().evalJS(command)
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.$refs.web.evalJs(command)
|
||||
// #endif
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置媒体播放速率
|
||||
* @param {Number} rate 播放速率
|
||||
*/
|
||||
setPlaybackRate(rate) {
|
||||
this.playbackRate = rate
|
||||
for (let i = (this._videos || []).length; i--;) {
|
||||
this._videos[i].playbackRate(rate)
|
||||
}
|
||||
// #ifdef APP-PLUS
|
||||
const command = 'for(var e=document.getElementsByTagName("video"),i=e.length;i--;)e[i].playbackRate=' + rate
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
let page = this.$parent
|
||||
while (!page.$scope) page = page.$parent
|
||||
page.$scope.$getAppWebview().evalJS(command)
|
||||
// #endif
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
this.$refs.web.evalJs(command)
|
||||
// #endif
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 设置内容
|
||||
* @param {String} content html 内容
|
||||
* @param {Boolean} append 是否在尾部追加
|
||||
*/
|
||||
setContent(content, append) {
|
||||
if (!append || !this.imgList) {
|
||||
this.imgList = []
|
||||
}
|
||||
const nodes = new Parser(this).parse(content)
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
if (this._ready) {
|
||||
this._set(nodes, append)
|
||||
}
|
||||
// #endif
|
||||
this.$set(this, 'nodes', append ? (this.nodes || []).concat(nodes) : nodes)
|
||||
|
||||
// #ifndef APP-PLUS-NVUE
|
||||
this._videos = []
|
||||
this.$nextTick(() => {
|
||||
this._hook('onLoad')
|
||||
this.$emit('load')
|
||||
})
|
||||
|
||||
if (this.lazyLoad || this.imgList._unloadimgs < this.imgList.length / 2) {
|
||||
// 设置懒加载,每 350ms 获取高度,不变则认为加载完毕
|
||||
let height = 0
|
||||
const callback = rect => {
|
||||
if (!rect || !rect.height) rect = {}
|
||||
// 350ms 总高度无变化就触发 ready 事件
|
||||
if (rect.height === height) {
|
||||
this.$emit('ready', rect)
|
||||
} else {
|
||||
height = rect.height
|
||||
setTimeout(() => {
|
||||
this.getRect().then(callback).catch(callback)
|
||||
}, 350)
|
||||
}
|
||||
}
|
||||
this.getRect().then(callback).catch(callback)
|
||||
} else {
|
||||
// 未设置懒加载,等待所有图片加载完毕
|
||||
if (!this.imgList._unloadimgs) {
|
||||
this.getRect().then(rect => {
|
||||
this.$emit('ready', rect)
|
||||
}).catch(() => {
|
||||
this.$emit('ready', {})
|
||||
})
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 调用插件钩子函数
|
||||
*/
|
||||
_hook(name) {
|
||||
for (let i = plugins.length; i--;) {
|
||||
if (this.plugins[i][name]) {
|
||||
this.plugins[i][name]()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// #ifdef APP-PLUS-NVUE
|
||||
/**
|
||||
* @description 设置内容
|
||||
*/
|
||||
_set(nodes, append) {
|
||||
this.$refs.web.evalJs('setContent(' + JSON.stringify(nodes).replace(/%22/g, '') + ',' + JSON.stringify([this.containerStyle.replace(/(?:margin|padding)[^;]+/g, ''), this.errorImg, this.loadingImg, this.pauseVideo, this.scrollTable, this.selectable]) + ',' + append + ')')
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 接收到 web-view 消息
|
||||
*/
|
||||
_onMessage(e) {
|
||||
const message = e.detail.data[0]
|
||||
switch (message.action) {
|
||||
// web-view 初始化完毕
|
||||
case 'onJSBridgeReady':
|
||||
this._ready = true
|
||||
if (this.nodes) {
|
||||
this._set(this.nodes)
|
||||
}
|
||||
break
|
||||
// 内容 dom 加载完毕
|
||||
case 'onLoad':
|
||||
this.height = message.height
|
||||
this._hook('onLoad')
|
||||
this.$emit('load')
|
||||
break
|
||||
// 所有图片加载完毕
|
||||
case 'onReady':
|
||||
this.getRect().then(res => {
|
||||
this.$emit('ready', res)
|
||||
}).catch(() => {
|
||||
this.$emit('ready', {})
|
||||
})
|
||||
break
|
||||
// 总高度发生变化
|
||||
case 'onHeightChange':
|
||||
this.height = message.height
|
||||
break
|
||||
// 图片点击
|
||||
case 'onImgTap':
|
||||
this.$emit('imgtap', message.attrs)
|
||||
if (this.previewImg) {
|
||||
uni.previewImage({
|
||||
current: parseInt(message.attrs.i),
|
||||
urls: this.imgList
|
||||
})
|
||||
}
|
||||
break
|
||||
// 链接点击
|
||||
case 'onLinkTap': {
|
||||
const href = message.attrs.href
|
||||
this.$emit('linktap', message.attrs)
|
||||
if (href) {
|
||||
// 锚点跳转
|
||||
if (href[0] === '#') {
|
||||
if (this.useAnchor) {
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset: message.offset
|
||||
})
|
||||
}
|
||||
} else if (href.includes('://')) {
|
||||
// 打开外链
|
||||
if (this.copyLink) {
|
||||
plus.runtime.openWeb(href)
|
||||
}
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: href,
|
||||
fail() {
|
||||
uni.switchTab({
|
||||
url: href
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
case 'onPlay':
|
||||
this.$emit('play')
|
||||
break
|
||||
// 获取到锚点的偏移量
|
||||
case 'getOffset':
|
||||
if (typeof message.offset === 'number') {
|
||||
dom.scrollToElement(this.$refs.web, {
|
||||
offset: message.offset + this._navigateTo.offset
|
||||
})
|
||||
this._navigateTo.resolve()
|
||||
} else {
|
||||
this._navigateTo.reject(Error('Label not found'))
|
||||
}
|
||||
break
|
||||
// 点击
|
||||
case 'onClick':
|
||||
this.$emit('tap')
|
||||
this.$emit('click')
|
||||
break
|
||||
// 出错
|
||||
case 'onError':
|
||||
this.$emit('error', {
|
||||
source: message.source,
|
||||
attrs: message.attrs
|
||||
})
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* #ifndef APP-PLUS-NVUE */
|
||||
/* 根节点样式 */
|
||||
._root {
|
||||
padding: 1px 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
color: rgb(64, 64, 64);
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* 长按复制 */
|
||||
._select {
|
||||
user-select: text;
|
||||
}
|
||||
|
||||
/* #endif */
|
||||
</style>
|
||||
@@ -0,0 +1,893 @@
|
||||
<template>
|
||||
<view
|
||||
:id="attrs.id"
|
||||
:class="'_block _' + name + ' ' + attrs.class"
|
||||
:style="attrs.style"
|
||||
>
|
||||
<block v-for="(n, i) in childs" v-bind:key="i">
|
||||
<!-- 图片 -->
|
||||
<!-- 占位图 -->
|
||||
<image
|
||||
v-if="
|
||||
n.name === 'img' && !n.t && ((opts[1] && !ctrl[i]) || ctrl[i] < 0)
|
||||
"
|
||||
class="_img"
|
||||
:style="n.attrs.style"
|
||||
:src="ctrl[i] < 0 ? opts[2] : opts[1]"
|
||||
mode="widthFix"
|
||||
/>
|
||||
<!-- 显示图片 -->
|
||||
<!-- #ifdef H5 || (APP-PLUS && VUE2) -->
|
||||
<img
|
||||
v-if="n.name === 'img'"
|
||||
:id="n.attrs.id"
|
||||
:class="'_img ' + n.attrs.class"
|
||||
:style="(ctrl[i] === -1 ? 'display:none;' : '') + n.attrs.style"
|
||||
:src="n.attrs.src || (ctrl.load ? n.attrs['data-src'] : '')"
|
||||
:data-i="i"
|
||||
@load="imgLoad"
|
||||
@error="mediaError"
|
||||
@tap.stop="imgTap"
|
||||
@longpress="imgLongTap"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 || (APP-PLUS && VUE2) -->
|
||||
<!-- 表格中的图片,使用 rich-text 防止大小不正确 -->
|
||||
<rich-text
|
||||
v-if="n.name === 'img' && n.t"
|
||||
:style="'display:' + n.t"
|
||||
:nodes="[
|
||||
{
|
||||
attrs: { style: n.attrs.style || '', src: n.attrs.src },
|
||||
name: 'img',
|
||||
},
|
||||
]"
|
||||
:data-i="i"
|
||||
@tap.stop="imgTap"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-HARMONY -->
|
||||
<image
|
||||
v-else-if="n.name === 'img'"
|
||||
:id="n.attrs.id"
|
||||
:class="'_img ' + n.attrs.class"
|
||||
:style="
|
||||
(ctrl[i] === -1 ? 'display:none;' : '') +
|
||||
'width:' +
|
||||
ctrl[i] +
|
||||
'px;' +
|
||||
n.attrs.style
|
||||
"
|
||||
:src="n.attrs.src || (ctrl.load ? n.attrs['data-src'] : '')"
|
||||
:mode="!n.h ? 'widthFix' : !n.w ? 'heightFix' : n.m || 'scaleToFill'"
|
||||
:data-i="i"
|
||||
@load="imgLoad"
|
||||
@error="mediaError"
|
||||
@tap.stop="imgTap"
|
||||
@longpress="imgLongTap"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 || APP-PLUS || MP-KUAISHOU -->
|
||||
<image
|
||||
v-else-if="n.name === 'img'"
|
||||
: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"
|
||||
:image-menu-prevent="!opts[3] || n.attrs.ignore"
|
||||
:data-i="i"
|
||||
@load="imgLoad"
|
||||
@error="mediaError"
|
||||
@tap.stop="imgTap"
|
||||
@longpress="imgLongTap"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef MP-KUAISHOU -->
|
||||
<image
|
||||
v-else-if="n.name === 'img'"
|
||||
:id="n.attrs.id"
|
||||
:class="'_img ' + n.attrs.class"
|
||||
:style="(ctrl[i] === -1 ? 'display:none;' : '') + n.attrs.style"
|
||||
:src="n.attrs.src"
|
||||
:lazy-load="opts[0]"
|
||||
:data-i="i"
|
||||
@load="imgLoad"
|
||||
@error="mediaError"
|
||||
@tap.stop="imgTap"
|
||||
></image>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef APP-PLUS && VUE3 -->
|
||||
<image
|
||||
v-else-if="n.name === 'img'"
|
||||
:id="n.attrs.id"
|
||||
:class="'_img ' + n.attrs.class"
|
||||
:style="
|
||||
(ctrl[i] === -1 ? 'display:none;' : '') +
|
||||
'width:' +
|
||||
(ctrl[i] || 1) +
|
||||
'px;' +
|
||||
n.attrs.style
|
||||
"
|
||||
:src="n.attrs.src || (ctrl.load ? n.attrs['data-src'] : '')"
|
||||
:mode="!n.h ? 'widthFix' : !n.w ? 'heightFix' : n.m || ''"
|
||||
:data-i="i"
|
||||
@load="imgLoad"
|
||||
@error="mediaError"
|
||||
@tap.stop="imgTap"
|
||||
@longpress="imgLongTap"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- 文本 -->
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<text
|
||||
v-else-if="n.text"
|
||||
:user-select="opts[4] == 'force' && isiOS"
|
||||
decode
|
||||
>{{ n.text }}</text
|
||||
>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-WEIXIN || MP-BAIDU || MP-ALIPAY || MP-TOUTIAO -->
|
||||
<text v-else-if="n.text" decode>{{ n.text }}</text>
|
||||
<!-- #endif -->
|
||||
<text v-else-if="n.name === 'br'">{{ "\n" }}</text>
|
||||
<!-- 链接 -->
|
||||
<view
|
||||
v-else-if="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"
|
||||
@tap.stop="linkTap"
|
||||
>
|
||||
<node
|
||||
name="span"
|
||||
:childs="n.children"
|
||||
:opts="opts"
|
||||
style="display: inherit"
|
||||
/>
|
||||
</view>
|
||||
<!-- 视频 -->
|
||||
<!-- #ifdef APP-PLUS -->
|
||||
<view
|
||||
v-else-if="n.html"
|
||||
:id="n.attrs.id"
|
||||
:class="'_video ' + n.attrs.class"
|
||||
:style="n.attrs.style"
|
||||
v-html="n.html"
|
||||
:data-i="i"
|
||||
@vplay.stop="play"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef APP-PLUS -->
|
||||
<video
|
||||
v-else-if="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"
|
||||
@play="play"
|
||||
@error="mediaError"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifdef H5 || APP-PLUS -->
|
||||
<iframe
|
||||
v-else-if="n.name === 'iframe'"
|
||||
:style="n.attrs.style"
|
||||
:allowfullscreen="n.attrs.allowfullscreen"
|
||||
:frameborder="n.attrs.frameborder"
|
||||
:src="n.attrs.src"
|
||||
/>
|
||||
<embed
|
||||
v-else-if="n.name === 'embed'"
|
||||
:style="n.attrs.style"
|
||||
:src="n.attrs.src"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef MP-TOUTIAO || ((H5 || APP-PLUS) && VUE3) -->
|
||||
<!-- 音频 -->
|
||||
<audio
|
||||
v-else-if="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"
|
||||
@play="play"
|
||||
@error="mediaError"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<view
|
||||
v-else-if="(n.name === 'table' && n.c) || n.name === 'li'"
|
||||
:id="n.attrs.id"
|
||||
:class="'_' + n.name + ' ' + n.attrs.class"
|
||||
:style="n.attrs.style"
|
||||
>
|
||||
<node v-if="n.name === 'li'" :childs="n.children" :opts="opts" />
|
||||
<view
|
||||
v-else
|
||||
v-for="(tbody, x) in n.children"
|
||||
v-bind:key="x"
|
||||
:class="'_' + tbody.name + ' ' + tbody.attrs.class"
|
||||
:style="tbody.attrs.style"
|
||||
>
|
||||
<node
|
||||
v-if="tbody.name === 'td' || tbody.name === 'th'"
|
||||
:childs="tbody.children"
|
||||
:opts="opts"
|
||||
/>
|
||||
<block v-else v-for="(tr, y) in tbody.children" v-bind:key="y">
|
||||
<view
|
||||
v-if="tr.name === 'td' || tr.name === 'th'"
|
||||
:class="'_' + tr.name + ' ' + tr.attrs.class"
|
||||
:style="tr.attrs.style"
|
||||
>
|
||||
<node :childs="tr.children" :opts="opts" />
|
||||
</view>
|
||||
<view
|
||||
v-else
|
||||
:class="'_' + tr.name + ' ' + tr.attrs.class"
|
||||
:style="tr.attrs.style"
|
||||
>
|
||||
<view
|
||||
v-for="(td, z) in tr.children"
|
||||
v-bind:key="z"
|
||||
:class="'_' + td.name + ' ' + td.attrs.class"
|
||||
:style="td.attrs.style"
|
||||
>
|
||||
<node :childs="td.children" :opts="opts" />
|
||||
</view>
|
||||
</view>
|
||||
</block>
|
||||
</view>
|
||||
</view>
|
||||
<markdown-container
|
||||
v-else-if="n.name == 'container'"
|
||||
:data="getRenderData(n.attrs.data)"
|
||||
data-source="markdown-container"
|
||||
/>
|
||||
<!-- markdown-custom-process 工具调用组件 -->
|
||||
<markdown-container
|
||||
v-else-if="n.name == 'markdown-custom-process'"
|
||||
:data="getRenderData(n.attrs)"
|
||||
data-source="markdown-container"
|
||||
/>
|
||||
<markdown-container-group
|
||||
v-else-if="n.name == 'container-group' || n.name == 'markdown-custom-process-group'"
|
||||
:childs="n.children"
|
||||
>
|
||||
<node :childs="n.children" :opts="opts" :processing-list="processingList" />
|
||||
</markdown-container-group>
|
||||
<!-- task-result 任务结果组件 -->
|
||||
<task-result
|
||||
v-else-if="n.name === 'task-result'"
|
||||
:data="n"
|
||||
:conversation-id="getConversationId()"
|
||||
/>
|
||||
<!-- 富文本 -->
|
||||
<!-- #ifdef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
|
||||
<rich-text
|
||||
v-else-if="!n.c && (n.l || !handler.isInline(n.name, n.attrs.style))"
|
||||
:id="n.attrs.id"
|
||||
:style="n.f"
|
||||
:user-select="opts[4]"
|
||||
:nodes="[n]"
|
||||
@tap="copyCode"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- #ifndef H5 || ((MP-WEIXIN || MP-QQ || APP-PLUS || MP-360) && VUE2) -->
|
||||
<!-- hl-language 头部节点:将 rich-text 和原生复制按钮并排在同一行,避免给对布局的依赖 -->
|
||||
<view
|
||||
v-else-if="
|
||||
!n.c && n.attrs && n.attrs.class === 'hl-language' && copyText
|
||||
"
|
||||
class="hl-language-native"
|
||||
>
|
||||
<text class="hl-language-name">{{
|
||||
(n.children && n.children[0] && n.children[0].text) || ""
|
||||
}}</text>
|
||||
<view class="hl-copy-btn-native" @tap.stop="doCopyText(copyText)">
|
||||
<text class="hl-copy-btn-text">{{
|
||||
getI18nText("Mobile.ThirdParty.MpHtml.copyCode")
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<rich-text
|
||||
v-else-if="!n.c"
|
||||
:id="n.attrs.id"
|
||||
:style="'display:inline;' + n.f"
|
||||
:class="
|
||||
n.name === 'div' && n.attrs?.class === 'event'
|
||||
? 'div-event-style'
|
||||
: ''
|
||||
"
|
||||
:preview="false"
|
||||
:selectable="opts[4]"
|
||||
:user-select="opts[4]"
|
||||
:nodes="[n]"
|
||||
@tap="handleCurrentTap(n)"
|
||||
/>
|
||||
<!-- #endif -->
|
||||
<!-- 继续递归 -->
|
||||
<view
|
||||
v-else-if="n.c === 2"
|
||||
:id="n.attrs.id"
|
||||
:class="'_block _' + n.name + ' ' + n.attrs.class"
|
||||
:style="n.f + ';' + n.attrs.style"
|
||||
>
|
||||
<node
|
||||
v-for="(n2, j) in n.children"
|
||||
v-bind:key="j"
|
||||
:style="n2.f"
|
||||
:name="n2.name"
|
||||
:attrs="n2.attrs"
|
||||
:childs="n2.children"
|
||||
:opts="opts"
|
||||
:copy-text="n2._copyText"
|
||||
/>
|
||||
</view>
|
||||
<node
|
||||
v-else
|
||||
:style="n.f"
|
||||
:name="n.name"
|
||||
:attrs="n.attrs"
|
||||
:childs="n.children"
|
||||
:opts="opts"
|
||||
:copy-text="n._copyText"
|
||||
/>
|
||||
</block>
|
||||
</view>
|
||||
</template>
|
||||
<script module="handler" lang="wxs">
|
||||
// 行内标签列表
|
||||
var inlineTags = {
|
||||
abbr: true,
|
||||
b: true,
|
||||
big: true,
|
||||
code: true,
|
||||
del: true,
|
||||
em: true,
|
||||
i: true,
|
||||
ins: true,
|
||||
label: true,
|
||||
q: true,
|
||||
small: true,
|
||||
span: true,
|
||||
strong: true,
|
||||
sub: true,
|
||||
sup: true,
|
||||
};
|
||||
/**
|
||||
* @description 判断是否为行内标签
|
||||
*/
|
||||
module.exports = {
|
||||
isInline: function (tagName, style) {
|
||||
return (
|
||||
inlineTags[tagName] || (style || "").indexOf("display:inline") !== -1
|
||||
);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
import markdownContainer from '../container/container.vue'
|
||||
import markdownContainerGroup from '../container/container-group.vue'
|
||||
import taskResult from '../task-result/task-result.vue'
|
||||
import { getProcessingDataByPriority } from '../container/utils'
|
||||
import node from './node'
|
||||
import { t } from '@/utils/i18n'
|
||||
export default {
|
||||
name: 'node',
|
||||
options: {
|
||||
// #ifdef MP-WEIXIN
|
||||
virtualHost: true,
|
||||
// #endif
|
||||
// #ifdef MP-TOUTIAO
|
||||
addGlobalClass: false
|
||||
// #endif
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
ctrl: {},
|
||||
root: null, // Initialize root to prevent "not defined" warning during render
|
||||
// #ifdef MP-WEIXIN
|
||||
isiOS: uni.getDeviceInfo().system.includes('iOS')
|
||||
// #endif
|
||||
}
|
||||
},
|
||||
props: {
|
||||
name: String,
|
||||
processingList: Array,
|
||||
attrs: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
childs: Array,
|
||||
opts: Array,
|
||||
copyText: String
|
||||
},
|
||||
components: {
|
||||
markdownContainer,
|
||||
markdownContainerGroup,
|
||||
taskResult,
|
||||
// #ifndef ((H5 || APP-PLUS) && VUE3) || APP-HARMONY
|
||||
node
|
||||
// #endif
|
||||
},
|
||||
mounted () {
|
||||
this.$nextTick(() => {
|
||||
for (this.root = this.$parent; this.root.$options.name !== 'mp-html'; this.root = this.root.$parent);
|
||||
})
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (this.opts[0]) {
|
||||
let i
|
||||
for (i = this.childs.length; i--;) {
|
||||
if (this.childs[i].name === 'img') break
|
||||
}
|
||||
if (i !== -1) {
|
||||
this.observer = uni.createIntersectionObserver(this).relativeToViewport({
|
||||
top: 500,
|
||||
bottom: 500
|
||||
})
|
||||
this.observer.observe('._img', res => {
|
||||
if (res.intersectionRatio) {
|
||||
this.$set(this.ctrl, 'load', 1)
|
||||
this.observer.disconnect()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
beforeDestroy () {
|
||||
// #ifdef H5 || APP-PLUS
|
||||
if (this.observer) {
|
||||
this.observer.disconnect()
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
methods:{
|
||||
getI18nText (key) {
|
||||
return t(key)
|
||||
},
|
||||
showTextToast (title) {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: 'none'
|
||||
})
|
||||
},
|
||||
/**
|
||||
* 获取会话ID(用于task-result等组件)
|
||||
*/
|
||||
getConversationId() {
|
||||
// 尝试从根组件获取会话ID
|
||||
if (this.root && this.root.conversationId) {
|
||||
return this.root.conversationId
|
||||
}
|
||||
// 尝试从mp-html组件获取
|
||||
for (let parent = this.$parent; parent; parent = parent.$parent) {
|
||||
if (parent.conversationId) {
|
||||
return parent.conversationId
|
||||
}
|
||||
}
|
||||
return ''
|
||||
},
|
||||
getRenderData (data: any) {
|
||||
if(!data) {
|
||||
return {}
|
||||
}
|
||||
|
||||
if(typeof data === 'string') {
|
||||
try {
|
||||
data = JSON.parse(data)
|
||||
} catch (e) {
|
||||
console.warn('[mp-html/node] getRenderData JSON.parse error:', e, 'data:', data)
|
||||
return {} // Return empty object on parse failure
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure data is an object before spreading
|
||||
if (typeof data !== 'object' || data === null) {
|
||||
return {}
|
||||
}
|
||||
|
||||
const result = {
|
||||
...data,
|
||||
// 在 HTML 解析过程中,mp-html 的解析器会将属性名自动转为全小写,也就是 executeid
|
||||
...getProcessingDataByPriority(data.executeId || data.executeid, this.processingList)
|
||||
}
|
||||
|
||||
return result
|
||||
},
|
||||
// #ifdef MP-WEIXIN
|
||||
toJSON () { return this },
|
||||
// #endif
|
||||
/**
|
||||
* @description 播放视频事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
play (e) {
|
||||
const i = e.currentTarget.dataset.i
|
||||
const node = this.childs[i]
|
||||
this.root.$emit('play', {
|
||||
source: node.name,
|
||||
attrs: {
|
||||
...node.attrs,
|
||||
src: node.src[this.ctrl[i] || 0]
|
||||
}
|
||||
})
|
||||
// #ifndef APP-PLUS
|
||||
if (this.root.pauseVideo) {
|
||||
let flag = false
|
||||
const id = e.target.id
|
||||
for (let i = this.root._videos.length; i--;) {
|
||||
if (this.root._videos[i].id === id) {
|
||||
flag = true
|
||||
} else {
|
||||
this.root._videos[i].pause() // 自动暂停其他视频
|
||||
}
|
||||
}
|
||||
// 将自己加入列表
|
||||
if (!flag) {
|
||||
const ctx = uni.createVideoContext(id
|
||||
// #ifndef MP-BAIDU
|
||||
, this
|
||||
// #endif
|
||||
)
|
||||
ctx.id = id
|
||||
if (this.root.playbackRate) {
|
||||
ctx.playbackRate(this.root.playbackRate)
|
||||
}
|
||||
this.root._videos.push(ctx)
|
||||
}
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
imgTap (e) {
|
||||
const node = this.childs[e.currentTarget.dataset.i]
|
||||
if (node.a) {
|
||||
this.linkTap(node.a)
|
||||
return
|
||||
}
|
||||
if (node.attrs.ignore) return
|
||||
// #ifdef H5 || APP-PLUS
|
||||
node.attrs.src = node.attrs.src || node.attrs['data-src']
|
||||
// #endif
|
||||
// #ifndef APP-HARMONY
|
||||
this.root.$emit('imgtap', node.attrs)
|
||||
// #endif
|
||||
// #ifdef APP-HARMONY
|
||||
this.root.$emit('imgtap', {
|
||||
...node.attrs
|
||||
})
|
||||
// #endif
|
||||
// 自动预览图片
|
||||
if (this.root.previewImg) {
|
||||
uni.previewImage({
|
||||
// #ifdef MP-WEIXIN
|
||||
showmenu: this.root.showImgMenu,
|
||||
// #endif
|
||||
// #ifdef MP-ALIPAY
|
||||
enablesavephoto: this.root.showImgMenu,
|
||||
enableShowPhotoDownload: this.root.showImgMenu,
|
||||
// #endif
|
||||
current: parseInt(node.attrs.i),
|
||||
urls: this.root.imgList
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片长按
|
||||
*/
|
||||
imgLongTap (e) {
|
||||
// #ifdef APP-PLUS
|
||||
const attrs = this.childs[e.currentTarget.dataset.i].attrs
|
||||
if (this.opts[3] && !attrs.ignore) {
|
||||
uni.showActionSheet({
|
||||
itemList: ['保存图片'],
|
||||
success: () => {
|
||||
const save = path => {
|
||||
uni.saveImageToPhotosAlbum({
|
||||
filePath: path,
|
||||
success: () => {
|
||||
this.showTextToast(t('Mobile.ThirdParty.MpHtml.saveSuccess'))
|
||||
}
|
||||
})
|
||||
}
|
||||
if (this.root.imgList[attrs.i].startsWith('http')) {
|
||||
uni.downloadFile({
|
||||
url: this.root.imgList[attrs.i],
|
||||
success: res => save(res.tempFilePath)
|
||||
})
|
||||
} else {
|
||||
save(this.root.imgList[attrs.i])
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// #endif
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 图片加载完成事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
imgLoad (e) {
|
||||
const i = e.currentTarget.dataset.i
|
||||
/* #ifndef H5 || (APP-PLUS && VUE2) */
|
||||
if (!this.childs[i].w) {
|
||||
// 设置原宽度
|
||||
this.$set(this.ctrl, i, e.detail.width)
|
||||
} else /* #endif */ if ((this.opts[1] && !this.ctrl[i]) || this.ctrl[i] === -1) {
|
||||
// 加载完毕,取消加载中占位图
|
||||
this.$set(this.ctrl, i, 1)
|
||||
}
|
||||
this.checkReady()
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 检查是否所有图片加载完毕
|
||||
*/
|
||||
checkReady () {
|
||||
if (this.root && !this.root.lazyLoad) {
|
||||
this.root._unloadimgs -= 1
|
||||
if (!this.root._unloadimgs) {
|
||||
setTimeout(() => {
|
||||
this.root.getRect().then(rect => {
|
||||
this.root.$emit('ready', rect)
|
||||
}).catch(() => {
|
||||
this.root.$emit('ready', {})
|
||||
})
|
||||
}, 350)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 链接点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
linkTap (e) {
|
||||
const node = e.currentTarget ? this.childs[e.currentTarget.dataset.i] : {}
|
||||
const attrs = node.attrs || e
|
||||
const href = attrs.href
|
||||
this.root.$emit('linktap', Object.assign({
|
||||
innerText: this.root.getText(node.children || []) // 链接内的文本内容
|
||||
}, attrs))
|
||||
if (href) {
|
||||
if (href[0] === '#') {
|
||||
// 跳转锚点
|
||||
this.root.navigateTo(href.substring(1)).catch(() => { })
|
||||
} else if (href.split('?')[0].includes('://')) {
|
||||
// 复制外部链接
|
||||
if (this.root.copyLink) {
|
||||
// #ifdef H5
|
||||
window.open(href)
|
||||
// #endif
|
||||
// #ifdef MP
|
||||
uni.setClipboardData({
|
||||
data: href,
|
||||
success: () => this.showTextToast(t('Mobile.Link.copied'))
|
||||
})
|
||||
// #endif
|
||||
// #ifdef APP-PLUS
|
||||
plus.runtime.openWeb(href)
|
||||
// #endif
|
||||
}
|
||||
} else {
|
||||
// 跳转页面
|
||||
uni.navigateTo({
|
||||
url: href,
|
||||
fail () {
|
||||
uni.switchTab({
|
||||
url: href,
|
||||
fail () { }
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 复制代码事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
copyCode (e) {
|
||||
// srcElement \u5728\u5fae\u4fe1\u5c0f\u7a0b\u5e8f\u4e2d\u4e0d\u5b58\u5728\uff0c\u52a0\u5b89\u5168\u8bbf\u95ee
|
||||
const data = (e.srcElement && e.srcElement.dataset) || (e.currentTarget && e.currentTarget.dataset)
|
||||
if(!data || data.action !== 'copy') {
|
||||
return
|
||||
}
|
||||
const content = data.content
|
||||
|
||||
if (content) {
|
||||
// 实现复制到剪贴板功能
|
||||
uni.setClipboardData({
|
||||
data: content,
|
||||
success: () => {
|
||||
this.showTextToast(t('Mobile.Common.copySuccess'))
|
||||
},
|
||||
fail: () => {
|
||||
this.showTextToast(t('Mobile.Common.copyFailed'))
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
/**
|
||||
* @description 当前节点点击事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
handleCurrentTap(e){
|
||||
// #ifdef MP-WEIXIN
|
||||
if (e.name==='div' && e.attrs?.class==='event') {
|
||||
uni.$emit('message-event-delegate', e)
|
||||
return
|
||||
}
|
||||
// #endif
|
||||
|
||||
// Handle copy code button in highlight blocks
|
||||
if (e.attrs?.['data-action'] === 'copy' && e.attrs?.['data-content']) {
|
||||
uni.setClipboardData({
|
||||
data: e.attrs['data-content'],
|
||||
success: () => {
|
||||
this.showTextToast(t('Mobile.Common.copySuccess'))
|
||||
},
|
||||
fail: () => {
|
||||
this.showTextToast(t('Mobile.Common.copyFailed'))
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 复制代码文本(非 H5 平台使用)
|
||||
* @param {String} text
|
||||
*/
|
||||
doCopyText (text) {
|
||||
if (!text) return
|
||||
uni.setClipboardData({
|
||||
data: text,
|
||||
success: () => {
|
||||
this.showTextToast(t('Mobile.Common.copySuccess'))
|
||||
},
|
||||
fail: () => {
|
||||
this.showTextToast(t('Mobile.Common.copyFailed'))
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
/**
|
||||
* @description 错误事件
|
||||
* @param {Event} e
|
||||
*/
|
||||
mediaError (e) {
|
||||
const i = e.currentTarget.dataset.i
|
||||
const node = this.childs[i]
|
||||
// 加载其他源
|
||||
if (node.name === 'video' || node.name === 'audio') {
|
||||
let index = (this.ctrl[i] || 0) + 1
|
||||
if (index > node.src.length) {
|
||||
index = 0
|
||||
}
|
||||
if (index < node.src.length) {
|
||||
this.$set(this.ctrl, i, index)
|
||||
return
|
||||
}
|
||||
} else if (node.name === 'img') {
|
||||
// #ifdef H5 && VUE3
|
||||
if (this.opts[0] && !this.ctrl.load) return
|
||||
// #endif
|
||||
// 显示错误占位图
|
||||
if (this.opts[2]) {
|
||||
this.$set(this.ctrl, i, -1)
|
||||
}
|
||||
this.checkReady()
|
||||
}
|
||||
if (this.root) {
|
||||
this.root.$emit('error', {
|
||||
source: node.name,
|
||||
attrs: node.attrs,
|
||||
// #ifndef H5 && VUE3
|
||||
errMsg: e.detail.errMsg
|
||||
// #endif
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "../styles/index.scss";
|
||||
|
||||
// 会话输出内容点击事件
|
||||
// 事件绑定配置样式
|
||||
.div-event-style {
|
||||
display: inline-block !important;
|
||||
font-size: 12px;
|
||||
margin: 0 4px;
|
||||
padding: 4px 8px;
|
||||
cursor: pointer;
|
||||
max-width: 100px;
|
||||
min-width: 18px;
|
||||
border-radius: 24px;
|
||||
color: rgba(0, 0, 0, 60%) !important;
|
||||
background-color: rgba(0, 0, 0, 5%);
|
||||
line-height: 14px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(235, 235, 235);
|
||||
}
|
||||
}
|
||||
|
||||
/* 非 H5 平台:hl-language 头部行的原生包裹层,匹配 .hl-language 的布局 */
|
||||
.hl-language-native {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 2px 10px;
|
||||
background-color: #252526;
|
||||
border-radius: 6px 6px 0 0;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* 非 H5 平台的原生可交互复制按钮 */
|
||||
.hl-copy-btn-native {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
|
||||
.hl-copy-btn-text {
|
||||
font-size: 10px;
|
||||
color: #999;
|
||||
line-height: normal;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
/* 语言名称文本 */
|
||||
.hl-language-name {
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
flex: 1;
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,174 @@
|
||||
/* HTML 基础元素样式 */
|
||||
|
||||
/* a 标签默认效果 */
|
||||
._a {
|
||||
padding: 1.5px 0 1.5px 0;
|
||||
color: rgb(59, 130, 246);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* a 标签点击态效果 */
|
||||
._hover {
|
||||
text-decoration: underline;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
/* 图片默认效果 */
|
||||
._img {
|
||||
max-width: 100%;
|
||||
-webkit-touch-callout: none;
|
||||
}
|
||||
|
||||
/* 内部样式 */
|
||||
|
||||
._block {
|
||||
display: block;
|
||||
}
|
||||
|
||||
._b,
|
||||
._strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._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: 0.83em;
|
||||
}
|
||||
|
||||
._h6 {
|
||||
font-size: 0.67em;
|
||||
}
|
||||
|
||||
._h1,
|
||||
._h2,
|
||||
._h3,
|
||||
._h4,
|
||||
._h5,
|
||||
._h6 {
|
||||
display: block;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
._image {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
._ins {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
._li {
|
||||
display: list-item;
|
||||
overflow: unset;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
._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;
|
||||
}
|
||||
|
||||
._thead,
|
||||
._tbody,
|
||||
._tfoot {
|
||||
display: table-row-group;
|
||||
}
|
||||
|
||||
._tr {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
._td,
|
||||
._th {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
._th {
|
||||
font-weight: bold;
|
||||
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;
|
||||
}
|
||||
|
||||
/* #ifdef APP-PLUS */
|
||||
._video {
|
||||
width: 300px;
|
||||
height: 225px;
|
||||
}
|
||||
/* #endif */
|
||||
@@ -0,0 +1,238 @@
|
||||
/* 代码高亮样式 - 基于 uni-ai-msg-code 深色主题 */
|
||||
/* FiraCode 字体已被移除以减小包体积 */
|
||||
/* @font-face {
|
||||
font-family: CodeFontFamily;
|
||||
src: url('@uni_modules/mp-html/static/font/FiraCode-Regular.ttf') format('truetype');
|
||||
} */
|
||||
|
||||
:deep(.hl-code) {
|
||||
color: #d4d4d4;
|
||||
background: transparent;
|
||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden; /* 防止代码区自己产生内部垂直滚动条 */
|
||||
padding: 10px 12px; /* 代码内容的内边距 */
|
||||
box-sizing: border-box;
|
||||
min-height: 100%;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
:deep(.hl-pre) {
|
||||
color: #d4d4d4;
|
||||
background: #1e1e1e;
|
||||
font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
|
||||
font-size: 14px;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
border-radius: 6px;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 0; /* Remove old padding */
|
||||
overflow: hidden; /* Stop whole wrapper from sliding */
|
||||
}
|
||||
|
||||
/* 代码头部样式 */
|
||||
:deep(.hl-language) {
|
||||
margin: 0; /* 确保没有外边距 */
|
||||
line-height: normal; /* 重置行高 */
|
||||
white-space: normal; /* 重置空白处理 */
|
||||
user-select: none;
|
||||
position: relative;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 2px 10px;
|
||||
background-color: #252526;
|
||||
border-radius: 6px 6px 0 0;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
:deep(.hl-body) {
|
||||
/* wrapper handle scrolling ONLY */
|
||||
max-height: 60vh;
|
||||
overflow-y: auto; /* vertically scroll the code and line numbers */
|
||||
overflow-x: hidden;
|
||||
width: 100%;
|
||||
position: relative;
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
:deep(.hl-container) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: stretch; /* flex cross-axis stretch without scroll boundaries */
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 代码高亮颜色 - 基于 uni-ai-msg-code 深色主题 */
|
||||
:deep(.hl-block-comment),
|
||||
:deep(.hl-cdata),
|
||||
:deep(.hl-comment),
|
||||
:deep(.hl-doctype),
|
||||
:deep(.hl-prolog) {
|
||||
color: #999; /* 注释使用灰色 */
|
||||
}
|
||||
|
||||
:deep(.hl-punctuation) {
|
||||
color: #d4d4d4; /* 标点符号使用默认文本颜色 */
|
||||
}
|
||||
|
||||
:deep(.hl-attr-name),
|
||||
:deep(.hl-deleted),
|
||||
:deep(.hl-namespace),
|
||||
:deep(.hl-tag) {
|
||||
color: #d16969; /* 元信息使用红色 */
|
||||
}
|
||||
|
||||
:deep(.hl-function-name) {
|
||||
color: #dcdcaa; /* 函数使用黄色 */
|
||||
}
|
||||
|
||||
:deep(.hl-boolean),
|
||||
:deep(.hl-function),
|
||||
:deep(.hl-number) {
|
||||
color: #b5cea8; /* 常量使用浅绿色 */
|
||||
}
|
||||
|
||||
:deep(.hl-class-name),
|
||||
:deep(.hl-constant),
|
||||
:deep(.hl-property),
|
||||
:deep(.hl-symbol) {
|
||||
color: #4ec9b0; /* 实体使用青色 */
|
||||
}
|
||||
|
||||
:deep(.hl-atrule),
|
||||
:deep(.hl-builtin),
|
||||
:deep(.hl-important),
|
||||
:deep(.hl-keyword),
|
||||
:deep(.hl-selector) {
|
||||
color: #569cd6; /* 关键字使用蓝色 */
|
||||
}
|
||||
|
||||
:deep(.hl-attr-value),
|
||||
:deep(.hl-char),
|
||||
:deep(.hl-regex),
|
||||
:deep(.hl-string),
|
||||
:deep(.hl-variable) {
|
||||
color: #ce9178; /* 字符串使用橙色 */
|
||||
}
|
||||
|
||||
:deep(.hl-entity),
|
||||
:deep(.hl-operator),
|
||||
:deep(.hl-url) {
|
||||
color: #4ec9b0; /* 支持类使用青色 */
|
||||
}
|
||||
|
||||
:deep(.hl-bold),
|
||||
:deep(.hl-important) {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
:deep(.hl-italic) {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
:deep(.hl-entity) {
|
||||
cursor: help;
|
||||
}
|
||||
|
||||
:deep(.hl-inserted) {
|
||||
color: #4ec9b0; /* 插入内容使用青色 */
|
||||
}
|
||||
|
||||
/* 行号样式 */
|
||||
:deep(.line-numbers-rows) {
|
||||
position: static;
|
||||
flex-shrink: 0;
|
||||
min-width: 3.5em;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
user-select: none;
|
||||
padding-top: 10px; /* align with code padding */
|
||||
padding-bottom: 10px;
|
||||
background-color: transparent;
|
||||
border-right: 1px solid #333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
min-height: 100%;
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
:deep(.line-numbers-rows .span) {
|
||||
display: flex;
|
||||
height: 1.5em; /* Match code line height */
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 复制按钮样式 */
|
||||
:deep(.hl-copy-btn) {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 10px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
:deep(.hl-copy-btn:hover) {
|
||||
background-color: #37373d;
|
||||
}
|
||||
|
||||
/* 滚动条样式 */
|
||||
:deep(.hl-pre::-webkit-scrollbar) {
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
:deep(.hl-pre::-webkit-scrollbar-track) {
|
||||
background: #252526;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:deep(.hl-pre::-webkit-scrollbar-thumb) {
|
||||
background: #666;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
:deep(.hl-pre::-webkit-scrollbar-thumb:hover) {
|
||||
background: #888;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/* mp-html 样式集合 - 统一导入文件 */
|
||||
|
||||
// 代码高亮样式
|
||||
@import './highlight.scss';
|
||||
|
||||
// KaTeX 字体定义
|
||||
@import './katex-fonts.scss';
|
||||
|
||||
// KaTeX 数学公式核心样式
|
||||
@import './katex-styles.scss';
|
||||
|
||||
// KaTeX 字体大小样式
|
||||
@import './katex-sizing.scss';
|
||||
|
||||
// Markdown 通用样式
|
||||
@import './markdown.scss';
|
||||
|
||||
// HTML 基础元素样式
|
||||
@import './basic-elements.scss';
|
||||
@@ -0,0 +1,110 @@
|
||||
/* KaTeX 字体定义 - 仅保留 TTF 格式以减小包体积
|
||||
* 已移除不常用的特殊字体:Caligraphic(花体)、Fraktur(哥特体)、Script(手写体)
|
||||
*/
|
||||
@font-face {
|
||||
font-family: KaTeX_AMS;
|
||||
src: url(/subpackages/static/fonts/KaTeX_AMS-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Main;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Main-Bold.ttf) format("truetype");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Main;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Main-BoldItalic.ttf) format("truetype");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Main;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Main-Italic.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Main;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Main-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Math;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Math-BoldItalic.ttf) format("truetype");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Math;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Math-Italic.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_SansSerif;
|
||||
src: url(/subpackages/static/fonts/KaTeX_SansSerif-Bold.ttf) format("truetype");
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_SansSerif;
|
||||
src: url(/subpackages/static/fonts/KaTeX_SansSerif-Italic.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_SansSerif;
|
||||
src: url(/subpackages/static/fonts/KaTeX_SansSerif-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Size1;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Size1-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Size2;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Size2-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* 以下字体已被移除以减小包体积 */
|
||||
/*
|
||||
@font-face {
|
||||
font-family: KaTeX_Size3;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Size3-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Size4;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Size4-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: KaTeX_Typewriter;
|
||||
src: url(/subpackages/static/fonts/KaTeX_Typewriter-Regular.ttf) format("truetype");
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
*/
|
||||
@@ -0,0 +1,860 @@
|
||||
/* KaTeX 字体大小样式 */
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size1),
|
||||
:deep(.katex .sizing.reset-size1.size1) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size2),
|
||||
:deep(.katex .sizing.reset-size1.size2) {
|
||||
font-size: 1.2em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size3),
|
||||
:deep(.katex .sizing.reset-size1.size3) {
|
||||
font-size: 1.4em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size4),
|
||||
:deep(.katex .sizing.reset-size1.size4) {
|
||||
font-size: 1.6em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size5),
|
||||
:deep(.katex .sizing.reset-size1.size5) {
|
||||
font-size: 1.8em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size6),
|
||||
:deep(.katex .sizing.reset-size1.size6) {
|
||||
font-size: 2em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size7),
|
||||
:deep(.katex .sizing.reset-size1.size7) {
|
||||
font-size: 2.4em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size8),
|
||||
:deep(.katex .sizing.reset-size1.size8) {
|
||||
font-size: 2.88em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size9),
|
||||
:deep(.katex .sizing.reset-size1.size9) {
|
||||
font-size: 3.456em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size10),
|
||||
:deep(.katex .sizing.reset-size1.size10) {
|
||||
font-size: 4.148em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size1.size11),
|
||||
:deep(.katex .sizing.reset-size1.size11) {
|
||||
font-size: 4.976em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size1),
|
||||
:deep(.katex .sizing.reset-size2.size1) {
|
||||
font-size: .83333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size2),
|
||||
:deep(.katex .sizing.reset-size2.size2) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size3),
|
||||
:deep(.katex .sizing.reset-size2.size3) {
|
||||
font-size: 1.16666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size4),
|
||||
:deep(.katex .sizing.reset-size2.size4) {
|
||||
font-size: 1.33333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size5),
|
||||
:deep(.katex .sizing.reset-size2.size5) {
|
||||
font-size: 1.5em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size6),
|
||||
:deep(.katex .sizing.reset-size2.size6) {
|
||||
font-size: 1.66666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size7),
|
||||
:deep(.katex .sizing.reset-size2.size7) {
|
||||
font-size: 2em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size8),
|
||||
:deep(.katex .sizing.reset-size2.size8) {
|
||||
font-size: 2.4em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size9),
|
||||
:deep(.katex .sizing.reset-size2.size9) {
|
||||
font-size: 2.88em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size10),
|
||||
:deep(.katex .sizing.reset-size2.size10) {
|
||||
font-size: 3.45666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size2.size11),
|
||||
:deep(.katex .sizing.reset-size2.size11) {
|
||||
font-size: 4.14666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size1),
|
||||
:deep(.katex .sizing.reset-size3.size1) {
|
||||
font-size: .71428571em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size2),
|
||||
:deep(.katex .sizing.reset-size3.size2) {
|
||||
font-size: .85714286em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size3),
|
||||
:deep(.katex .sizing.reset-size3.size3) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size4),
|
||||
:deep(.katex .sizing.reset-size3.size4) {
|
||||
font-size: 1.14285714em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size5),
|
||||
:deep(.katex .sizing.reset-size3.size5) {
|
||||
font-size: 1.28571429em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size6),
|
||||
:deep(.katex .sizing.reset-size3.size6) {
|
||||
font-size: 1.42857143em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size7),
|
||||
:deep(.katex .sizing.reset-size3.size7) {
|
||||
font-size: 1.71428571em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size8),
|
||||
:deep(.katex .sizing.reset-size3.size8) {
|
||||
font-size: 2.05714286em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size9),
|
||||
:deep(.katex .sizing.reset-size3.size9) {
|
||||
font-size: 2.46857143em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size10),
|
||||
:deep(.katex .sizing.reset-size3.size10) {
|
||||
font-size: 2.96285714em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size3.size11),
|
||||
:deep(.katex .sizing.reset-size3.size11) {
|
||||
font-size: 3.55428571em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size1),
|
||||
:deep(.katex .sizing.reset-size4.size1) {
|
||||
font-size: .625em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size2),
|
||||
:deep(.katex .sizing.reset-size4.size2) {
|
||||
font-size: .75em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size3),
|
||||
:deep(.katex .sizing.reset-size4.size3) {
|
||||
font-size: .875em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size4),
|
||||
:deep(.katex .sizing.reset-size4.size4) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size5),
|
||||
:deep(.katex .sizing.reset-size4.size5) {
|
||||
font-size: 1.125em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size6),
|
||||
:deep(.katex .sizing.reset-size4.size6) {
|
||||
font-size: 1.25em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size7),
|
||||
:deep(.katex .sizing.reset-size4.size7) {
|
||||
font-size: 1.5em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size8),
|
||||
:deep(.katex .sizing.reset-size4.size8) {
|
||||
font-size: 1.8em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size9),
|
||||
:deep(.katex .sizing.reset-size4.size9) {
|
||||
font-size: 2.16em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size10),
|
||||
:deep(.katex .sizing.reset-size4.size10) {
|
||||
font-size: 2.5925em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size4.size11),
|
||||
:deep(.katex .sizing.reset-size4.size11) {
|
||||
font-size: 3.11em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size1),
|
||||
:deep(.katex .sizing.reset-size5.size1) {
|
||||
font-size: .55555556em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size2),
|
||||
:deep(.katex .sizing.reset-size5.size2) {
|
||||
font-size: .66666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size3),
|
||||
:deep(.katex .sizing.reset-size5.size3) {
|
||||
font-size: .77777778em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size4),
|
||||
:deep(.katex .sizing.reset-size5.size4) {
|
||||
font-size: .88888889em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size5),
|
||||
:deep(.katex .sizing.reset-size5.size5) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size6),
|
||||
:deep(.katex .sizing.reset-size5.size6) {
|
||||
font-size: 1.11111111em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size7),
|
||||
:deep(.katex .sizing.reset-size5.size7) {
|
||||
font-size: 1.33333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size8),
|
||||
:deep(.katex .sizing.reset-size5.size8) {
|
||||
font-size: 1.6em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size9),
|
||||
:deep(.katex .sizing.reset-size5.size9) {
|
||||
font-size: 1.92em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size10),
|
||||
:deep(.katex .sizing.reset-size5.size10) {
|
||||
font-size: 2.30444444em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size5.size11),
|
||||
:deep(.katex .sizing.reset-size5.size11) {
|
||||
font-size: 2.76444444em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size1),
|
||||
:deep(.katex .sizing.reset-size6.size1) {
|
||||
font-size: .5em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size2),
|
||||
:deep(.katex .sizing.reset-size6.size2) {
|
||||
font-size: .6em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size3),
|
||||
:deep(.katex .sizing.reset-size6.size3) {
|
||||
font-size: .7em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size4),
|
||||
:deep(.katex .sizing.reset-size6.size4) {
|
||||
font-size: .8em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size5),
|
||||
:deep(.katex .sizing.reset-size6.size5) {
|
||||
font-size: .9em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size6),
|
||||
:deep(.katex .sizing.reset-size6.size6) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size7),
|
||||
:deep(.katex .sizing.reset-size6.size7) {
|
||||
font-size: 1.2em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size8),
|
||||
:deep(.katex .sizing.reset-size6.size8) {
|
||||
font-size: 1.44em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size9),
|
||||
:deep(.katex .sizing.reset-size6.size9) {
|
||||
font-size: 1.728em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size10),
|
||||
:deep(.katex .sizing.reset-size6.size10) {
|
||||
font-size: 2.074em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size6.size11),
|
||||
:deep(.katex .sizing.reset-size6.size11) {
|
||||
font-size: 2.488em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size1),
|
||||
:deep(.katex .sizing.reset-size7.size1) {
|
||||
font-size: .41666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size2),
|
||||
:deep(.katex .sizing.reset-size7.size2) {
|
||||
font-size: .5em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size3),
|
||||
:deep(.katex .sizing.reset-size7.size3) {
|
||||
font-size: .58333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size4),
|
||||
:deep(.katex .sizing.reset-size7.size4) {
|
||||
font-size: .66666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size5),
|
||||
:deep(.katex .sizing.reset-size7.size5) {
|
||||
font-size: .75em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size6),
|
||||
:deep(.katex .sizing.reset-size7.size6) {
|
||||
font-size: .83333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size7),
|
||||
:deep(.katex .sizing.reset-size7.size7) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size8),
|
||||
:deep(.katex .sizing.reset-size7.size8) {
|
||||
font-size: 1.2em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size9),
|
||||
:deep(.katex .sizing.reset-size7.size9) {
|
||||
font-size: 1.44em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size10),
|
||||
:deep(.katex .sizing.reset-size7.size10) {
|
||||
font-size: 1.72833333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size7.size11),
|
||||
:deep(.katex .sizing.reset-size7.size11) {
|
||||
font-size: 2.07333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size1),
|
||||
:deep(.katex .sizing.reset-size8.size1) {
|
||||
font-size: .34722222em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size2),
|
||||
:deep(.katex .sizing.reset-size8.size2) {
|
||||
font-size: .41666667em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size3),
|
||||
:deep(.katex .sizing.reset-size8.size3) {
|
||||
font-size: .48611111em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size4),
|
||||
:deep(.katex .sizing.reset-size8.size4) {
|
||||
font-size: .55555556em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size5),
|
||||
:deep(.katex .sizing.reset-size8.size5) {
|
||||
font-size: .625em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size6),
|
||||
:deep(.katex .sizing.reset-size8.size6) {
|
||||
font-size: .69444444em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size7),
|
||||
:deep(.katex .sizing.reset-size8.size7) {
|
||||
font-size: .83333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size8),
|
||||
:deep(.katex .sizing.reset-size8.size8) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size9),
|
||||
:deep(.katex .sizing.reset-size8.size9) {
|
||||
font-size: 1.2em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size10),
|
||||
:deep(.katex .sizing.reset-size8.size10) {
|
||||
font-size: 1.44027778em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size8.size11),
|
||||
:deep(.katex .sizing.reset-size8.size11) {
|
||||
font-size: 1.72777778em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size1),
|
||||
:deep(.katex .sizing.reset-size9.size1) {
|
||||
font-size: .28935185em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size2),
|
||||
:deep(.katex .sizing.reset-size9.size2) {
|
||||
font-size: .34722222em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size3),
|
||||
:deep(.katex .sizing.reset-size9.size3) {
|
||||
font-size: .40509259em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size4),
|
||||
:deep(.katex .sizing.reset-size9.size4) {
|
||||
font-size: .46296296em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size5),
|
||||
:deep(.katex .sizing.reset-size9.size5) {
|
||||
font-size: .52083333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size6),
|
||||
:deep(.katex .sizing.reset-size9.size6) {
|
||||
font-size: .5787037em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size7),
|
||||
:deep(.katex .sizing.reset-size9.size7) {
|
||||
font-size: .69444444em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size8),
|
||||
:deep(.katex .sizing.reset-size9.size8) {
|
||||
font-size: .83333333em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size9),
|
||||
:deep(.katex .sizing.reset-size9.size9) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size10),
|
||||
:deep(.katex .sizing.reset-size9.size10) {
|
||||
font-size: 1.20023148em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size9.size11),
|
||||
:deep(.katex .sizing.reset-size9.size11) {
|
||||
font-size: 1.43981481em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size1),
|
||||
:deep(.katex .sizing.reset-size10.size1) {
|
||||
font-size: .24108004em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size2),
|
||||
:deep(.katex .sizing.reset-size10.size2) {
|
||||
font-size: .28929605em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size3),
|
||||
:deep(.katex .sizing.reset-size10.size3) {
|
||||
font-size: .33751205em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size4),
|
||||
:deep(.katex .sizing.reset-size10.size4) {
|
||||
font-size: .38572806em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size5),
|
||||
:deep(.katex .sizing.reset-size10.size5) {
|
||||
font-size: .43394407em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size6),
|
||||
:deep(.katex .sizing.reset-size10.size6) {
|
||||
font-size: .48216008em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size7),
|
||||
:deep(.katex .sizing.reset-size10.size7) {
|
||||
font-size: .57859209em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size8),
|
||||
:deep(.katex .sizing.reset-size10.size8) {
|
||||
font-size: .69431051em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size9),
|
||||
:deep(.katex .sizing.reset-size10.size9) {
|
||||
font-size: .83317261em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size10),
|
||||
:deep(.katex .sizing.reset-size10.size10) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size10.size11),
|
||||
:deep(.katex .sizing.reset-size10.size11) {
|
||||
font-size: 1.19961427em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size1),
|
||||
:deep(.katex .sizing.reset-size11.size1) {
|
||||
font-size: .20096463em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size2),
|
||||
:deep(.katex .sizing.reset-size11.size2) {
|
||||
font-size: .24115756em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size3),
|
||||
:deep(.katex .sizing.reset-size11.size3) {
|
||||
font-size: .28135048em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size4),
|
||||
:deep(.katex .sizing.reset-size11.size4) {
|
||||
font-size: .32154341em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size5),
|
||||
:deep(.katex .sizing.reset-size11.size5) {
|
||||
font-size: .36173633em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size6),
|
||||
:deep(.katex .sizing.reset-size11.size6) {
|
||||
font-size: .40192926em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size7),
|
||||
:deep(.katex .sizing.reset-size11.size7) {
|
||||
font-size: .48231511em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size8),
|
||||
:deep(.katex .sizing.reset-size11.size8) {
|
||||
font-size: .57877814em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size9),
|
||||
:deep(.katex .sizing.reset-size11.size9) {
|
||||
font-size: .69453376em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size10),
|
||||
:deep(.katex .sizing.reset-size11.size10) {
|
||||
font-size: .83360129em
|
||||
}
|
||||
|
||||
:deep(.katex .fontsize-ensurer.reset-size11.size11),
|
||||
:deep(.katex .sizing.reset-size11.size11) {
|
||||
font-size: 1em
|
||||
}
|
||||
|
||||
:deep(.katex .delimsizing.size1) {
|
||||
font-family: KaTeX_Size1
|
||||
}
|
||||
|
||||
:deep(.katex .delimsizing.size2) {
|
||||
font-family: KaTeX_Size2
|
||||
}
|
||||
|
||||
:deep(.katex .delimsizing.size3) {
|
||||
font-family: KaTeX_Size3
|
||||
}
|
||||
|
||||
:deep(.katex .delimsizing.size4) {
|
||||
font-family: KaTeX_Size4
|
||||
}
|
||||
|
||||
:deep(.katex .delimsizing.mult .delim-size1>.katex-span) {
|
||||
font-family: KaTeX_Size1
|
||||
}
|
||||
|
||||
:deep(.katex .delimsizing.mult .delim-size4>.katex-span) {
|
||||
font-family: KaTeX_Size4
|
||||
}
|
||||
|
||||
:deep(.katex .nulldelimiter) {
|
||||
display: inline-block;
|
||||
width: .12em
|
||||
}
|
||||
|
||||
:deep(.katex .delimcenter) {
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .op-symbol) {
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .op-symbol.small-op) {
|
||||
font-family: KaTeX_Size1
|
||||
}
|
||||
|
||||
:deep(.katex .op-symbol.large-op) {
|
||||
font-family: KaTeX_Size2
|
||||
}
|
||||
|
||||
:deep(.katex .op-limits>.vlist-t) {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
:deep(.katex .accent>.vlist-t) {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
:deep(.katex .accent .accent-body) {
|
||||
position: relative
|
||||
}
|
||||
|
||||
.katex .accent .accent-body:not(.accent-full) {
|
||||
width: 0
|
||||
}
|
||||
|
||||
:deep(.katex .overlay) {
|
||||
display: block
|
||||
}
|
||||
|
||||
:deep(.katex .mtable .vertical-separator) {
|
||||
display: inline-block;
|
||||
min-width: 1px
|
||||
}
|
||||
|
||||
:deep(.katex .mtable .arraycolsep) {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
:deep(.katex .mtable .col-align-c>.vlist-t) {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
:deep(.katex .mtable .col-align-l>.vlist-t) {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
:deep(.katex .mtable .col-align-r>.vlist-t) {
|
||||
text-align: right
|
||||
}
|
||||
|
||||
:deep(.katex .svg-align) {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
:deep(.katex .katex-svg) {
|
||||
display: block;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: inherit;
|
||||
fill: currentColor;
|
||||
stroke: currentColor;
|
||||
fill-rule: nonzero;
|
||||
fill-opacity: 1;
|
||||
stroke-width: 1;
|
||||
stroke-linecap: butt;
|
||||
stroke-linejoin: miter;
|
||||
stroke-miterlimit: 4;
|
||||
stroke-dasharray: none;
|
||||
stroke-dashoffset: 0;
|
||||
stroke-opacity: 1
|
||||
}
|
||||
|
||||
:deep(.katex .katex-svg path) {
|
||||
stroke: none
|
||||
}
|
||||
|
||||
:deep(.katex img) {
|
||||
border-style: none;
|
||||
min-width: 0;
|
||||
min-height: 0;
|
||||
max-width: none;
|
||||
max-height: none
|
||||
}
|
||||
|
||||
:deep(.katex .stretchy) {
|
||||
width: 100%;
|
||||
display: block;
|
||||
position: relative;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .stretchy::after),
|
||||
:deep(.katex .stretchy::before) {
|
||||
content: ""
|
||||
}
|
||||
|
||||
:deep(.katex .hide-tail) {
|
||||
width: 100%;
|
||||
position: relative;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .halfarrow-left) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 50.2%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .halfarrow-right) {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 50.2%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .brace-left) {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
width: 25.1%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .brace-center) {
|
||||
position: absolute;
|
||||
left: 25%;
|
||||
width: 50%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .brace-right) {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
width: 25.1%;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .x-arrow-pad) {
|
||||
padding: 0 .5em
|
||||
}
|
||||
|
||||
:deep(.katex .cd-arrow-pad) {
|
||||
padding: 0 .55556em 0 .27778em
|
||||
}
|
||||
|
||||
:deep(.katex .mover),
|
||||
:deep(.katex .munder),
|
||||
:deep(.katex .x-arrow) {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
:deep(.katex .boxpad) {
|
||||
padding: 0 .3em
|
||||
}
|
||||
|
||||
:deep(.katex .fbox),
|
||||
:deep(.katex .fcolorbox) {
|
||||
box-sizing: border-box;
|
||||
border: .04em solid
|
||||
}
|
||||
|
||||
:deep(.katex .cancel-pad) {
|
||||
padding: 0 .2em
|
||||
}
|
||||
|
||||
:deep(.katex .cancel-lap) {
|
||||
margin-left: -.2em;
|
||||
margin-right: -.2em
|
||||
}
|
||||
|
||||
:deep(.katex .sout) {
|
||||
border-bottom-style: solid;
|
||||
border-bottom-width: .08em
|
||||
}
|
||||
|
||||
:deep(.katex .angl) {
|
||||
box-sizing: border-box;
|
||||
border-top: .049em solid;
|
||||
border-right: .049em solid;
|
||||
margin-right: .03889em
|
||||
}
|
||||
|
||||
:deep(.katex .anglpad) {
|
||||
padding: 0 .03889em
|
||||
}
|
||||
|
||||
:deep(.katex .eqn-num::before) {
|
||||
counter-increment: katexEqnNo;
|
||||
content: "(" counter(katexEqnNo) ")"
|
||||
}
|
||||
|
||||
:deep(.katex .mml-eqn-num::before) {
|
||||
counter-increment: mmlEqnNo;
|
||||
content: "(" counter(mmlEqnNo) ")"
|
||||
}
|
||||
|
||||
:deep(.katex .mtr-glue) {
|
||||
width: 50%
|
||||
}
|
||||
|
||||
:deep(.katex .cd-vert-arrow) {
|
||||
display: inline-block;
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .cd-label-left) {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: calc(50% + .3em);
|
||||
text-align: left
|
||||
}
|
||||
|
||||
:deep(.katex .cd-label-right) {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
left: calc(50% + .3em);
|
||||
text-align: right
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
/* KaTeX 数学公式样式 */
|
||||
:deep(.katex) {
|
||||
counter-reset: katexEqnNo mmlEqnNo;
|
||||
font: normal 1.21em KaTeX_Main, Times New Roman, serif;
|
||||
line-height: 1.2;
|
||||
text-indent: 0;
|
||||
text-rendering: auto
|
||||
}
|
||||
|
||||
:deep(.katex text),
|
||||
:deep(.katex view) {
|
||||
-ms-high-contrast-adjust: none !important;
|
||||
border-color: currentColor
|
||||
}
|
||||
|
||||
:deep(.katex .katex-mathml) {
|
||||
position: absolute;
|
||||
clip: rect(1px, 1px, 1px, 1px);
|
||||
padding: 0;
|
||||
border: 0;
|
||||
height: 1px;
|
||||
width: 1px;
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
:deep(.katex .katex-html>.newline) {
|
||||
display: block
|
||||
}
|
||||
|
||||
:deep(.katex .base) {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
white-space: nowrap;
|
||||
width: min-content
|
||||
}
|
||||
|
||||
:deep(.katex .strut) {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
:deep(.katex .textbf) {
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
:deep(.katex .textit) {
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
:deep(.katex .textrm) {
|
||||
font-family: KaTeX_Main
|
||||
}
|
||||
|
||||
:deep(.katex .textsf) {
|
||||
font-family: KaTeX_SansSerif
|
||||
}
|
||||
|
||||
:deep(.katex .texttt) {
|
||||
font-family: KaTeX_Typewriter
|
||||
}
|
||||
|
||||
:deep(.katex .mathnormal) {
|
||||
font-family: KaTeX_Math;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
:deep(.katex .mathit) {
|
||||
font-family: KaTeX_Main;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
:deep(.katex .mathrm) {
|
||||
font-style: normal
|
||||
}
|
||||
|
||||
:deep(.katex .mathbf) {
|
||||
font-family: KaTeX_Main;
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
:deep(.katex .boldsymbol) {
|
||||
font-family: KaTeX_Math;
|
||||
font-weight: 700;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
:deep(.katex .amsrm) {
|
||||
font-family: KaTeX_AMS
|
||||
}
|
||||
|
||||
:deep(.katex .mathbb),
|
||||
:deep(.katex .textbb) {
|
||||
font-family: KaTeX_AMS
|
||||
}
|
||||
|
||||
:deep(.katex .mathcal) {
|
||||
font-family: KaTeX_Caligraphic
|
||||
}
|
||||
|
||||
:deep(.katex .mathfrak),
|
||||
:deep(.katex .textfrak) {
|
||||
font-family: KaTeX_Fraktur
|
||||
}
|
||||
|
||||
:deep(.katex .mathtt) {
|
||||
font-family: KaTeX_Typewriter
|
||||
}
|
||||
|
||||
:deep(.katex .mathscr),
|
||||
:deep(.katex .textscr) {
|
||||
font-family: KaTeX_Script
|
||||
}
|
||||
|
||||
:deep(.katex .mathsf),
|
||||
:deep(.katex .textsf) {
|
||||
font-family: KaTeX_SansSerif
|
||||
}
|
||||
|
||||
:deep(.katex .mathboldsf),
|
||||
:deep(.katex .textboldsf) {
|
||||
font-family: KaTeX_SansSerif;
|
||||
font-weight: 700
|
||||
}
|
||||
|
||||
:deep(.katex .mathitsf),
|
||||
:deep(.katex .textitsf) {
|
||||
font-family: KaTeX_SansSerif;
|
||||
font-style: italic
|
||||
}
|
||||
|
||||
:deep(.katex .mainrm) {
|
||||
font-family: KaTeX_Main;
|
||||
font-style: normal
|
||||
}
|
||||
|
||||
:deep(.katex .vlist-t) {
|
||||
display: inline-table;
|
||||
table-layout: fixed;
|
||||
border-collapse: collapse
|
||||
}
|
||||
|
||||
:deep(.katex .vlist-r) {
|
||||
display: table-row
|
||||
}
|
||||
|
||||
:deep(.katex .vlist) {
|
||||
display: table-cell;
|
||||
vertical-align: bottom;
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .vlist>.katex-span) {
|
||||
display: block;
|
||||
height: 0;
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .vlist>.katex-span>.katex-span) {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
:deep(.katex .vlist>.katex-span>.pstrut) {
|
||||
overflow: hidden;
|
||||
width: 0
|
||||
}
|
||||
|
||||
:deep(.katex .vlist-t2) {
|
||||
margin-right: -2px
|
||||
}
|
||||
|
||||
:deep(.katex .vlist-s) {
|
||||
display: table-cell;
|
||||
vertical-align: bottom;
|
||||
font-size: 1px;
|
||||
width: 2px;
|
||||
min-width: 2px
|
||||
}
|
||||
|
||||
:deep(.katex .vbox) {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
align-items: baseline
|
||||
}
|
||||
|
||||
:deep(.katex .hbox) {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
width: 100%
|
||||
}
|
||||
|
||||
:deep(.katex .thinbox) {
|
||||
display: inline-flex;
|
||||
flex-direction: row;
|
||||
width: 0;
|
||||
max-width: 0
|
||||
}
|
||||
|
||||
:deep(.katex .msupsub) {
|
||||
text-align: left
|
||||
}
|
||||
|
||||
:deep(.katex .mfrac>.katex-span>.katex-span) {
|
||||
text-align: center
|
||||
}
|
||||
|
||||
:deep(.katex .mfrac .frac-line) {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
border-bottom-style: solid
|
||||
}
|
||||
|
||||
:deep(.katex .hdashline),
|
||||
:deep(.katex .hline),
|
||||
:deep(.katex .mfrac .frac-line),
|
||||
:deep(.katex .overline .overline-line),
|
||||
:deep(.katex .rule),
|
||||
:deep(.katex .underline .underline-line) {
|
||||
min-height: 1px
|
||||
}
|
||||
|
||||
:deep(.katex .mspace) {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
:deep(.katex .clap),
|
||||
:deep(.katex .llap),
|
||||
:deep(.katex .rlap) {
|
||||
width: 0;
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .clap>.inner),
|
||||
:deep(.katex .llap>.inner),
|
||||
:deep(.katex .rlap>.inner) {
|
||||
position: absolute
|
||||
}
|
||||
|
||||
:deep(.katex .clap>.fix),
|
||||
:deep(.katex .llap>.fix),
|
||||
:deep(.katex .rlap>.fix) {
|
||||
display: inline-block
|
||||
}
|
||||
|
||||
:deep(.katex .llap>.inner) {
|
||||
right: 0
|
||||
}
|
||||
|
||||
:deep(.katex .clap>.inner),
|
||||
:deep(.katex .rlap>.inner) {
|
||||
left: 0
|
||||
}
|
||||
|
||||
:deep(.katex .clap>.inner>.katex-span) {
|
||||
margin-left: -50%;
|
||||
margin-right: 50%
|
||||
}
|
||||
|
||||
:deep(.katex .rule) {
|
||||
display: inline-block;
|
||||
border: solid 0;
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex .hline),
|
||||
:deep(.katex .overline .overline-line),
|
||||
:deep(.katex .underline .underline-line) {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
border-bottom-style: solid
|
||||
}
|
||||
|
||||
:deep(.katex .hdashline) {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
border-bottom-style: dashed
|
||||
}
|
||||
|
||||
:deep(.katex .sqrt>.root) {
|
||||
margin-left: .27777778em;
|
||||
margin-right: -.55555556em
|
||||
}
|
||||
|
||||
:deep(.katex-display) {
|
||||
display: block;
|
||||
margin: 1em 0;
|
||||
text-align: center;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
:deep(.katex-display>.katex) {
|
||||
display: block;
|
||||
text-align: center;
|
||||
white-space: nowrap
|
||||
}
|
||||
|
||||
:deep(.katex-display>.katex>.katex-html) {
|
||||
display: block;
|
||||
position: relative
|
||||
}
|
||||
|
||||
:deep(.katex-display>.katex>.katex-html>.tag) {
|
||||
position: absolute;
|
||||
right: 0
|
||||
}
|
||||
|
||||
:deep(.katex-display.leqno>.katex>.katex-html>.tag) {
|
||||
left: 0;
|
||||
right: auto
|
||||
}
|
||||
|
||||
:deep(.katex-display.fleqn>.katex) {
|
||||
text-align: left;
|
||||
padding-left: 2em
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
$mdZoom: 1.143;
|
||||
$lineHeight: calc($mdZoom * 25px);
|
||||
$fontWeightStrong: 600;
|
||||
/* Markdown 通用样式 */
|
||||
:deep(.md-p) {
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
line-height: 1.5;
|
||||
strong {
|
||||
font-weight: $fontWeightStrong;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.md-table),
|
||||
:deep(.md-blockquote) {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
:deep(.md-table) {
|
||||
box-sizing: border-box;
|
||||
display: table;
|
||||
width: max-content;
|
||||
min-width: 100%;
|
||||
overflow: auto;
|
||||
border-spacing: 0;
|
||||
border-collapse: collapse;
|
||||
|
||||
}
|
||||
|
||||
:deep(.md-tr) {
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #c6cbd1;
|
||||
}
|
||||
|
||||
.md-table .md-tr:nth-child(2n) {
|
||||
background-color: #f6f8fa;
|
||||
}
|
||||
|
||||
:deep(.md-th),
|
||||
:deep(.md-td) {
|
||||
padding: 6px 13px !important;
|
||||
border: 1px solid #dfe2e5;
|
||||
}
|
||||
|
||||
:deep(.md-th) {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.md-blockquote) {
|
||||
padding: 0 1em;
|
||||
color: #6a737d;
|
||||
border-left: 0.25em solid #dfe2e5;
|
||||
}
|
||||
|
||||
:deep(.md-code),
|
||||
:deep(.md-code code) {
|
||||
display: inline-block !important;
|
||||
padding: 0.2em 0.4em;
|
||||
font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;
|
||||
font-size: 85%;
|
||||
background-color: rgba(27, 31, 35, 0.05);
|
||||
border-radius: 3px;
|
||||
word-break: break-all;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
:deep(.md-pre .md-code) {
|
||||
padding: 0;
|
||||
font-size: 100%;
|
||||
background: transparent;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
:deep(.md-hr) {
|
||||
height: 0.5px;
|
||||
border: none;
|
||||
margin: 30rpx 0;
|
||||
background-color: #d9d9d9;
|
||||
}
|
||||
/**
|
||||
H1 20px H2 18px H3 16px H4 16px H5 16px
|
||||
**/
|
||||
|
||||
:deep(.md-h1) {
|
||||
font-size: 20px;
|
||||
border-bottom: 2rpx solid #d9d9d9;
|
||||
padding-bottom: .3em;
|
||||
line-height: 1.5;
|
||||
font-weight: $fontWeightStrong;
|
||||
margin: calc($mdZoom * 16px) 0 calc($mdZoom * 12px) 0;
|
||||
}
|
||||
|
||||
:deep(.md-h2) {
|
||||
font-size: 18px;
|
||||
font-weight: $fontWeightStrong;
|
||||
line-height: 1.5;
|
||||
margin: calc($mdZoom * 16px) 0 calc($mdZoom * 12px) 0;
|
||||
}
|
||||
|
||||
:deep(.md-h3),
|
||||
:deep(.md-h4),
|
||||
:deep(.md-h5) {
|
||||
font-size: 16px;
|
||||
font-weight: $fontWeightStrong;
|
||||
line-height: $lineHeight;
|
||||
margin: calc($mdZoom * 16px) 0 calc($mdZoom * 12px) 0;
|
||||
}
|
||||
|
||||
:deep(.md-h6) {
|
||||
font-size: 14px;
|
||||
font-weight: $fontWeightStrong;
|
||||
line-height: $lineHeight;
|
||||
margin: calc($mdZoom * 16px) 0 calc($mdZoom * 12px) 0;
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<view class="task-result" @tap="handleClick">
|
||||
<!-- 左侧图标 -->
|
||||
<view class="task-result-icon">
|
||||
<text class="iconfont"></text>
|
||||
</view>
|
||||
|
||||
<!-- 文件描述/名称 -->
|
||||
<view class="task-result-action">
|
||||
<text class="action-text">{{ displayText }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 右侧图标 -->
|
||||
<view class="task-result-arrow">
|
||||
<text class="iconfont"></text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
getFileProxyUrlByConversationIdAndFilePath,
|
||||
jumpToFilePreviewPage,
|
||||
} from "@/utils/system.uts";
|
||||
|
||||
export default {
|
||||
name: "TaskResult",
|
||||
props: {
|
||||
// task-result 节点数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
// 会话ID
|
||||
conversationId: {
|
||||
type: [String, Number],
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
// 提取描述文本
|
||||
description() {
|
||||
return this.extractChildText("description");
|
||||
},
|
||||
// 提取文件名
|
||||
fileName() {
|
||||
return this.extractChildText("file");
|
||||
},
|
||||
// 显示文本:优先显示描述,其次显示文件名
|
||||
displayText() {
|
||||
return this.description || this.fileName || "查看结果";
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
/**
|
||||
* 从子节点中提取指定类型的文本内容
|
||||
* @param tagName 标签名
|
||||
* @returns 文本内容
|
||||
*/
|
||||
extractChildText(tagName) {
|
||||
const children = this.data?.children || [];
|
||||
|
||||
for (const child of children) {
|
||||
if (child.name === tagName) {
|
||||
// 递归提取文本
|
||||
return this.getTextContent(child);
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
|
||||
/**
|
||||
* 递归获取节点的文本内容
|
||||
* @param node 节点
|
||||
* @returns 文本内容
|
||||
*/
|
||||
getTextContent(node) {
|
||||
if (!node) return "";
|
||||
|
||||
// 如果是文本节点
|
||||
if (node.type === "text") {
|
||||
return node.text || "";
|
||||
}
|
||||
|
||||
// 如果有子节点,递归处理
|
||||
if (node.children && Array.isArray(node.children)) {
|
||||
return node.children
|
||||
.map((child) => this.getTextContent(child))
|
||||
.join("");
|
||||
}
|
||||
|
||||
return "";
|
||||
},
|
||||
|
||||
/**
|
||||
* 点击处理:打开预览视图
|
||||
*/
|
||||
async handleClick() {
|
||||
let conversationId = String(this.conversationId);
|
||||
// 移除 chat- 前缀,因为页面参数使用的是纯数字ID
|
||||
if (conversationId && conversationId.startsWith("chat-")) {
|
||||
conversationId = conversationId.replace("chat-", "");
|
||||
}
|
||||
|
||||
if (conversationId) {
|
||||
try {
|
||||
const fileId = this.fileName.split(`${conversationId}/`).pop();
|
||||
const fileProxyUrl =
|
||||
await getFileProxyUrlByConversationIdAndFilePath(
|
||||
conversationId,
|
||||
fileId,
|
||||
);
|
||||
jumpToFilePreviewPage(conversationId, fileProxyUrl);
|
||||
} catch (error) {
|
||||
console.error("[TaskResult] 获取文件列表失败:", error);
|
||||
}
|
||||
} else {
|
||||
// 如果没有会话ID,发送事件让父组件处理
|
||||
uni.$emit("task_result_click", {
|
||||
data: this.data,
|
||||
fileName: this.fileName,
|
||||
description: this.description,
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.task-result {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 20rpx 20rpx;
|
||||
margin: 16rpx 0;
|
||||
border-radius: 16rpx;
|
||||
background-color: rgba(12, 20, 102, 0.04);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
&:active {
|
||||
background-color: rgba(12, 20, 102, 0.08);
|
||||
}
|
||||
|
||||
.task-result-icon {
|
||||
flex-shrink: 0;
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.iconfont {
|
||||
font-size: 32rpx;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
}
|
||||
|
||||
.task-result-action {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
overflow: hidden;
|
||||
|
||||
.action-text {
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
line-height: 40rpx;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.task-result-arrow {
|
||||
flex-shrink: 0;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.iconfont {
|
||||
font-size: 24rpx;
|
||||
color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
}
|
||||
|
||||
// 响应式设计
|
||||
@media (max-width: 750rpx) {
|
||||
.task-result-action {
|
||||
.action-text {
|
||||
font-size: 26rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
82
qiming-mobile/subpackages/uni_modules/mp-html/package.json
Normal file
82
qiming-mobile/subpackages/uni_modules/mp-html/package.json
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
"id": "mp-html",
|
||||
"displayName": "mp-html 富文本组件【全端支持,支持编辑、latex等扩展】",
|
||||
"version": "v2.5.1",
|
||||
"description": "一个强大的富文本组件,高效轻量,功能丰富",
|
||||
"keywords": [
|
||||
"富文本",
|
||||
"编辑器",
|
||||
"html",
|
||||
"rich-text",
|
||||
"editor"
|
||||
],
|
||||
"repository": "https://github.com/jin-yufeng/mp-html",
|
||||
"dcloudext": {
|
||||
"sale": {
|
||||
"regular": {
|
||||
"price": "0.00"
|
||||
},
|
||||
"sourcecode": {
|
||||
"price": "0.00"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"qq": ""
|
||||
},
|
||||
"declaration": {
|
||||
"ads": "无",
|
||||
"data": "无",
|
||||
"permissions": "无"
|
||||
},
|
||||
"npmurl": "https://www.npmjs.com/package/mp-html",
|
||||
"type": "component-vue"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"katex": "^0.16.0"
|
||||
},
|
||||
"uni_modules": {
|
||||
"platforms": {
|
||||
"cloud": {
|
||||
"tcb": "y",
|
||||
"aliyun": "y",
|
||||
"alipay": "n"
|
||||
},
|
||||
"client": {
|
||||
"App": {
|
||||
"app-vue": "y",
|
||||
"app-nvue": "y",
|
||||
"app-harmony": "u",
|
||||
"app-uvue": "u"
|
||||
},
|
||||
"H5-mobile": {
|
||||
"Safari": "y",
|
||||
"Android Browser": "y",
|
||||
"微信浏览器(Android)": "y",
|
||||
"QQ浏览器(Android)": "y"
|
||||
},
|
||||
"H5-pc": {
|
||||
"Chrome": "y",
|
||||
"IE": "u",
|
||||
"Edge": "y",
|
||||
"Firefox": "y",
|
||||
"Safari": "y"
|
||||
},
|
||||
"小程序": {
|
||||
"微信": "y",
|
||||
"阿里": "y",
|
||||
"百度": "y",
|
||||
"字节跳动": "y",
|
||||
"QQ": "y"
|
||||
},
|
||||
"快应用": {
|
||||
"华为": "y",
|
||||
"联盟": "y"
|
||||
},
|
||||
"Vue": {
|
||||
"vue2": "y",
|
||||
"vue3": "y"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
"use strict";function t(t){for(var e=Object.create(null),n=t.attributes.length;n--;)e[t.attributes[n].name]=t.attributes[n].value;return e}function e(){a[1]&&(this.src=a[1],this.onerror=null),this.onclick=null,this.ontouchstart=null,uni.postMessage({data:{action:"onError",source:"img",attrs:t(this)}})}function n(){window.unloadimgs-=1,0===window.unloadimgs&&uni.postMessage({data:{action:"onReady"}})}function o(r,s,c){for(var d=0;d<r.length;d++)!function(d){var u=r[d],l=void 0;if(u.type&&"node"!==u.type)l=document.createTextNode(u.text.replace(/&/g,"&"));else{var g=u.name;"svg"===g&&(c="http://www.w3.org/2000/svg"),"html"!==g&&"body"!==g||(g="div"),l=c?document.createElementNS(c,g):document.createElement(g);for(var p in u.attrs)l.setAttribute(p,u.attrs[p]);if(u.children&&o(u.children,l,c),"img"===g){if(window.unloadimgs+=1,l.onload=n,l.onerror=n,!l.src&&l.getAttribute("data-src")&&(l.src=l.getAttribute("data-src")),u.attrs.ignore||(l.onclick=function(e){e.stopPropagation(),uni.postMessage({data:{action:"onImgTap",attrs:t(this)}})}),a[2]){var h=new Image;h.src=l.src,l.src=a[2],h.onload=function(){l.src=this.src},h.onerror=function(){l.onerror()}}l.onerror=e}else if("a"===g)l.addEventListener("click",function(e){e.stopPropagation(),e.preventDefault();var n,o=this.getAttribute("href");o&&"#"===o[0]&&(n=(document.getElementById(o.substr(1))||{}).offsetTop),uni.postMessage({data:{action:"onLinkTap",attrs:t(this),offset:n}})},!0);else if("video"===g||"audio"===g)i.push(l),u.attrs.autoplay||u.attrs.controls||l.setAttribute("controls","true"),l.onplay=function(){if(uni.postMessage({data:{action:"onPlay"}}),a[3])for(var t=0;t<i.length;t++)i[t]!==this&&i[t].pause()},l.onerror=function(){uni.postMessage({data:{action:"onError",source:g,attrs:t(this)}})};else if("table"===g&&a[4]&&!l.style.cssText.includes("inline")){var f=document.createElement("div");f.style.overflow="auto",f.appendChild(l),l=f}else"svg"===g&&(c=void 0)}s.appendChild(l)}(d)}document.addEventListener("UniAppJSBridgeReady",function(){document.body.onclick=function(){return uni.postMessage({data:{action:"onClick"}})},uni.postMessage({data:{action:"onJSBridgeReady"}})});var a,i=[];window.setContent=function(t,e,n){var r=document.getElementById("content");e[0]&&(document.body.style.cssText=e[0]),e[5]||(r.style.userSelect="none"),n||(r.innerHTML="",i=[]),a=e,window.unloadimgs=0;var s=document.createDocumentFragment();o(t,s),r.appendChild(s);var c=r.scrollHeight;uni.postMessage({data:{action:"onLoad",height:c}}),window.unloadimgs||uni.postMessage({data:{action:"onReady",height:c}}),clearInterval(window.timer),window.timer=setInterval(function(){r.scrollHeight!==c&&(c=r.scrollHeight,uni.postMessage({data:{action:"onHeightChange",height:c}}))},350)},window.onunload=function(){clearInterval(window.timer)};
|
||||
1
qiming-mobile/subpackages/uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
vendored
Normal file
1
qiming-mobile/subpackages/uni_modules/mp-html/static/app-plus/mp-html/js/uni.webview.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
!function(e,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(e=e||self).uni=n()}(this,(function(){"use strict";try{var e={};Object.defineProperty(e,"passive",{get:function(){!0}}),window.addEventListener("test-passive",null,e)}catch(e){}var n=Object.prototype.hasOwnProperty;function t(e,t){return n.call(e,t)}var i=[],a=function(e,n){var t={options:{timestamp:+new Date},name:e,arg:n};if(window.__dcloud_weex_postMessage||window.__dcloud_weex_){if("postMessage"===e){var a={data:[n]};return window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessage(a):window.__dcloud_weex_.postMessage(JSON.stringify(a))}var o={type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}};window.__dcloud_weex_postMessage?window.__dcloud_weex_postMessageToService(o):window.__dcloud_weex_.postMessageToService(JSON.stringify(o))}if(!window.plus)return window.parent.postMessage({type:"WEB_INVOKE_APPSERVICE",data:t,pageId:""},"*");if(0===i.length){var r=plus.webview.currentWebview();if(!r)throw new Error("plus.webview.currentWebview() is undefined");var d=r.parent(),s="";s=d?d.id:r.id,i.push(s)}if(plus.webview.getWebviewById("__uniapp__service"))plus.webview.postMessageToUniNView({type:"WEB_INVOKE_APPSERVICE",args:{data:t,webviewIds:i}},"__uniapp__service");else{var w=JSON.stringify(t);plus.webview.getLaunchWebview().evalJS('UniPlusBridge.subscribeHandler("'.concat("WEB_INVOKE_APPSERVICE",'",').concat(w,",").concat(JSON.stringify(i),");"))}},o={navigateTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("navigateTo",{url:encodeURI(n)})},navigateBack:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.delta;a("navigateBack",{delta:parseInt(n)||1})},switchTab:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("switchTab",{url:encodeURI(n)})},reLaunch:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("reLaunch",{url:encodeURI(n)})},redirectTo:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=e.url;a("redirectTo",{url:encodeURI(n)})},getEnv:function(e){window.plus?e({plus:!0}):e({h5:!0})},postMessage:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};a("postMessage",e.data||{})}},r=/uni-app/i.test(navigator.userAgent),d=/Html5Plus/i.test(navigator.userAgent),s=/complete|loaded|interactive/;var w=window.my&&navigator.userAgent.indexOf("AlipayClient")>-1;var u=window.swan&&window.swan.webView&&/swan/i.test(navigator.userAgent);var c=window.qq&&window.qq.miniProgram&&/QQ/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var g=window.tt&&window.tt.miniProgram&&/toutiaomicroapp/i.test(navigator.userAgent);var v=window.wx&&window.wx.miniProgram&&/micromessenger/i.test(navigator.userAgent)&&/miniProgram/i.test(navigator.userAgent);var p=window.qa&&/quickapp/i.test(navigator.userAgent);for(var l,_=function(){window.UniAppJSBridge=!0,document.dispatchEvent(new CustomEvent("UniAppJSBridgeReady",{bubbles:!0,cancelable:!0}))},f=[function(e){if(r||d)return window.__dcloud_weex_postMessage||window.__dcloud_weex_?document.addEventListener("DOMContentLoaded",e):window.plus&&s.test(document.readyState)?setTimeout(e,0):document.addEventListener("plusready",e),o},function(e){if(v)return window.WeixinJSBridge&&window.WeixinJSBridge.invoke?setTimeout(e,0):document.addEventListener("WeixinJSBridgeReady",e),window.wx.miniProgram},function(e){if(c)return window.QQJSBridge&&window.QQJSBridge.invoke?setTimeout(e,0):document.addEventListener("QQJSBridgeReady",e),window.qq.miniProgram},function(e){if(w){document.addEventListener("DOMContentLoaded",e);var n=window.my;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){if(u)return document.addEventListener("DOMContentLoaded",e),window.swan.webView},function(e){if(g)return document.addEventListener("DOMContentLoaded",e),window.tt.miniProgram},function(e){if(p){window.QaJSBridge&&window.QaJSBridge.invoke?setTimeout(e,0):document.addEventListener("QaJSBridgeReady",e);var n=window.qa;return{navigateTo:n.navigateTo,navigateBack:n.navigateBack,switchTab:n.switchTab,reLaunch:n.reLaunch,redirectTo:n.redirectTo,postMessage:n.postMessage,getEnv:n.getEnv}}},function(e){return document.addEventListener("DOMContentLoaded",e),o}],m=0;m<f.length&&!(l=f[m](_));m++);l||(l={});var E="undefined"!=typeof uni?uni:{};if(!E.navigateTo)for(var b in l)t(l,b)&&(E[b]=l[b]);return E.webView=l,E}));
|
||||
@@ -0,0 +1 @@
|
||||
<head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"><style>body,html{width:100%;height:100%;overflow-x:scroll;overflow-y:hidden}body{margin:0}video{width:300px;height:225px}img{max-width:100%;-webkit-touch-callout:none}</style></head><body><div id="content" style="overflow:hidden"></div><script type="text/javascript" src="./js/uni.webview.min.js"></script><script type="text/javascript" src="./js/handler.js"></script></body>
|
||||
Reference in New Issue
Block a user