新增相机限制

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 配置 # 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 # VITE_API_BASE_URL=https://api.yourdomain.com

View File

@ -221,6 +221,50 @@
cursor: pointer; 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 { #progress-container {
position: absolute; position: absolute;
@ -289,83 +333,76 @@
<div id="click-info-content"></div> <div id="click-info-content"></div>
</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="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-title">棚子尺寸</span>
<span class="category-arrow"></span> <span class="category-arrow expanded"></span>
</div> </div>
<div class="category-content"> <div class="category-content expanded">
<div class="option-group"> <div class="option-group">
<button class="option-btn" data-option="size-1">3*3</button> <button class="option-btn" data-option="size-1">SPF111S1013W</button>
<button class="option-btn" data-option="size-2">3x6</button> <button class="option-btn" data-option="size-2">SPF111S1013TA</button>
<button class="option-btn" data-option="size-3">10x13EM星空篷</button> <button class="option-btn" data-option="size-3">SPF111S1013C</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>
</div> </div>
</div> </div>
</div> </div>
<!-- 棚子类型 --> <!-- 百叶 -->
<div class="config-category"> <div class="config-category">
<div class="category-header" data-category="type"> <div class="category-header active" data-category="louver-1013">
<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">
<span class="category-title">百叶</span> <span class="category-title">百叶</span>
<span class="category-arrow"></span> <span class="category-arrow expanded"></span>
</div> </div>
<div class="category-content"> <div class="category-content expanded">
<div class="option-group"> <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-1">SPFPDS13FTW</button>
<button class="option-btn" data-option="color-2">SPFPDS13FTC</button> <button class="option-btn" data-option="color-2">SPFPDS13FTC</button>
<div>10</div> <button class="option-btn" data-option="color-3">SPFPDS10FTW</button>
<button class="option-btn" data-option="color-1">SPFPDS10FTW</button> <button class="option-btn" data-option="color-4">SPFPDS10FTC</button>
<button class="option-btn" data-option="color-2">SPFPDS10FTC</button> </div>
</div>
</div>
</div>
</div> <!-- 10x10 尺寸配置 -->
</div> <div class="tab-content" id="tab-size-1010">
</div> <!-- 棚子尺寸 -->
<!-- 配色 -->
<div class="config-category"> <div class="config-category">
<div class="category-header" data-category="color"> <div class="category-header active" data-category="size-1010">
<span class="category-title">配色</span> <span class="category-title">棚子尺寸</span>
<span class="category-arrow"></span> <span class="category-arrow expanded"></span>
</div> </div>
<div class="category-content"> <div class="category-content expanded">
<div class="option-group"> <div class="option-group">
<div>13</div> <button class="option-btn" data-option="size-4">SPF111S1010C</button>
<button class="option-btn" data-option="color-1">SPF111S1013W</button> <button class="option-btn" data-option="size-5">SPF111S1010TA</button>
<div>10</div> <button class="option-btn" data-option="size-6">SPF111S1010W</button>
<button class="option-btn" data-option="color-3">SPF111S1010TA</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> </div>
</div> </div>
@ -504,6 +541,21 @@
// ========== UI 交互逻辑 ========== // ========== 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 => { document.querySelectorAll('.category-header').forEach(header => {
header.addEventListener('click', function () { header.addEventListener('click', function () {

View File

@ -39,7 +39,7 @@ export const init = async (customConfig = {}) => {
const defaultConfig = { const defaultConfig = {
container: document.querySelector('#renderDom'), container: document.querySelector('#renderDom'),
modelUrlList: [], 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: { gizmo: {
position: false, position: false,
rotation: false, rotation: false,
@ -123,7 +123,6 @@ export const getPlacementZone = async (sku) => {
//执行事件 //执行事件
export const getEvent = async (dropzone_data, sku) => { export const getEvent = async (dropzone_data, sku) => {
console.log(sku);
// 将模型放置到该区域 // 将模型放置到该区域
try { try {
@ -153,6 +152,8 @@ export const executeEvent = async (dropzone_data, result, sku) => {
let modelId = null; // 在外部声明,用于在两个循环之间传递 let modelId = null; // 在外部声明,用于在两个循环之间传递
let modelName = null; let modelName = null;
let pergolaSku = null; // 用于存储棚子的 SKU
// 第一次循环:处理 change_model // 第一次循环:处理 change_model
for (const event of result.data.events) { for (const event of result.data.events) {
if (event.event_type === 'change_model') { if (event.event_type === 'change_model') {
@ -205,6 +206,20 @@ export const executeEvent = async (dropzone_data, result, sku) => {
console.log(`百叶模型颜色已替换为 ${color}`); 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(`检查模型 ${name + '_' + category} 是否存在:`, modelAlreadyExists);
} }
} }
console.log(hasModelChange && !modelAlreadyExists);
kernel.dropZone.hide(); kernel.dropZone.hide();
// 只有在需要更换模型且模型不存在时才清除 // 只有在需要更换模型且模型不存在时才清除
if (hasModelChange && !modelAlreadyExists) { if (hasModelChange && !modelAlreadyExists) {
@ -238,6 +252,8 @@ console.log(hasModelChange && !modelAlreadyExists);
// 先处理所有 change_model 事件 // 先处理所有 change_model 事件
for (const event of result.data.events) { for (const event of result.data.events) {
console.log(event);
if (event.event_type === 'change_model') { if (event.event_type === 'change_model') {
const { target_data } = event; const { target_data } = event;
console.log(event.target_data); console.log(event.target_data);

View File

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

View File

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

View File

@ -554,6 +554,24 @@ export class AppModel extends Monobehiver {
return undefined; 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[] { private getModelTransformTargets(meshes: AbstractMesh[]): AbstractMesh[] {
const meshSet = new Set<AbstractMesh>(meshes); const meshSet = new Set<AbstractMesh>(meshes);
const rootMeshes = meshes.filter(mesh => !mesh.parent || !meshSet.has(mesh.parent as AbstractMesh)); 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 => { exists: (modelId: string): boolean => {
return this.mainApp.appModel.exists(modelId); 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();
} }
}; };