数据格式
(1代表cpu、2代表主板、3代表内存、。。。)
1@i3 12100 @630
2@H610 @480
3@DDR4 3200 16G @220
4@500G M.2 @299
5@300W电源 @150
6@小机箱 @85
7@GT 730G 4G @350
8@WD 2T @399
9@飞利浦 24Led @580
主代码 Html + JS
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>电脑组装报价表</title>
<link rel="stylesheet" href="./iconfont/iconfont.css">
<link rel="stylesheet" href="css/index.css" />
</head>
<body>
<h1>电脑组装报价表</h1>
<form class="info no-print" autocomplete="off">
<textarea placeholder="请输入内容" class="uname" name="uname" lay-verify="required" style="width: 500px;height: 100px;"></textarea>
<button class="add">
<i class="iconfont icon-tianjia"></i>录入
</button>
</form>
<div class="title no-print">共有数据<span>0</span>条</div>
<table>
<thead>
<tr>
<th>ID</th>
<th>类别</th>
<th>配件名称</th>
<th>数量</th>
<th>单价</th>
<th>金额</th>
<th>录入时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<!-- 表格内容 -->
</tbody>
</table>
<div class="title heji">大写: <strong>零</strong> 合计:<span>0</span>元</div>
<div class="boot">
<button class="printer no-print">
<i class="iconfont icon-tianjia"></i>打印
</button>
</div>
<script src="js/daxie.js"></script>
<script>
// 参考数据
const initData = [
{
stuId: 1,
bname: 'cpu',
goods: 'i3 12100',
sl: 1,
dj: 630,
je: 630,
time: '2099/9/9 08:08:08'
}
]
// 1. 渲染业务
// 1.1 先读取本地存储的数据
// (1). 本地存储有数据则记得转换为对象然后存储到变量里面,后期用于渲染页面
// (2). 如果没有数据,则用 空数组来代替
let count = 0 //合计数据
const arr = JSON.parse(localStorage.getItem('data')) || []
console.log('数据arr:',arr)
// 1.2 利用map和join方法来渲染页面
const tbody = document.querySelector('tbody')
function render() {
// (1). 利用map遍历数组,返回对应tr的数组
const trArr = arr.map(function (ele, index) {
count +=parseInt(ele.dj)
return `
<tr>
<td>${ele.stuId}</td>
<td>${ele.bname}</td>
<td>${ele.goods}</td>
<td>${ele.sl}</td>
<td>${ele.dj}</td>
<td>${ele.je}</td>
<td>${ele.time}</td>
<td>
<a href="javascript:" data-id="${index}">
<i class="iconfont icon-shanchu"></i>
删除
</a>
</td>
</tr>
`
count +=ele.dj // 合计储存数据
})
console.log(trArr)
// (2). 把数组转换为字符串 join
// (3). 把生成的字符串追加给tbody
tbody.innerHTML = trArr.join('')
// 显示共计有几条数据
document.querySelector('.title span').innerHTML = arr.length
}
render()
// 2. 新增业务
const info = document.querySelector('.info')
const uname = document.querySelector('.uname')
// 2.1 form表单注册提交事件,阻止默认行为
info.addEventListener('submit', function (e) {
e.preventDefault()
// 2.2 非空判断
if (!uname.value) {
return alert('输入内容不能为空')
}
const dataT = [] // 接收新的数据对像
let lines = uname.value.split("\n");
console.log(lines)
// console.log(typeof(lines))
// 2.3 给 arr 数组追加对象,里面存储 表单获取过来的数据
for (let line of lines) {
let parts = line.split("@"); // 将每行分割成组件编号、名称和价格
console.log(parts)
let [number, name, price] = parts;
price = price.trim(); // 去除价格两侧的空格
// 根据组件编号创建对象,并添加到结果数组中
if (number === "1") {
dataT.push({ id: "1", lx: "cpu", pj: name, jg: price });
} else if (number === "2") {
dataT.push({ id: "2", lx: "主板", pj: name, jg: price });
} else if (number === "3") {
dataT.push({ id: "3", lx: "内存", pj: name, jg: price });
} else if (number === "4") {
dataT.push({ id: "4", lx: "固态硬盘", pj: name, jg: price });
} else if (number === "5") {
dataT.push({ id: "5", lx: "电源", pj: name, jg: price });
} else if (number === "6") {
dataT.push({ id: "6", lx: "机箱", pj: name, jg: price });
} else if (number === "7") {
dataT.push({ id: "7", lx: "外置显卡", pj: name, jg: price });
} else if (number === "8") {
dataT.push({ id: "8", lx: "机械硬盘", pj: name, jg: price });
} else if (number === "9") {
dataT.push({ id: "9", lx: "显示器", pj: name, jg: price });
}
}
for (let i = 0; i < dataT.length; i++){
arr.push({
// 处理 stuId:数组最后一条数据的stuId + 1
stuId: arr.length ? arr[arr.length - 1].stuId + 1 : 1,
bname: dataT[i].lx,
goods: dataT[i].pj,
sl: 1,
dj: dataT[i].jg,
je: dataT[i].jg,
time: new Date().toLocaleString()
})
// 2.4 渲染页面和重置表单(reset()方法)
render()
}
this.reset() // 重置表单
// 2.5 把数组重新存入本地存储里面,记得转换为JSON字符串存储
localStorage.setItem('data', JSON.stringify(arr))
location.reload(); // 刷新显示储存数据 合计结果
})
// 3. 删除业务
// 3.1 采用事件委托形式,给 tbody 注册点击事件
tbody.addEventListener('click', function (e) {
// 判断是否点击的是删除按钮 A 链接
if (e.target.tagName === 'A') {
// alert(11)
// 3.2 得到当前点击链接的索引号。渲染数据的时候,动态给a链接添加自定义属性例如 data-id="0"
console.log(e.target.dataset.id)
// 确认框 确认是否要真的删除
if (confirm('您确定要删除这条数据吗?')) {
// 3.3 根据索引号,利用 splice 删除数组这条数据
arr.splice(e.target.dataset.id, 1)
// 3.4 重新渲染页面
render()
// 3.5 把最新 arr 数组存入本地存储
localStorage.setItem('data', JSON.stringify(arr))
location.reload(); // 刷新显示储存数据 合计结果
}
}
})
// 显示小写合计
console.log('数量:',count)
document.querySelector('.heji span').innerHTML = count
// 显示大写合计,用numberTochinese 函数转成大写
let Num = numberToChinese(count)
document.querySelector('.heji strong').innerHTML = Num
// 打印
function printPage() {
window.print();
}
// 监听打印按钮
const pr = document.querySelector('.printer')
pr.addEventListener('click',function(){
printPage();
})
</script>
</body>
</html>
注1:其中数据转换:
let parts = line.split("@"); // 将每行分割成组件编号、名称和价格
// 根据组件编号创建对象,并添加到结果数组中
if (number === "1") {
dataT.push({ id: "1", lx: "cpu", pj: name, jg: price });
} else if (number === "2") {
dataT.push({ id: "2", lx: "主板", pj: name, jg: price });
} else if (number === "3") {
dataT.push({ id: "3", lx: "内存", pj: name, jg: price });
} else if (number === "4") {
dataT.push({ id: "4", lx: "固态硬盘", pj: name, jg: price });
} else if (number === "5") {
dataT.push({ id: "5", lx: "电源", pj: name, jg: price });
} else if (number === "6") {
dataT.push({ id: "6", lx: "机箱", pj: name, jg: price });
} else if (number === "7") {
dataT.push({ id: "7", lx: "外置显卡", pj: name, jg: price });
} else if (number === "8") {
dataT.push({ id: "8", lx: "机械硬盘", pj: name, jg: price });
} else if (number === "9") {
dataT.push({ id: "9", lx: "显示器", pj: name, jg: price });
}
注2:两条内存 未解决 可以当 双条 合成 1套
注3:打印 只是用CSS 隐藏 不打印的
CSS代码 index.css
* {
margin: 0;
padding: 0;
}
a {
text-decoration: none;
color: #721c24;
}
h1 {
text-align: center;
color: #333;
margin: 20px 0;
}
.title {
width: 933px;
height: 50px;
line-height: 50px;
padding-right: 15px;
border: 1px solid #ebebeb;
margin: 10px auto;
background-color: #f2f2f2;
text-align: right;
}
.title span {
display: inline-block;
vertical-align: middle;
height: 20px;
margin: -3px 5px 0;
text-align: center;
line-height: 20px;
color: #f26934;
font-weight: 700;
}
table {
margin: 0 auto;
width: 950px;
border-collapse: collapse;
color: #3c3637;
}
th {
padding: 10px;
background: #f2f2f2;
font-size: 18px;
text-align: left;
}
td,
th {
border: 1px solid #bbbaba;
padding: 15px;
}
td {
color: #080808;
font-size: 16px;
}
tbody tr {
background: #fff;
}
tbody tr:hover {
background: #fbfafa;
}
tbody a {
display: inline-block;
width: 80px;
height: 30px;
text-align: center;
line-height: 30px;
color: #fff;
background-color: #f26934;
}
.info {
width: 900px;
margin: 50px auto;
text-align: center;
}
.info input,
.info select {
width: 100px;
height: 30px;
outline: none;
border: 1px solid #ebebeb;
padding-left: 5px;
box-sizing: border-box;
margin-right: 10px;
}
.info button {
width: 70px;
height: 30px;
background-color: #5dbfd8;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
font-size: 14px;
}
.info button:hover {
background-color: #52abc1;
}
.printer {
width: 70px;
height: 30px;
background-color: #5dbfd8;
outline: none;
border: 0;
color: #fff;
cursor: pointer;
font-size: 14px;
}
.printer:hover {
background-color: #52abc1;
}
.boot {
margin: 0 auto;
width: 950px;
padding-bottom: 20px;
text-align: center;
}
/* 对打印机进行样式设置 */
@media print {
.no-print {
display: none; /* 在打印时隐藏带有no-print类的元素 */
}
td,th {
border: 1px solid #1a1a1a;
padding: 15px;
}
}
@media print {
@page {
margin-top: 0;
margin-bottom: 0;
}
header, footer {
display: none;
}
}
小写转大写 JS代码 daxie.js
function numberToChinese(num) {
const digit = {
0: '零',
1: '壹',
2: '贰',
3: '叁',
4: '肆',
5: '伍',
6: '陆',
7: '柒',
8: '捌',
9: '玖',
};
const unit = ['', '拾', '佰', '仟', '万', '亿'];
const moneyStr = String(num.toFixed(2));
const moneyArr = moneyStr.split('.');
const integralPart = Number(moneyArr[0]);
const decimalPart = Number(moneyArr[1]);
const toChinese = (num) => {
const numArr = String(num).split('');
const len = numArr.length;
const resultArr = [];
for (let i = 0; i < len; i++) {
const digitIndex = Number(numArr[i]);
if (i !== len - 1 && digitIndex !== 0) {
resultArr.push(digit[digitIndex], unit[len - i - 1]);
} else {
resultArr.push(digit[digitIndex]);
}
}
return resultArr.join('');
};
if (num === 0) {
return '零元整';
}
const result = toChinese(integralPart);
if (decimalPart === 0) {
return result + '元整';
} else {
return result + '元' + toChinese(decimalPart) + '角';
}
}
console.log(numberToChinese(123456789.12)); // 壹亿贰仟叁佰肆拾伍万陆仟柒佰捌拾玖元壹角贰分