chore: initialize qiming workspace repository
This commit is contained in:
@@ -0,0 +1,355 @@
|
||||
<template>
|
||||
<view class="manual-wrapper">
|
||||
<scroll-view
|
||||
class="manual-container"
|
||||
direction="horizontal"
|
||||
:scroll-with-animation="true"
|
||||
:show-scrollbar="false"
|
||||
>
|
||||
<!-- 页面首页 -->
|
||||
<view
|
||||
v-if="pageHomeIndex && expandPageArea === ExpandPageAreaEnum.Yes"
|
||||
class="manual-box"
|
||||
@click="handleOpenPagePreview"
|
||||
>
|
||||
<text class="icon iconfont"></text>
|
||||
<text class="text">{{ t("Mobile.Common.pageHome") }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 工作台 -->
|
||||
<view v-if="isTaskAgent" class="manual-box" @click="handleOpenFileTree">
|
||||
<text class="icon iconfont"></text>
|
||||
<text class="text">{{ t("Mobile.Common.workspace") }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 沙盒选择 -->
|
||||
<view v-if="isTaskAgent && !readonly" class="manual-group">
|
||||
<!-- 自定义 Select 触发区 -->
|
||||
<view
|
||||
v-if="!isSandboxUnavailable && currentSandboxName"
|
||||
class="manual-box manual-select"
|
||||
@click="openSandboxDrawer"
|
||||
>
|
||||
<text class="text">{{ currentSandboxName }}</text>
|
||||
<text class="icon iconfont icon-arrow-down"></text>
|
||||
</view>
|
||||
|
||||
<!-- 不可用状态 -->
|
||||
<view v-else class="manual-box manual-select disabled">
|
||||
<text class="text">{{ sandboxDisabledText }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 模型选择 -->
|
||||
<view
|
||||
v-if="allowOtherModel && currentModelName"
|
||||
class="manual-box manual-select"
|
||||
@click="modelSelectVisible = true"
|
||||
>
|
||||
<text class="text">{{ currentModelName }}</text>
|
||||
<text class="icon iconfont icon-arrow-down"></text>
|
||||
</view>
|
||||
|
||||
<template v-for="item in manualComponents" :key="item.id">
|
||||
<view
|
||||
class="manual-box"
|
||||
:class="{ active: isSelected(item) }"
|
||||
@click="handleSelectComponent(item)"
|
||||
>
|
||||
<text
|
||||
class="icon iconfont"
|
||||
:class="getIconClass(item.name)"
|
||||
v-if="getIconClass(item.name)"
|
||||
></text>
|
||||
<text class="text">{{ item.name }}</text>
|
||||
</view>
|
||||
</template>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<page-preview-iframe ref="pagePreviewIframeRef" />
|
||||
|
||||
<!-- 沙盒切换弹窗 -->
|
||||
<sandbox-select-modal
|
||||
:visible="sandboxVisible"
|
||||
:sandbox-list="sandboxList"
|
||||
:current-sandbox-id="currentSandboxId"
|
||||
:is-sandbox-switch-disabled="isSandboxSwitchDisabled"
|
||||
:readonly="readonly"
|
||||
@on-close="handleSandboxClose"
|
||||
@on-sandbox-change="handleSandboxChangeInside"
|
||||
/>
|
||||
|
||||
<!-- 模型选择弹窗 -->
|
||||
<model-select-modal
|
||||
v-if="allowOtherModel"
|
||||
:visible="modelSelectVisible"
|
||||
:agent-id="agentId"
|
||||
:agent-type="agentType"
|
||||
:current-model-id="currentModelId"
|
||||
:is-temp-chat="isTempChat"
|
||||
@on-close="modelSelectVisible = false"
|
||||
@on-model-change="handleModelChangeInside"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="uts" setup>
|
||||
import { ExpandPageAreaEnum } from "@/types/enums/agent.uts";
|
||||
import { AgentManualComponentInfo } from "@/types/interfaces/agent.uts";
|
||||
import { SandboxInfo } from "@/types/interfaces/sandbox";
|
||||
import SandboxSelectModal from "../sandbox-select-modal/sandbox-select-modal.uvue";
|
||||
import { useI18n } from "@/utils/i18n";
|
||||
import ModelSelectModal from "../model-select-modal/model-select-modal.uvue";
|
||||
import { AgentTypeEnum } from "@/types/enums/agent.uts";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
manualComponents: AgentManualComponentInfo[];
|
||||
selectedComponents: AgentSelectedComponentInfo[];
|
||||
isTaskAgent?: boolean;
|
||||
pageHomeIndex?: string;
|
||||
expandPageArea?: number;
|
||||
sandboxList?: SandboxInfo[];
|
||||
currentSandboxId?: string;
|
||||
isSandboxSwitchDisabled?: boolean;
|
||||
isSandboxUnavailable?: boolean;
|
||||
sandboxDisabledText?: string;
|
||||
readonly?: boolean;
|
||||
// 模型选择相关
|
||||
allowOtherModel?: boolean;
|
||||
currentModelId?: number;
|
||||
currentModelName?: string;
|
||||
agentId?: number;
|
||||
agentType?: AgentTypeEnum;
|
||||
isTempChat?: boolean;
|
||||
}>(),
|
||||
{
|
||||
manualComponents: () => [],
|
||||
selectedComponents: () => [],
|
||||
isTaskAgent: false,
|
||||
pageHomeIndex: "",
|
||||
expandPageArea: 0,
|
||||
sandboxList: () => [],
|
||||
currentSandboxId: "",
|
||||
isSandboxSwitchDisabled: false,
|
||||
isSandboxUnavailable: false,
|
||||
sandboxDisabledText: "",
|
||||
readonly: false,
|
||||
allowOtherModel: false,
|
||||
currentModelId: 0,
|
||||
currentModelName: "",
|
||||
agentId: 0,
|
||||
agentType: AgentTypeEnum.ChatBot,
|
||||
isTempChat: false,
|
||||
},
|
||||
);
|
||||
|
||||
const emit = defineEmits<{
|
||||
onSandboxChange: (sandboxId: string) => void;
|
||||
onModelChange: (modelId: number, name: string) => void;
|
||||
onSelectComponent: (item: AgentSelectedComponentInfo) => void;
|
||||
onOpenPagePreview: (uri: string) => void;
|
||||
onOpenFileTree: () => void;
|
||||
}>();
|
||||
|
||||
// 当前显示的沙盒名称
|
||||
const currentSandboxName = computed(() => {
|
||||
const item = props.sandboxList.find(
|
||||
(item) => item.sandboxId === props.currentSandboxId,
|
||||
);
|
||||
return item ? item.name : props.sandboxList[0]?.name || "";
|
||||
});
|
||||
|
||||
// 当前显示的模型名称使用 props 传入的值
|
||||
const modelSelectVisible = ref(false);
|
||||
|
||||
const handleModelChangeInside = (id: number, name: string) => {
|
||||
emit("onModelChange", id, name);
|
||||
modelSelectVisible.value = false;
|
||||
};
|
||||
// 页面预览iframe引用
|
||||
const pagePreviewIframeRef = ref<any>(null);
|
||||
const sandboxVisible = ref(false);
|
||||
|
||||
// 打开沙盒切换抽屉
|
||||
const openSandboxDrawer = () => {
|
||||
sandboxVisible.value = true;
|
||||
};
|
||||
|
||||
// 抽屉内切换沙盒反馈
|
||||
const handleSandboxChangeInside = (id: string) => {
|
||||
emit("onSandboxChange", id);
|
||||
sandboxVisible.value = false;
|
||||
};
|
||||
|
||||
const handleSandboxClose = () => {
|
||||
sandboxVisible.value = false;
|
||||
};
|
||||
|
||||
// 点击工作台,打开文件树弹窗
|
||||
const handleOpenFileTree = () => {
|
||||
emit("onOpenFileTree");
|
||||
};
|
||||
|
||||
// 打开页面预览
|
||||
const handleOpenPagePreview = () => {
|
||||
if (!props.pageHomeIndex) return;
|
||||
// #ifdef H5 || WEB
|
||||
let uri =
|
||||
process.env.NODE_ENV === "production"
|
||||
? `${window.location.origin}${props.pageHomeIndex}`
|
||||
: props.pageHomeIndex;
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-WEIXIN
|
||||
let uri = props.pageHomeIndex;
|
||||
// #endif
|
||||
|
||||
emit("onOpenPagePreview", uri);
|
||||
};
|
||||
|
||||
// 选择组件
|
||||
const handleSelectComponent = (item: AgentManualComponentInfo) => {
|
||||
const selectedComponent: AgentSelectedComponentInfo = {
|
||||
id: item.id,
|
||||
type: item.type,
|
||||
};
|
||||
emit("onSelectComponent", selectedComponent);
|
||||
};
|
||||
|
||||
// 判断组件是否被选中
|
||||
const isSelected = (item: AgentManualComponentInfo): boolean => {
|
||||
return props.selectedComponents.some((selected) => selected.id === item.id);
|
||||
};
|
||||
|
||||
// 根据组件名称返回对应的图标类名
|
||||
const getIconClass = (name: string): string => {
|
||||
const lowerName = (name || "").toLowerCase();
|
||||
if (
|
||||
name.includes("搜索") ||
|
||||
name.includes("互联网") ||
|
||||
lowerName.includes("search") ||
|
||||
lowerName.includes("internet")
|
||||
) {
|
||||
return "icon-Globe";
|
||||
} else if (
|
||||
name.includes("研究") ||
|
||||
name.includes("深度") ||
|
||||
lowerName.includes("research") ||
|
||||
lowerName.includes("deep")
|
||||
) {
|
||||
return "icon-bulb";
|
||||
}
|
||||
return "";
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.manual-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 76rpx;
|
||||
|
||||
.manual-container {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 76rpx;
|
||||
scroll-behavior: smooth;
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
.manual-group {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.manual-box {
|
||||
gap: 6rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 76rpx;
|
||||
padding: 16rpx 24rpx;
|
||||
margin-right: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
border: 2rpx solid #f0f0f0;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&.active {
|
||||
background: #f2f2ff;
|
||||
border-color: #f2f2ff;
|
||||
|
||||
.icon {
|
||||
color: #4f46e5;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: #5147ff;
|
||||
}
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 32rpx;
|
||||
color: #6b7280;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
.text {
|
||||
color: rgba(21, 23, 31, 0.7);
|
||||
font-size: 28rpx;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
&.manual-select {
|
||||
border-color: #eeeeee;
|
||||
min-width: 100rpx;
|
||||
max-width: 300rpx;
|
||||
flex-shrink: 0;
|
||||
transition: all 0.3s ease;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.text {
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.icon-arrow-down {
|
||||
font-size: 24rpx;
|
||||
margin-left: -4rpx;
|
||||
color: rgba(21, 23, 31, 0.4);
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.6;
|
||||
background: #f5f5f5;
|
||||
pointer-events: auto;
|
||||
|
||||
.text {
|
||||
color: rgba(21, 23, 31, 0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.disabled {
|
||||
opacity: 0.6;
|
||||
background: #f5f5f5;
|
||||
pointer-events: none;
|
||||
|
||||
.text {
|
||||
color: rgba(21, 23, 31, 0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user