新增相机限制

This commit is contained in:
2026-05-20 16:40:47 +08:00
parent 8dc9371cc5
commit b5b70251e2
7 changed files with 177 additions and 78 deletions

4
.env
View File

@ -1,6 +1,8 @@
# API 配置
# 开发环境
VITE_API_BASE_URL=https://ztserver.zguiy.com
VITE_API_BASE_URL=http://192.168.3.100:26517
#生产环境
# VITE_API_BASE_URL=https://ztserver.zguiy.com
# 生产环境示例(部署时修改)
# VITE_API_BASE_URL=https://api.yourdomain.com

View File

@ -221,6 +221,50 @@
cursor: pointer;
}
/* 标签页样式 */
.tabs-container {
margin-bottom: 15px;
}
.tabs-header {
display: flex;
gap: 8px;
margin-bottom: 15px;
border-bottom: 2px solid rgba(255, 255, 255, 0.1);
}
.tab-btn {
padding: 10px 20px;
background: rgba(255, 255, 255, 0.05);
color: rgba(255, 255, 255, 0.6);
border: none;
border-bottom: 2px solid transparent;
cursor: pointer;
font-size: 13px;
transition: all 0.3s;
flex: 1;
margin-bottom: -2px;
}
.tab-btn:hover {
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.8);
}
.tab-btn.active {
background: rgba(76, 175, 80, 0.2);
color: #fff;
border-bottom-color: #4CAF50;
}
.tab-content {
display: none;
}
.tab-content.active {
display: block;
}
/* 进度条样式 */
#progress-container {
position: absolute;
@ -289,83 +333,76 @@
<div id="click-info-content"></div>
</div>
<!-- 标签页容器 -->
<div class="tabs-container">
<div class="tabs-header">
<button class="tab-btn active" data-tab="size-1013">10x13 尺寸</button>
<button class="tab-btn" data-tab="size-1010">10x10 尺寸</button>
</div>
<!-- 10x13 尺寸配置 -->
<div class="tab-content active" id="tab-size-1013">
<!-- 棚子尺寸 -->
<div class="config-category">
<div class="category-header" data-category="size">
<div class="category-header active" data-category="size-1013">
<span class="category-title">棚子尺寸</span>
<span class="category-arrow"></span>
<span class="category-arrow expanded"></span>
</div>
<div class="category-content">
<div class="category-content expanded">
<div class="option-group">
<button class="option-btn" data-option="size-1">3*3</button>
<button class="option-btn" data-option="size-2">3x6</button>
<button class="option-btn" data-option="size-3">10x13EM星空篷</button>
<button class="option-btn" data-option="size-4">全铁3x6</button>
<button class="option-btn" data-option="size-1">10x12</button>
<button class="option-btn" data-option="size-2">SPF111S1010W</button>
<button class="option-btn" data-option="size-3">SPF111S1013W</button>
<button class="option-btn" data-option="size-4">10x20星空篷</button>
<button class="option-btn" data-option="size-1">SPF111S1013W</button>
<button class="option-btn" data-option="size-2">SPF111S1013TA</button>
<button class="option-btn" data-option="size-3">SPF111S1013C</button>
</div>
</div>
</div>
<!-- 棚子类型 -->
<!-- 百叶 -->
<div class="config-category">
<div class="category-header" data-category="type">
<span class="category-title">棚子类型</span>
<span class="category-arrow"></span>
</div>
<div class="category-content">
<div class="option-group">
<button class="option-btn" data-option="type-1">平顶</button>
<button class="option-btn" data-option="type-2">尖顶</button>
<button class="option-btn" data-option="type-3">弧形</button>
<button class="option-btn" data-option="type-4">异形</button>
</div>
</div>
</div>
<!-- 百叶 (单选) -->
<div class="config-category">
<div class="category-header" data-category="louver">
<div class="category-header active" data-category="louver-1013">
<span class="category-title">百叶</span>
<span class="category-arrow"></span>
<span class="category-arrow expanded"></span>
</div>
<div class="category-content">
<div class="category-content expanded">
<div class="option-group">
<button class="option-btn" data-option="louver-1">SPFPDS13FTW</button>
<button class="option-btn" data-option="louver-2">SPFPDS13FTC</button>
<button class="option-btn" data-option="louver-3">3m下拉帘</button>
<button class="option-btn" data-option="louver-4">SPFSW13FTW</button>
<button class="option-btn" data-option="louver-4">SPFSW10FTW</button>
<button class="option-btn" data-option="louver-4">SPFPDS10FTC</button>
<button class="option-btn" data-option="louver-4">SPFPDS10FTW</button>
<div>13</div>
<button class="option-btn" data-option="color-1">SPFPDS13FTW</button>
<button class="option-btn" data-option="color-2">SPFPDS13FTC</button>
<div>10</div>
<button class="option-btn" data-option="color-1">SPFPDS10FTW</button>
<button class="option-btn" data-option="color-2">SPFPDS10FTC</button>
<button class="option-btn" data-option="color-3">SPFPDS10FTW</button>
<button class="option-btn" data-option="color-4">SPFPDS10FTC</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 配色 -->
<!-- 10x10 尺寸配置 -->
<div class="tab-content" id="tab-size-1010">
<!-- 棚子尺寸 -->
<div class="config-category">
<div class="category-header" data-category="color">
<span class="category-title">配色</span>
<span class="category-arrow"></span>
<div class="category-header active" data-category="size-1010">
<span class="category-title">棚子尺寸</span>
<span class="category-arrow expanded"></span>
</div>
<div class="category-content">
<div class="category-content expanded">
<div class="option-group">
<div>13</div>
<button class="option-btn" data-option="color-1">SPF111S1013W</button>
<div>10</div>
<button class="option-btn" data-option="color-3">SPF111S1010TA</button>
<button class="option-btn" data-option="size-4">SPF111S1010C</button>
<button class="option-btn" data-option="size-5">SPF111S1010TA</button>
<button class="option-btn" data-option="size-6">SPF111S1010W</button>
</div>
</div>
</div>
<!-- 百叶 -->
<div class="config-category">
<div class="category-header active" data-category="louver-1010">
<span class="category-title">百叶</span>
<span class="category-arrow expanded"></span>
</div>
<div class="category-content expanded">
<div class="option-group">
<button class="option-btn" data-option="color-3">SPFPDS10FTW</button>
<button class="option-btn" data-option="color-4">SPFPDS10FTC</button>
</div>
</div>
</div>
</div>
</div>
@ -504,6 +541,21 @@
// ========== UI 交互逻辑 ==========
// 标签页切换
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', function () {
const tabId = this.dataset.tab;
// 移除所有标签页的激活状态
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
// 激活当前标签页
this.classList.add('active');
document.getElementById('tab-' + tabId).classList.add('active');
});
});
// 折叠面板切换
document.querySelectorAll('.category-header').forEach(header => {
header.addEventListener('click', function () {

View File

@ -39,7 +39,7 @@ export const init = async (customConfig = {}) => {
const defaultConfig = {
container: document.querySelector('#renderDom'),
modelUrlList: [],
env: { envPath: 'https://sdk.zguiy.com/resurces/hdr/hdr.env', intensity: 1.2, rotationY: 0.3, background: true },
env: { envPath: 'https://sdk.zguiy.com/resurces/hdr/hdr.env', intensity: 1.2, rotationY: 0.3, background: false },
gizmo: {
position: false,
rotation: false,
@ -123,7 +123,6 @@ export const getPlacementZone = async (sku) => {
//执行事件
export const getEvent = async (dropzone_data, sku) => {
console.log(sku);
// 将模型放置到该区域
try {
@ -153,6 +152,8 @@ export const executeEvent = async (dropzone_data, result, sku) => {
let modelId = null; // 在外部声明,用于在两个循环之间传递
let modelName = null;
let pergolaSku = null; // 用于存储棚子的 SKU
// 第一次循环:处理 change_model
for (const event of result.data.events) {
if (event.event_type === 'change_model') {
@ -205,6 +206,20 @@ export const executeEvent = async (dropzone_data, result, sku) => {
console.log(`百叶模型颜色已替换为 ${color}`);
}
}
// 查找棚子的 SKU从已加载的模型中查找 model_control_type 为 'pergola' 的模型)
const allModels = kernel.model.getAllMetadata();
for (const model of allModels) {
if (model.modelControlType === 'pergola') {
pergolaSku = getSkuByModelId(model.modelId);
if (pergolaSku) {
break;
}
}
}
console.log('当前棚子的 SKU:', pergolaSku);
return pergolaSku;
}
@ -225,7 +240,6 @@ export const executeEvent2 = async (result, sku) => {
console.log(`检查模型 ${name + '_' + category} 是否存在:`, modelAlreadyExists);
}
}
console.log(hasModelChange && !modelAlreadyExists);
kernel.dropZone.hide();
// 只有在需要更换模型且模型不存在时才清除
if (hasModelChange && !modelAlreadyExists) {
@ -238,6 +252,8 @@ console.log(hasModelChange && !modelAlreadyExists);
// 先处理所有 change_model 事件
for (const event of result.data.events) {
console.log(event);
if (event.event_type === 'change_model') {
const { target_data } = event;
console.log(event.target_data);

View File

@ -29,8 +29,7 @@ export class AppCamera extends Monobehiver {
this.object.panningSensibility = 0;
// 限制垂直角范围,实现上帝视角
// this.object.upperBetaLimit = Tools.ToRadians(60); // 最大垂直角接近90度避免万向锁
// this.object.lowerBetaLimit = Tools.ToRadians(60); // 最小垂直角
this.object.upperBetaLimit = Tools.ToRadians(90); // 最大垂直角接近90度避免万向锁
this.object.position = new Vector3(-0, 10, 0);
this.setTarget(0, 2, 0);

View File

@ -12,7 +12,7 @@ export const AppConfig = {
envPath: '/hdr/sanGiuseppeBridge.env',
intensity: 1.5,
rotationY: 0,
background: true,
background: false,
},
gizmo: {
position: true,

View File

@ -554,6 +554,24 @@ export class AppModel extends Monobehiver {
return undefined;
}
/**
* 获取所有模型的元数据
* @returns 所有模型的元数据数组
*/
getAllModelMetadata(): ModelMetadata[] {
const keys = this.modelDic.Keys();
const metadataList: ModelMetadata[] = [];
for (const key of keys) {
const metadata = this.modelMetadataDic.Get(key);
if (metadata) {
metadataList.push(metadata);
}
}
return metadataList;
}
private getModelTransformTargets(meshes: AbstractMesh[]): AbstractMesh[] {
const meshSet = new Set<AbstractMesh>(meshes);
const rootMeshes = meshes.filter(mesh => !mesh.parent || !meshSet.has(mesh.parent as AbstractMesh));

View File

@ -82,6 +82,18 @@ export class KernelAdapter {
*/
exists: (modelId: string): boolean => {
return this.mainApp.appModel.exists(modelId);
},
/**
* 获取所有模型的元数据
* @returns 所有模型的元数据数组,包含 modelName, modelId, modelControlType 等信息
* @example
* // 获取所有模型
* const allModels = kernel.model.getAllMetadata();
* // 查找特定类型的模型
* const pergola = allModels.find(m => m.modelControlType === 'pergola');
*/
getAllMetadata: (): any[] => {
return this.mainApp.appModel.getAllModelMetadata();
}
};