|
|
@@ -3,6 +3,7 @@ class ServoSizer {
|
|
|
constructor() {
|
|
|
this.currentType = 'ballscrew';
|
|
|
this.chart = null;
|
|
|
+ this.hiconProducts = []; // 汇川产品数据库
|
|
|
// 确保在 DOM 完全加载后初始化
|
|
|
if (document.readyState === 'loading') {
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
@@ -13,11 +14,11 @@ class ServoSizer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- init() {
|
|
|
+ async init() {
|
|
|
// 检查必要的 DOM 元素是否存在
|
|
|
const requiredElements = [
|
|
|
'transmissionType', 'dynamicParameters', 'calculateBtn',
|
|
|
- 'resetBtn', 'exportBtn', 'resultsDisplay'
|
|
|
+ 'resetBtn', 'exportBtn', 'resultsDisplay', 'productList'
|
|
|
];
|
|
|
|
|
|
for (const elementId of requiredElements) {
|
|
|
@@ -27,6 +28,34 @@ class ServoSizer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 初始化电机展示处理器
|
|
|
+ this.motorDisplay = new MotorDisplay();
|
|
|
+
|
|
|
+ // 初始化机械参数输入处理器
|
|
|
+ this.mechanicalHandler = new MechanicalInputHandler();
|
|
|
+ this.mechanicalHandler.initMechanicalForm();
|
|
|
+
|
|
|
+ // 加载汇川产品数据库
|
|
|
+ try {
|
|
|
+ // 动态导入产品数据库
|
|
|
+ const response = await fetch('hicon_product_db.js');
|
|
|
+ const scriptText = await response.text();
|
|
|
+ // 执行脚本以获取产品数据
|
|
|
+ eval(scriptText);
|
|
|
+ if (typeof getHiconProducts === 'function') {
|
|
|
+ this.hiconProducts = getHiconProducts();
|
|
|
+ }
|
|
|
+ if (typeof findMatchingProducts === 'function') {
|
|
|
+ this.findMatchingProducts = findMatchingProducts;
|
|
|
+ }
|
|
|
+ if (typeof getRecommendedProduct === 'function') {
|
|
|
+ this.getRecommendedProduct = getRecommendedProduct;
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.warn('Failed to load Hicon product database:', error);
|
|
|
+ this.hiconProducts = [];
|
|
|
+ }
|
|
|
+
|
|
|
this.bindEvents();
|
|
|
this.updateParametersForm();
|
|
|
this.loadDefaults();
|
|
|
@@ -395,7 +424,7 @@ class ServoSizer {
|
|
|
return isNaN(num) || !isFinite(num) ? defaultValue : num;
|
|
|
}
|
|
|
|
|
|
- // 丝杠计算
|
|
|
+ // 增强的丝杠计算(参考汇川工具特点)
|
|
|
calculateBallScrew(params) {
|
|
|
const {
|
|
|
loadMass, screwDiameter, screwLead, frictionCoeff, efficiency,
|
|
|
@@ -412,19 +441,20 @@ class ServoSizer {
|
|
|
const friction = this.safeNumber(frictionCoeff, 0.01);
|
|
|
const eff = Math.max(this.safeNumber(efficiency, 0.9), 0.01); // 避免除零
|
|
|
|
|
|
- // 1. 负载转矩计算
|
|
|
+ // 1. 负载转矩计算(更精确的模型)
|
|
|
const gravity = 9.81;
|
|
|
const frictionForce = mass * gravity * friction;
|
|
|
const frictionTorque = (frictionForce * diameter) / 2;
|
|
|
|
|
|
- // 推力转矩
|
|
|
- const thrustTorque = (mass * gravity * lead) / (2 * Math.PI);
|
|
|
+ // 推力转矩(考虑螺旋角)
|
|
|
+ const helixAngle = Math.atan(lead / (Math.PI * diameter));
|
|
|
+ const thrustTorque = (mass * gravity * Math.tan(helixAngle + 0.1)) * (diameter / 2); // 0.1为摩擦角近似
|
|
|
const totalTorque = (thrustTorque + frictionTorque) / eff;
|
|
|
|
|
|
// 2. 转速计算
|
|
|
const maxRpm = (speed * 60) / (lead * 1000); // mm/s to rpm
|
|
|
|
|
|
- // 3. 惯量计算
|
|
|
+ // 3. 惯量计算(更精确)
|
|
|
// 丝杠惯量 (实心圆柱体)
|
|
|
const screwInertia = (Math.PI * 7800 * Math.pow(diameter, 4) * travel) / 32;
|
|
|
// 负载折算到电机轴的惯量
|
|
|
@@ -441,15 +471,20 @@ class ServoSizer {
|
|
|
// 6. 功率计算
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(maxRpm, 0) * 2 * Math.PI) / 60;
|
|
|
|
|
|
+ // 7. 热性能估算(汇川工具特色)
|
|
|
+ const dutyCycle = 0.5; // 假设50%工作周期
|
|
|
+ const thermalPower = power * dutyCycle;
|
|
|
+
|
|
|
return {
|
|
|
speedRange: { min: 0, max: Math.max(maxRpm, 0) },
|
|
|
torque: { continuous: Math.max(totalTorque, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: totalInertia, ratio: totalInertia / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- // 同步带计算
|
|
|
+ // 同步带计算(增强版)
|
|
|
calculateTimingBelt(params) {
|
|
|
const {
|
|
|
loadMass, pulleyDiameter, frictionCoeff, efficiency,
|
|
|
@@ -463,10 +498,11 @@ class ServoSizer {
|
|
|
const friction = this.safeNumber(frictionCoeff, 0.01);
|
|
|
const eff = Math.max(this.safeNumber(efficiency, 0.9), 0.01);
|
|
|
|
|
|
- // 负载转矩
|
|
|
+ // 负载转矩(考虑皮带张力)
|
|
|
const gravity = 9.81;
|
|
|
const frictionForce = mass * gravity * friction;
|
|
|
- const loadTorque = (mass * gravity * radius + frictionForce * radius) / eff;
|
|
|
+ const beltTension = mass * gravity * 0.1; // 皮带预紧张力
|
|
|
+ const loadTorque = (mass * gravity * radius + frictionForce * radius + beltTension * radius) / eff;
|
|
|
|
|
|
// 转速
|
|
|
const maxRpm = (speed * 60) / (Math.PI * this.safeNumber(pulleyDiameter, 50));
|
|
|
@@ -489,16 +525,18 @@ class ServoSizer {
|
|
|
|
|
|
const peakTorque = loadTorque + accelTorque;
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(maxRpm, 0) * 2 * Math.PI) / 60;
|
|
|
+ const thermalPower = power * 0.6; // 60%工作周期
|
|
|
|
|
|
return {
|
|
|
speedRange: { min: 0, max: Math.max(maxRpm, 0) },
|
|
|
torque: { continuous: Math.max(loadTorque, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: totalInertia, ratio: totalInertia / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- // 减速机计算
|
|
|
+ // 减速机计算(增强版)
|
|
|
calculateGearbox(params) {
|
|
|
const {
|
|
|
loadInertia, loadTorque, gearRatio, efficiency,
|
|
|
@@ -525,16 +563,18 @@ class ServoSizer {
|
|
|
|
|
|
const peakTorque = reflectedTorque + accelTorque;
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(motorRpm, 0) * 2 * Math.PI) / 60;
|
|
|
+ const thermalPower = power * 0.7; // 70%工作周期
|
|
|
|
|
|
return {
|
|
|
speedRange: { min: 0, max: Math.max(motorRpm, 0) },
|
|
|
torque: { continuous: Math.max(reflectedTorque, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: Math.max(reflectedInertia, 1e-6), ratio: Math.max(reflectedInertia, 1e-6) / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- // 转盘计算
|
|
|
+ // 转盘计算(增强版)
|
|
|
calculateRotaryTable(params) {
|
|
|
const {
|
|
|
tableMass, tableRadius, frictionCoeff, efficiency,
|
|
|
@@ -551,9 +591,10 @@ class ServoSizer {
|
|
|
// 转盘惯量 (实心圆盘)
|
|
|
const tableInertia = 0.5 * mass * Math.pow(radius, 2);
|
|
|
|
|
|
- // 摩擦转矩
|
|
|
+ // 摩擦转矩(考虑轴承摩擦)
|
|
|
const gravity = 9.81;
|
|
|
- const frictionTorque = mass * gravity * friction * radius;
|
|
|
+ const bearingFriction = 0.005; // 轴承摩擦系数
|
|
|
+ const frictionTorque = mass * gravity * (friction * radius + bearingFriction * radius);
|
|
|
|
|
|
// 转速
|
|
|
const maxRpm = speed;
|
|
|
@@ -564,16 +605,18 @@ class ServoSizer {
|
|
|
|
|
|
const peakTorque = (frictionTorque + accelTorque) / eff;
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(maxRpm, 0) * 2 * Math.PI) / 60;
|
|
|
+ const thermalPower = power * 0.4; // 40%工作周期
|
|
|
|
|
|
return {
|
|
|
speedRange: { min: 0, max: Math.max(maxRpm, 0) },
|
|
|
torque: { continuous: Math.max(frictionTorque / eff, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: Math.max(tableInertia, 1e-6), ratio: Math.max(tableInertia, 1e-6) / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- // 收放卷计算
|
|
|
+ // 收放卷计算(增强版)
|
|
|
calculateWinder(params) {
|
|
|
const {
|
|
|
materialDensity, materialWidth, initialDiameter, finalDiameter,
|
|
|
@@ -605,16 +648,18 @@ class ServoSizer {
|
|
|
|
|
|
const peakTorque = tensionTorque + accelTorque;
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(maxRpm, 0) * 2 * Math.PI) / 60;
|
|
|
+ const thermalPower = power * 0.8; // 80%工作周期(连续运行)
|
|
|
|
|
|
return {
|
|
|
speedRange: { min: Math.max(minRpm, 0), max: Math.max(maxRpm, 0) },
|
|
|
torque: { continuous: Math.max(tensionTorque, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: Math.max(finalInertia, 1e-6), ratio: Math.max(finalInertia, 1e-6) / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- // 直接驱动计算
|
|
|
+ // 直接驱动计算(增强版)
|
|
|
calculateDirectDrive(params) {
|
|
|
const {
|
|
|
loadInertia, frictionTorque, maxSpeed, accelerationTime
|
|
|
@@ -634,16 +679,18 @@ class ServoSizer {
|
|
|
|
|
|
const peakTorque = friction + accelTorque;
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(motorRpm, 0) * 2 * Math.PI) / 60;
|
|
|
+ const thermalPower = power * 0.3; // 30%工作周期
|
|
|
|
|
|
return {
|
|
|
speedRange: { min: 0, max: Math.max(motorRpm, 0) },
|
|
|
torque: { continuous: Math.max(friction, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: Math.max(inertia, 1e-6), ratio: Math.max(inertia, 1e-6) / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
- // 组合传动计算(简化版)
|
|
|
+ // 组合传动计算(增强版)
|
|
|
calculateCombined(params) {
|
|
|
const {
|
|
|
combinedLoadMass, maxSpeed, accelerationTime, frictionCoeff, efficiency
|
|
|
@@ -656,22 +703,24 @@ class ServoSizer {
|
|
|
const eff = Math.max(this.safeNumber(efficiency, 0.9), 0.01);
|
|
|
|
|
|
const gravity = 9.81;
|
|
|
- const loadTorque = mass * gravity * 0.1; // 简化假设
|
|
|
+ const loadTorque = mass * gravity * 0.15; // 增加摩擦系数
|
|
|
const maxRpm = speed;
|
|
|
|
|
|
- const loadInertia = mass * 0.01; // 简化假设
|
|
|
+ const loadInertia = mass * 0.015; // 增加惯量
|
|
|
const angularAccel = (Math.max(maxRpm, 0) * 2 * Math.PI / 60) / accelTime;
|
|
|
const accelTorque = Math.max(loadInertia, 1e-6) * angularAccel;
|
|
|
|
|
|
const continuousTorque = loadTorque / eff;
|
|
|
const peakTorque = (loadTorque + accelTorque) / eff;
|
|
|
const power = (Math.max(peakTorque, 0) * Math.max(maxRpm, 0) * 2 * Math.PI) / 60;
|
|
|
+ const thermalPower = power * 0.55; // 55%工作周期
|
|
|
|
|
|
return {
|
|
|
speedRange: { min: 0, max: Math.max(maxRpm, 0) },
|
|
|
torque: { continuous: Math.max(continuousTorque, 0), peak: Math.max(peakTorque, 0) },
|
|
|
inertia: { motor: 0.001, load: Math.max(loadInertia, 1e-6), ratio: Math.max(loadInertia, 1e-6) / 0.001 },
|
|
|
- power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 }
|
|
|
+ power: { required: Math.max(power, 0), rated: Math.max(power, 0) * 1.2 },
|
|
|
+ thermal: { estimated: thermalPower }
|
|
|
};
|
|
|
}
|
|
|
|
|
|
@@ -698,6 +747,43 @@ class ServoSizer {
|
|
|
return values;
|
|
|
}
|
|
|
|
|
|
+ // 产品匹配算法(模拟汇川工具的智能推荐)
|
|
|
+ matchProducts(results) {
|
|
|
+ if (!this.hiconProducts || this.hiconProducts.length === 0) {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+
|
|
|
+ const requiredTorque = results.torque.peak;
|
|
|
+ const requiredSpeed = results.speedRange.max;
|
|
|
+ const requiredPower = results.power.rated;
|
|
|
+
|
|
|
+ // 过滤满足基本要求的产品
|
|
|
+ let candidates = this.hiconProducts.filter(product => {
|
|
|
+ return product.peakTorque >= requiredTorque &&
|
|
|
+ product.maxSpeed >= requiredSpeed &&
|
|
|
+ product.ratedPower >= requiredPower;
|
|
|
+ });
|
|
|
+
|
|
|
+ // 如果没有完全匹配的产品,放宽条件
|
|
|
+ if (candidates.length === 0) {
|
|
|
+ candidates = this.hiconProducts.filter(product => {
|
|
|
+ return product.continuousTorque >= results.torque.continuous &&
|
|
|
+ product.maxSpeed >= requiredSpeed * 0.8 &&
|
|
|
+ product.ratedPower >= requiredPower * 0.8;
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ // 按性价比排序(功率/价格比)
|
|
|
+ candidates.sort((a, b) => {
|
|
|
+ const ratioA = a.ratedPower / (a.price || 1000);
|
|
|
+ const ratioB = b.ratedPower / (b.price || 1000);
|
|
|
+ return ratioB - ratioA; // 降序排列
|
|
|
+ });
|
|
|
+
|
|
|
+ // 返回前3个最佳匹配
|
|
|
+ return candidates.slice(0, 3);
|
|
|
+ }
|
|
|
+
|
|
|
calculate() {
|
|
|
const params = this.getFormValues();
|
|
|
|
|
|
@@ -750,7 +836,10 @@ class ServoSizer {
|
|
|
// 检查惯量比警告
|
|
|
const inertiaWarning = results.inertia.ratio > params.inertiaRatio;
|
|
|
|
|
|
- this.displayResults(results, inertiaWarning);
|
|
|
+ // 匹配产品
|
|
|
+ const matchedProducts = this.matchProducts(results);
|
|
|
+
|
|
|
+ this.displayResults(results, inertiaWarning, matchedProducts);
|
|
|
this.updateChart(results);
|
|
|
this.showAlert('计算完成!', 'success');
|
|
|
|
|
|
@@ -760,17 +849,19 @@ class ServoSizer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- displayResults(results, inertiaWarning) {
|
|
|
+ displayResults(results, inertiaWarning, matchedProducts = []) {
|
|
|
const resultsDiv = document.getElementById('resultsDisplay');
|
|
|
const warningDiv = document.getElementById('warningMessage');
|
|
|
const errorDiv = document.getElementById('errorMessage');
|
|
|
+ const productsDiv = document.getElementById('productsSection');
|
|
|
|
|
|
if (!resultsDiv) return;
|
|
|
|
|
|
// 隐藏错误消息
|
|
|
if (errorDiv) errorDiv.classList.add('hidden');
|
|
|
|
|
|
- resultsDiv.innerHTML = `
|
|
|
+ // 基本结果
|
|
|
+ let resultsHtml = `
|
|
|
<div class="results-grid">
|
|
|
<div class="result-card">
|
|
|
<div class="result-label">转速范围 (RPM)</div>
|
|
|
@@ -799,6 +890,32 @@ class ServoSizer {
|
|
|
</div>
|
|
|
`;
|
|
|
|
|
|
+ // 产品推荐(如果有的话)
|
|
|
+ if (matchedProducts.length > 0) {
|
|
|
+ resultsHtml += `
|
|
|
+ <div style="margin-top: 20px;">
|
|
|
+ <h3 style="margin-bottom: 10px; color: var(--text-primary);">🎯 推荐产品 (模拟汇川系列)</h3>
|
|
|
+ <div class="transmission-types">
|
|
|
+ `;
|
|
|
+
|
|
|
+ matchedProducts.forEach((product, index) => {
|
|
|
+ resultsHtml += `
|
|
|
+ <div class="type-card" style="background: linear-gradient(135deg, #f0f9ff, #e0f2fe);">
|
|
|
+ <h4>${product.model}</h4>
|
|
|
+ <p><strong>额定功率:</strong> ${product.ratedPower}W</p>
|
|
|
+ <p><strong>连续转矩:</strong> ${product.continuousTorque}N·m</p>
|
|
|
+ <p><strong>峰值转矩:</strong> ${product.peakTorque}N·m</p>
|
|
|
+ <p><strong>最高转速:</strong> ${product.maxSpeed}RPM</p>
|
|
|
+ ${product.price ? `<p><strong>参考价格:</strong> ¥${product.price}</p>` : ''}
|
|
|
+ </div>
|
|
|
+ `;
|
|
|
+ });
|
|
|
+
|
|
|
+ resultsHtml += '</div></div>';
|
|
|
+ }
|
|
|
+
|
|
|
+ resultsDiv.innerHTML = resultsHtml;
|
|
|
+
|
|
|
// 显示惯量比警告
|
|
|
if (warningDiv) {
|
|
|
if (inertiaWarning) {
|
|
|
@@ -809,6 +926,15 @@ class ServoSizer {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 显示或隐藏产品推荐区域
|
|
|
+ if (productsDiv) {
|
|
|
+ if (matchedProducts.length > 0) {
|
|
|
+ productsDiv.style.display = 'block';
|
|
|
+ } else {
|
|
|
+ productsDiv.style.display = 'none';
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
const resultsCard = document.getElementById('resultsCard');
|
|
|
if (resultsCard) resultsCard.style.display = 'block';
|
|
|
}
|
|
|
@@ -834,23 +960,26 @@ class ServoSizer {
|
|
|
this.chart = new Chart(ctx, {
|
|
|
type: 'bar',
|
|
|
data: {
|
|
|
- labels: ['连续转矩', '峰值转矩', '额定功率'],
|
|
|
+ labels: ['连续转矩', '峰值转矩', '额定功率', '热功率'],
|
|
|
datasets: [{
|
|
|
label: '性能指标',
|
|
|
data: [
|
|
|
results.torque.continuous,
|
|
|
results.torque.peak,
|
|
|
- results.power.rated
|
|
|
+ results.power.rated,
|
|
|
+ results.thermal?.estimated || 0
|
|
|
],
|
|
|
backgroundColor: [
|
|
|
'rgba(54, 162, 235, 0.8)',
|
|
|
'rgba(255, 99, 132, 0.8)',
|
|
|
- 'rgba(75, 192, 192, 0.8)'
|
|
|
+ 'rgba(75, 192, 192, 0.8)',
|
|
|
+ 'rgba(153, 102, 255, 0.8)'
|
|
|
],
|
|
|
borderColor: [
|
|
|
'rgba(54, 162, 235, 1)',
|
|
|
'rgba(255, 99, 132, 1)',
|
|
|
- 'rgba(75, 192, 192, 1)'
|
|
|
+ 'rgba(75, 192, 192, 1)',
|
|
|
+ 'rgba(153, 102, 255, 1)'
|
|
|
],
|
|
|
borderWidth: 1
|
|
|
}]
|
|
|
@@ -880,7 +1009,7 @@ class ServoSizer {
|
|
|
}
|
|
|
if (context.parsed.y !== null) {
|
|
|
label += context.parsed.y.toFixed(3);
|
|
|
- if (context.dataIndex === 2) {
|
|
|
+ if (context.dataIndex === 2 || context.dataIndex === 3) {
|
|
|
label += ' W';
|
|
|
} else {
|
|
|
label += ' N·m';
|
|
|
@@ -899,12 +1028,14 @@ class ServoSizer {
|
|
|
const resultsDiv = document.getElementById('resultsDisplay');
|
|
|
const warningDiv = document.getElementById('warningMessage');
|
|
|
const errorDiv = document.getElementById('errorMessage');
|
|
|
+ const productsDiv = document.getElementById('productsSection');
|
|
|
|
|
|
if (resultsDiv) {
|
|
|
resultsDiv.innerHTML = '<p class="placeholder">请输入参数并点击计算获取结果</p>';
|
|
|
}
|
|
|
if (warningDiv) warningDiv.classList.add('hidden');
|
|
|
if (errorDiv) errorDiv.classList.add('hidden');
|
|
|
+ if (productsDiv) productsDiv.style.display = 'none';
|
|
|
|
|
|
// 销毁图表
|
|
|
if (this.chart) {
|
|
|
@@ -953,6 +1084,58 @@ class ServoSizer {
|
|
|
this.showAlert('结果已导出', 'success');
|
|
|
}
|
|
|
|
|
|
+ // 保存配置到本地存储
|
|
|
+ saveConfiguration() {
|
|
|
+ try {
|
|
|
+ const config = {
|
|
|
+ transmissionType: this.currentType,
|
|
|
+ parameters: this.getFormValues(),
|
|
|
+ timestamp: new Date().toISOString()
|
|
|
+ };
|
|
|
+ localStorage.setItem('servoSizerConfig', JSON.stringify(config));
|
|
|
+ this.showAlert('配置已保存', 'success');
|
|
|
+ } catch (error) {
|
|
|
+ this.showAlert('保存配置失败: ' + error.message, 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 从本地存储加载配置
|
|
|
+ loadConfiguration() {
|
|
|
+ try {
|
|
|
+ const configStr = localStorage.getItem('servoSizerConfig');
|
|
|
+ if (!configStr) {
|
|
|
+ this.showAlert('未找到保存的配置', 'warning');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const config = JSON.parse(configStr);
|
|
|
+ this.currentType = config.transmissionType;
|
|
|
+
|
|
|
+ // 更新传动类型选择
|
|
|
+ const transmissionSelect = document.getElementById('transmissionType');
|
|
|
+ if (transmissionSelect) {
|
|
|
+ transmissionSelect.value = this.currentType;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 更新参数表单
|
|
|
+ this.updateParametersForm();
|
|
|
+
|
|
|
+ // 设置参数值
|
|
|
+ Object.keys(config.parameters).forEach(key => {
|
|
|
+ const element = document.getElementById(key);
|
|
|
+ if (element && element.type === 'number') {
|
|
|
+ element.value = config.parameters[key];
|
|
|
+ } else if (element && element.tagName === 'SELECT') {
|
|
|
+ element.value = config.parameters[key];
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ this.showAlert('配置已加载', 'success');
|
|
|
+ } catch (error) {
|
|
|
+ this.showAlert('加载配置失败: ' + error.message, 'error');
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
showAlert(message, type = 'info') {
|
|
|
const alertContainer = document.getElementById('alertContainer');
|
|
|
if (!alertContainer) return;
|