*{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}

Basic Mutual Conversion (Wire Break Detection + Unit + Decimal Places)

Range Lower Limit (Value corresponding to 4mA)

Range Upper Limit (Value corresponding to 20mA)

Engineering Value Unit

Decimal Places (1~6)

Input Current mA

Engineering Value: -- Percentage: 0.00%

Save This Record

Copy Result

Input Engineering Value

Current: -- mA Percentage: 0.00%

Save This Record

Copy Result

Batch Conversion

Batch Input (1 current mA per line, automatically converted to engineering value + percentage)

Batch Calculate

Save All to Records

All Conversion Records

Export CSV File

Clear All Records

Current (mA)

Engineering Value

Unit

Percentage (%)

Status

// Global record array

let recordList = [];

const tableTbody = document.querySelector("#recordTable tbody");

// Get global configuration

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};

}

// Determine if current is abnormal (wire break)

function isAbnormalCurrent(curr){

return curr < 4 || curr > 20;

}

// Convert current to engineering value and percentage

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)

};

}

// Convert engineering value to current and percentage

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)

};

}

// Real-time refresh of current conversion

function refreshCurrView(){

const {unit} = getConfig();

const curr = parseFloat(document.getElementById("currIn").value);

const box = document.getElementById("currResult");

if(isNaN(curr)){

box.innerHTML = `Engineering Value: -- ${unit} Percentage: 0.00%`;

box.className = "result-box";

return;

}

const res = currToProc(curr);

let html = `Engineering Value: ${res.proc} ${unit} Percentage: ${res.pct}%`;

box.className = "result-box";

if(isAbnormalCurrent(curr)){

box.classList.add("warn");

html += " [Wire Break Abnormal]";

}

box.innerHTML = html;

}

// Real-time refresh of engineering value conversion

function refreshProcView(){

const {unit,decimal} = getConfig();

const proc = parseFloat(document.getElementById("procIn").value);

const box = document.getElementById("procResult");

if(isNaN(proc)){

box.innerHTML = `Current: -- mA Percentage: 0.00%`;

box.className = "result-box";

return;

}

const res = procToCurr(proc);

const currVal = parseFloat(res.curr);

let html = `Current: ${res.curr} mA Percentage: ${res.pct}%`;

box.className = "result-box";

if(isAbnormalCurrent(currVal)){

box.classList.add("warn");

html += " [Wire Break Abnormal]";

}

box.innerHTML = html;

}

// Bind all input listeners

["minRange","maxRange","unitText","decimalNum","currIn","procIn"].forEach(id=>{

document.getElementById(id).addEventListener("input",()=>{

refreshCurrView();

refreshProcView();

})

})

// Save current conversion record

function saveCurrRecord(){

const {unit} = getConfig();

const curr = parseFloat(document.getElementById("currIn").value);

if(isNaN(curr)) return alert("Please enter a valid current");

const r = currToProc(curr);

const status = isAbnormalCurrent(curr) ? "Abnormal" : "Normal";

recordList.push({

curr:curr.toFixed(getConfig().decimal),

proc:r.proc,

unit:unit,

pct:r.pct,

status:status

});

renderRecord();

}

// Save engineering value conversion record

function saveProcRecord(){

const {unit,decimal} = getConfig();

const proc = parseFloat(document.getElementById("procIn").value);

if(isNaN(proc)) return alert("Please enter a valid engineering value");

const r = procToCurr(proc);

const currVal = parseFloat(r.curr);

const status = isAbnormalCurrent(currVal) ? "Abnormal" : "Normal";

recordList.push({

curr:r.curr,

proc:proc.toFixed(decimal),

unit:unit,

pct:r.pct,

status:status

});

renderRecord();

}

// Render record table

function renderRecord(){

tableTbody.innerHTML = "";

recordList.forEach(item=>{

const tr = document.createElement("tr");

let warnTd = item.status === "Abnormal" ? 'style="color:red"' : "";

tr.innerHTML = `

${item.curr}

${item.proc}

${item.unit}

${item.pct}

${item.status}

`;

tableTbody.appendChild(tr);

})

}

// Clear all records

function clearAllRecord(){

recordList = [];

renderRecord();

}

// Copy result

function copyCurr(){

const txt = document.getElementById("currResult").innerText.trim();

navigator.clipboard.writeText(txt).then(()=>alert("Copied: "+txt))

}

function copyProc(){

const txt = document.getElementById("procResult").innerText.trim();

navigator.clipboard.writeText(txt).then(()=>alert("Copied: "+txt))

}

// Batch calculation

function calcBatch(){

const {unit} = getConfig();

const text = document.getElementById("batchInput").value.trim();

const lines = text.split("\n").filter(v=>v.trim()!="");

let html = "Current (mA) Engineering Value Unit Percentage Status

";

lines.forEach(line=>{

const c = parseFloat(line.trim());

if(isNaN(c)) return;

const r = currToProc(c);

const status = isAbnormalCurrent(c) ? "Abnormal" : "Normal";

const red = isAbnormalCurrent(c) ? 'style="color:red"' : "";

html += `

${c}

${r.proc}

${unit}

${r.pct}%

${status}

`;

})

html += "";

document.getElementById("batchOut").innerHTML = html;

}

// Save all batch to records

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) ? "Abnormal" : "Normal";

recordList.push({

curr:c.toFixed(decimal),

proc:r.proc,

unit:unit,

pct:r.pct,

status:status

});

})

renderRecord();

alert("Batch data has been saved to the record table");

}

// Export CSV

function exportCSV(){

if(recordList.length === 0) return alert("No records to export");

let csv = "Current (mA),Engineering Value,Unit,Percentage (%),Status\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_Conversion_Records.csv";

a.click();

URL.revokeObjectURL(a.href);

}

// Page initialization refresh

refreshCurrView();

refreshProcView();