*{box-sizing:border-box;margin:0;padding:0;font-family:"Microsoft YaHei",sans-serif}
body{max-width:1100px;margin:20px auto;padding:0 15px;background:#f3f6fa}
.container{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px}
@media(max-width:768px){.container{grid-template-columns:1fr}}
.card{background:#fff;padding:20px;border-radius:10px;box-shadow:0 1px 8px #00000012}
h2{text-align:center;color:#2a3442;margin-bottom:18px;font-size:20px}
h3{margin:16px 0 10px;color:#333;font-size:16px}
.group{margin-bottom:14px}
label{display:block;margin-bottom:5px;color:#444;font-weight:500}
input,textarea{width:100%;padding:9px 12px;border:1px solid #d0d7e3;border-radius:6px;font-size:15px;outline:0}
input:focus,textarea:focus{border-color:#2b7cd3}
.row{display:flex;gap:10px;align-items:center}
.result-box{padding:12px;background:#e8f3ff;border-radius:6px;margin-top:8px;font-weight:bold;color:#1c4b82}
.percent{color:#238547;margin-left:12px}
.warn{color:#dc3545 !important;}
.btn{background:#2b7cd3;color:#fff;border:none;padding:7px 12px;border-radius:5px;cursor:pointer;font-size:14px}
.btn:hover{background:#2068b9}
.btn-danger{background:#dc3545}
.btn-danger:hover{background:#bb2d3b}
.btn-success{background:#28a745}
.btn-success:hover{background:#218838}
.divider{height:1px;background:#e2e8f0;margin:22px 0}
table{width:100%;border-collapse:collapse;margin-top:10px;font-size:14px}
th,td{border:1px solid #dee2e6;padding:8px;text-align:center}
th{background:#f1f5fb}
.record-wrap{max-height:320px;overflow:auto}
.oper-bar{display:flex;gap:8px;margin:10px 0}
.tip{font-size:12px;color:#666;margin-top:4px}
.set-row{display:grid;grid-template-columns:1fr 1fr;gap:10px}
Базовое взаимное преобразование (обнаружение обрыва + единицы + десятичные знаки)
Нижний предел диапазона (значение, соответствующее 4 мА)
Верхний предел диапазона (значение, соответствующее 20 мА)
Единица инженерного значения
Количество десятичных знаков (1~6)
Входной ток, мА
Инженерное значение: -- Доля: 0.00%
Сохранить эту запись
Копировать результат
Введите инженерное значение
Ток: -- мА Доля: 0.00%
Сохранить эту запись
Копировать результат
Пакетное преобразование
Пакетный ввод (по 1 току в мА на строку, автоматическое преобразование в инженерное значение + процент)
Пакетный расчёт
Сохранить всё в записи
Все записи преобразований
Экспорт в CSV-файл
Очистить все записи
Ток (мА)
Инженерное значение
Единица
Процент (%)
Статус
// Глобальный массив записей
let recordList = [];
const tableTbody = document.querySelector("#recordTable tbody");
// Получить глобальную конфигурацию
function getConfig(){
const min = parseFloat(document.getElementById("minRange").value) || 0;
const max = parseFloat(document.getElementById("maxRange").value) || 100;
const span = max - min;
const unit = document.getElementById("unitText").value.trim();
const dec = parseInt(document.getElementById("decimalNum").value) || 2;
const decimal = Math.max(1, Math.min(6, dec));
return {min,max,span,unit,decimal};
}
// Определить, является ли ток аномальным (обрыв)
function isAbnormalCurrent(curr){
return curr < 4 || curr > 20;
}
// Преобразование тока в инженерное значение, процент
function currToProc(curr){
const {min,max,span,decimal} = getConfig();
const proc = min + span * (curr - 4) / 16;
const pct = ((curr - 4)/16 * 100);
return {
proc: proc.toFixed(decimal),
pct: pct.toFixed(decimal)
};
}
// Преобразование инженерного значения в ток, процент
function procToCurr(proc){
const {min,max,span,decimal} = getConfig();
const curr = 4 + 16 * (proc - min) / span;
const pct = ((proc - min)/span * 100);
return {
curr: curr.toFixed(decimal),
pct: pct.toFixed(decimal)
};
}
// Обновление отображения преобразования тока в реальном времени
function refreshCurrView(){
const {unit} = getConfig();
const curr = parseFloat(document.getElementById("currIn").value);
const box = document.getElementById("currResult");
if(isNaN(curr)){
box.innerHTML = `Инженерное значение: -- ${unit} Доля: 0.00%`;
box.className = "result-box";
return;
}
const res = currToProc(curr);
let html = `Инженерное значение: ${res.proc} ${unit} Доля: ${res.pct}%`;
box.className = "result-box";
if(isAbnormalCurrent(curr)){
box.classList.add("warn");
html += " 【Обрыв цепи】";
}
box.innerHTML = html;
}
// Обновление отображения преобразования инженерного значения в реальном времени
function refreshProcView(){
const {unit,decimal} = getConfig();
const proc = parseFloat(document.getElementById("procIn").value);
const box = document.getElementById("procResult");
if(isNaN(proc)){
box.innerHTML = `Ток: -- мА Доля: 0.00%`;
box.className = "result-box";
return;
}
const res = procToCurr(proc);
const currVal = parseFloat(res.curr);
let html = `Ток: ${res.curr} мА Доля: ${res.pct}%`;
box.className = "result-box";
if(isAbnormalCurrent(currVal)){
box.classList.add("warn");
html += " 【Обрыв цепи】";
}
box.innerHTML = html;
}
// Привязать все слушатели ввода
["minRange","maxRange","unitText","decimalNum","currIn","procIn"].forEach(id=>{
document.getElementById(id).addEventListener("input",()=>{
refreshCurrView();
refreshProcView();
})
})
// Сохранить запись преобразования тока
function saveCurrRecord(){
const {unit} = getConfig();
const curr = parseFloat(document.getElementById("currIn").value);
if(isNaN(curr)) return alert("Введите корректный ток");
const r = currToProc(curr);
const status = isAbnormalCurrent(curr) ? "Аномалия" : "Норма";
recordList.push({
curr:curr.toFixed(getConfig().decimal),
proc:r.proc,
unit:unit,
pct:r.pct,
status:status
});
renderRecord();
}
// Сохранить запись преобразования инженерного значения
function saveProcRecord(){
const {unit,decimal} = getConfig();
const proc = parseFloat(document.getElementById("procIn").value);
if(isNaN(proc)) return alert("Введите корректное инженерное значение");
const r = procToCurr(proc);
const currVal = parseFloat(r.curr);
const status = isAbnormalCurrent(currVal) ? "Аномалия" : "Норма";
recordList.push({
curr:r.curr,
proc:proc.toFixed(decimal),
unit:unit,
pct:r.pct,
status:status
});
renderRecord();
}
// Отрисовка таблицы записей
function renderRecord(){
tableTbody.innerHTML = "";
recordList.forEach(item=>{
const tr = document.createElement("tr");
let warnTd = item.status === "Аномалия" ? 'style="color:red"' : "";
tr.innerHTML = `
${item.curr}
${item.proc}
${item.unit}
${item.pct}
${item.status}
`;
tableTbody.appendChild(tr);
})
}
// Очистить все записи
function clearAllRecord(){
recordList = [];
renderRecord();
}
// Копировать результат
function copyCurr(){
const txt = document.getElementById("currResult").innerText.trim();
navigator.clipboard.writeText(txt).then(()=>alert("Скопировано: "+txt))
}
function copyProc(){
const txt = document.getElementById("procResult").innerText.trim();
navigator.clipboard.writeText(txt).then(()=>alert("Скопировано: "+txt))
}
// Пакетный расчёт
function calcBatch(){
const {unit} = getConfig();
const text = document.getElementById("batchInput").value.trim();
const lines = text.split("\n").filter(v=>v.trim()!="");
let html = "Ток (мА) Инженерное значение Единица Процент Статус
";
lines.forEach(line=>{
const c = parseFloat(line.trim());
if(isNaN(c)) return;
const r = currToProc(c);
const status = isAbnormalCurrent(c) ? "Аномалия" : "Норма";
const red = isAbnormalCurrent(c) ? 'style="color:red"' : "";
html += `
${c}
${r.proc}
${unit}
${r.pct}%
${status}
`;
})
html += "";
document.getElementById("batchOut").innerHTML = html;
}
// Пакетное сохранение в записи
function saveAllBatch(){
const {unit,decimal} = getConfig();
const text = document.getElementById("batchInput").value.trim();
const lines = text.split("\n").filter(v=>v.trim()!="");
lines.forEach(line=>{
const c = parseFloat(line.trim());
if(isNaN(c)) return;
const r = currToProc(c);
const status = isAbnormalCurrent(c) ? "Аномалия" : "Норма";
recordList.push({
curr:c.toFixed(decimal),
proc:r.proc,
unit:unit,
pct:r.pct,
status:status
});
})
renderRecord();
alert("Пакетные данные сохранены в таблицу записей");
}
// Экспорт CSV
function exportCSV(){
if(recordList.length === 0) return alert("Нет записей для экспорта");
let csv = "Ток (мА),Инженерное значение,Единица,Процент (%),Статус\n";
recordList.forEach(item=>{
csv += `${item.curr},${item.proc},${item.unit},${item.pct},${item.status}\n`;
})
const blob = new Blob([csv],{type:"text/csv;charset=utf-8"});
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "4-20mA_записи_преобразований.csv";
a.click();
URL.revokeObjectURL(a.href);
}
// Инициализация и обновление страницы
refreshCurrView();
refreshProcView();