单据统计 对账单 Node.js+Layui+Json 增删改查 功能有 打印 导出 放大图片查看 搜索商家单据 刷新 table单行多行变 图片上传 还没有的 按时间线搜索 搜索商家统计不好 多删除

后端 index.js 主程序:

const express = require('express') //require函数引入express包
const app = express() //调用函数
const routes = require('./routes/index');  //引入路由模块
const hostname = 'localhost';
const port = 3007;

//实现静态资源服务
app.use(express.static('./')) //public就是静态资源的根目录,静态资源放于此文件夹
 
 //中间件
 app.use((req,resp,next) => {
     //中文乱码处理
     resp.header('Content-Type','text/html;charset=utf-8');
     next();
 });
 app.use((req,resp,next) => {
     //跨域设置
     resp.header("Access-Control-Allow-Credentials", true);
     resp.header("Access-Control-Allow-Origin", "*");
     resp.header("Access-Control-Allow-Headers", "X-Requested-With");
     resp.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
     resp.header("X-Powered-By", ' 3.2.1');
     resp.header("Content-Type", "application/json;charset=utf-8");
     next();
 });
 const path = require('path');

 
 app.engine('html', require('express-art-template'));
 //添加解析参数模块,能够解析POST方式提交的参数
 const bodyParser = require('body-parser');
 app.use(bodyParser.urlencoded({extended:true}));
  app.use(bodyParser.json());
  
 app.use(routes); //挂载路由到app服务中
 
app.listen(3007, () => { //创建监听
	console.log(`server is running at http://${hostname}:${port}/`);
    console.log('服务器启动成功...')
})

后端 routes/index.js 路由

var express = require('express');
var router = express.Router();
const moment = require('moment');
const fs = require('fs');
const Goods = require('../db/goods.js');
const multer = require('multer');
const path = require("path");


router.get('/goodslist', (req, res) => {
	console.log(req.query);
	Goods.find(req.query, (err, data, count) => {
		if (err) return res.status(500).send('Server Error.');
		// console.log(data);
		res.json({
			code: 0,
			msg: "",
			data: data,
			count: count
		});
	});
});


// 添加商品
router.post('/addGoods', (req, res) => {
	Goods.save(req.body, (err) => {
		if (err) return res.status(500).send('Server Error.');
		res.status(200).json({
			err_code: 0,
			message: 'OK'
		});
	});
});


// 编辑页面

// 编辑商品操作
router.post('/editGoods', (req, res) => {
	Goods.updateById(req.body, (err) => {
		if (err) return res.status(500).send('Server Error.');
		res.status(200).json({
			err_code: 0,
			message: 'OK'
		});
	});
});

// 删除商品操作
router.get('/deleteGoods', (req, res) => {
	Goods.deleteById(req.query.id, (err) => {
		if (err) return res.status(500).send('Server Error.');
		res.status(200).json({
			err_code: 0,
			message: 'OK'
		});
	});
});

const storage = multer.diskStorage({
	destination: function(req, file, cb) {
		cb(null, './upload')
	},
	filename: function(req, file, cb) {
		// const uniqueSuffix = Date.now()
		// cb(null, uniqueSuffix + '-' +file.originalname)
		// 解决中文名乱码的问题
		file.originalname = Buffer.from(file.originalname, "latin1").toString(
			"utf8"
		);
		cb(null, file.originalname)
	}
});
router.post('/upload', multer({
	storage: storage
}).single('file'), (req, res) => {
	// console.log(req.file);
	// res.send(req.file)
	// res.json()
	const url = '../upload/' + req.file.filename;
	res.json({
		code: 0,
		msg: '上传成功!',
		data: {
			src: url,
		}
	});
});
module.exports = router;

 后端 中间件 db/goods.js

const fs = require('fs');
const dbPath = './db/goods.json';
const moment = require('moment');

// 商品列表
exports.find = (query, callback) => {
	fs.readFile(dbPath, (err, data) => {
		if (err) {
			callback(err);
		}
		// 处理分页
		var page = query.page;
		var limit = query.limit;
		var data = JSON.parse(data);
		var name = query.name;
		data.count = data.data.length;

		if (name != '' && name != undefined) {
			var sd = data.data.slice(0, data.count);
			var sd = sd.filter(function(item) {
				return item.name.includes(name);
			});
		} else {
			if (page == page && limit == limit) {
			// var ppp = 0;
			var starts = parseInt((page * limit) - 10);
			var end = parseInt((page * limit));
			// 截取对应数据
			var sd = data.data.slice(starts, end);
		}
		}

		// console.log(sd);
		callback(null, sd, data.count);
	});
}
// 添加商品
exports.save = (u, callback) => {
	fs.readFile(dbPath, (err, data) => {
		if (err) {
			callback(err);
		}
		var dbU = JSON.parse(data).data;
		// 数组里面为空时的id问题
		u.id = dbU.length == 0 ? 1 : u.id = dbU[dbU.length - 1].id + 1;

		// 当前的时间
		var goods_creatime = moment(Date.now()).format('YYYY-MM-DD HH:mm:ss');
		u.goods_creatime = goods_creatime;

		dbU.push(u);

		var fileData = JSON.stringify({
			data: dbU
		});

		fs.writeFile(dbPath, fileData, (err) => {
			if (err) {
				callback(err);
			}
			callback(null);
		});
	});
}

// 编辑操作
exports.updateById = (u, callback) => {
	fs.readFile(dbPath, (err, data) => {
		if (err) callback(err);
		var goods = JSON.parse(data).data;
		// console.log(goods);
		u.id = parseInt(u.id);
		var dbU = goods.find(item => {
			return item.id === u.id;
		});

		for (var key in u) {
			dbU[key] = u[key];
		}
		var fileData = JSON.stringify({
			data: goods
		});
		fs.writeFile(dbPath, fileData, (err) => {
			if (err) {
				return callback(err);
			}
			callback(null);
		});
	});
}

//删除操作
exports.deleteById = (id, callback) => {
	fs.readFile(dbPath, (err, data) => {
		var u = JSON.parse(data).data;
		var deleteId = u.findIndex(item => {
			return id == item.id;
		});
		u.splice(deleteId, 1);
		var fileData = JSON.stringify({
			data: u
		});
		fs.writeFile(dbPath, fileData, (err) => {
			if (err) {
				return callback(err);
			}
			callback(null);
		});
	});
}

后端 json数据库 db/goods.json

{
	"data": [{
		"id": 10000,
		"name": "志拓",
		"sl": "1",
		"je": "20",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10001,
		"name": "普佳",
		"sl": "1",
		"je": "30",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10002,
		"name": "user-2",
		"sl": "1",
		"je": "40",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10003,
		"name": "user-3",
		"sl": "1",
		"je": "30",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10004,
		"name": "user-4",
		"sl": "2",
		"je": "34",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10005,
		"name": "user-5",
		"sl": "2",
		"je": "800",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10006,
		"name": "user-6",
		"sl": "1",
		"je": "555",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10007,
		"name": "user-7",
		"sl": "1",
		"je": "22",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明"
	}, {
		"id": 10008,
		"name": "user-811",
		"sl": "2",
		"je": "333",
		"img": "./img/01.png",
		"date": "2023-10-26",
		"bz": "备注说明1"
	}, {
		"name": "普佳",
		"sl": "1",
		"je": "233",
		"img": "../upload/360卫士.png",
		"file": "",
		"date": "2023-10-30",
		"bz": "22",
		"id": 10009,
		"goods_creatime": "2023-10-30 09:38:16"
	}, {
		"name": "普佳",
		"sl": "223",
		"je": "112",
		"img": "../upload/01.png",
		"file": "",
		"date": "2023-10-30",
		"bz": "112",
		"id": 10010,
		"goods_creatime": "2023-10-30 09:38:39"
	}]
}

前端 主页 index.html

<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>单据统计</title>
		<link rel="stylesheet" href="./layui/css/layui.css">
	</head>
	<body style="padding: 30px;">
		<form class="layui-form layui-row layui-col-space16">
			<div class="layui-col-md4">
				<div class="layui-input-wrap">
					<div class="layui-input-prefix">
						<i class="layui-icon layui-icon-username"></i>
					</div>
					<input type="text" name="name" value="" placeholder="商家名称" class="layui-input" lay-affix="clear">

				</div>
			</div>
			<div class="layui-col-md4">
				<div class="layui-input-wrap">
					<div class="layui-input-prefix">
						<i class="layui-icon layui-icon-date"></i>
					</div>
					<input type="text" name="B" placeholder="开始日期" lay-affix="clear"
						class="layui-input demo-table-search-date">
				</div>
			</div>
			<div class="layui-col-md4">
				<div class="layui-input-wrap">
					<div class="layui-input-prefix">
						<i class="layui-icon layui-icon-date"></i>
					</div>
					<input type="text" name="C" readonly placeholder="结束日期" class="layui-input demo-table-search-date">
				</div>
			</div>
			<div class="layui-btn-container layui-col-xs12">
				<button class="layui-btn" lay-submit lay-filter="demo-table-search">搜索</button>
				<button type="reset" class="layui-btn layui-btn-primary">重置</button>
			</div>
		</form>
		<table class="layui-hide" id="ID-table-demo-search"></table>


		<script type="text/html" id="barDemo">
			<div class="layui-clear-space">
				<a class="layui-btn layui-btn-xs" lay-event="detail">查看</a>
				<a class="layui-btn layui-btn-xs layui-bg-orange" lay-event="edit">编辑</a>
				<a class="layui-btn layui-btn-xs layui-bg-red" lay-event="del">删除</a>
			</div>
		</script>
		<script type="text/html" id="imgDemo">
			<img src="{{d.img}}" width="100%" onclick='previewImg(this)'>
		</script>
		<!-- 引用该 layui.js  -->
		<script src="./layui/layui.js"></script>
		<script>
			layui.use(function() {
				var layer = layui.layer;
				var table = layui.table;
				var form = layui.form;
				var laydate = layui.laydate;
				var $ = layui.jquery;

				// 创建表格实例
				table.render({
					elem: '#ID-table-demo-search',
					url: '/goodslist', // 此处为静态模拟数据,实际使用时需换成真实接口
					title: '单据',
					fieldTitle: '单据合计',
					toolbar: 'default',
					defaultToolbar: ['filter', 'exports', 'print', {
						title: '设为单行',
						layEvent: 'LAYTABLE_TIPS',
						icon: 'layui-icon-success'
					}, {
						title: '开启多行',
						layEvent: 'LAYTABLE_TIPS1',
						icon: 'layui-icon-slider'
					},{
						title: '刷新主页',
						layEvent: 'LAYTABLE_TIPS2',
						icon: 'layui-icon-refresh'
					}],
					totalRow: true, // 开启合计行
					even: true, // 是否开启隔行背景。
					cols: [
						[{
								type: 'checkbox',
								title: '😊',
								fixed: true
							}, // 单选框
							{
								field: 'id',
								title: 'ID',
								width: 80,
								sort: true,
								fixed: true,
								totalRowText: '合计:'
							},
							{
								field: 'name',
								title: '商家名称'
							},
							{
								field: 'sl',
								title: '数量',
								width: 80,
								totalRow: '{{= parseInt(d.TOTAL_NUMS) }} 张'
							},
							{
								field: 'je',
								title: '金额',
								width: 80,
								totalRow: '{{= parseInt(d.TOTAL_NUMS) }} 元'
							},
							{
								field: 'img',
								title: '单据图',
								width: 150,
								toolbar: '#imgDemo'
							},
							{
								field: 'date',
								title: '日期',
								width: 150,
								sort: true,
							},
							{
								field: 'bz',
								title: '备注',
								width: 250
							},
							{
								fixed: 'right',
								title: '操作',
								width: 134,
								minWidth: 155,
								toolbar: '#barDemo'
							}
						]
					],
					page: true,
					// height: 310
				});
				
				// 日期
				laydate.render({
					elem: '.demo-table-search-date'
				});
				
				// 搜索提交
				form.on('submit(demo-table-search)', function(data) {
					var field = data.field; // 获得表单字段
					// 执行搜索重载
					table.reload('ID-table-demo-search', {
						page: {
							curr: 1 // 重新从第 1 页开始
						},
						URL: '/goodlist',
						where: field // 搜索的字段
					});
					// layer.msg('搜索成功<br>此处为静态模拟数据,实际使用时换成真实接口即可');
					return false; // 阻止默认 form 跳转
				});

				// 头部工具栏事件 右边
				table.on('toolbar(ID-table-demo-search)', function(obj) {
					var checkStatus = table.checkStatus(obj.config.id); // 获取当前表格属性配置项 获取选中行相关数据
					var data = checkStatus.data; // 获取选中的数据
					// console.log(obj); // 查看对象所有成员
					console.log(data);

					// 根据不同的事件名进行相应的操作
					switch (obj.event) { // 对应模板元素中的 lay-event 属性值
						case 'add':
							// layer.msg('添加');
							layer.open({
								title: '添加商品信息',
								type: 2,
								area: ['80%', '80%'],
								shadeClose: true,
								content: './views/add.html'
							});
							break;
						case 'delete':
							if (data.length === 0) {
								return layer.msg('请选择一行');
							};
							layer.msg('删除');
							break;
						case 'update':
							layer.msg('编辑');
							if (data.length !== 1) return layer.msg('请选择一行');
							layer.open({
								title: '编辑商品信息',
								type: 2,
								area: ['80%', '80%'],
								shadeClose: true,
								content: './views/edit.html',
								success: function(layero, index) {
									var body = layer.getChildFrame('body', index);
									var iframeWin = window[layero.find('iframe')[0][
									'name']]; //得到iframe页的窗口对象,执行iframe页的方法:iframeWin.method();
									// console.log(body.html()) //得到iframe页的body内容
									// body.find(".classifyid").val(classifyid); //要修改的每个td的值存为变量传进去
									body.find('#uid').val(data[0].id);
									body.find('#name').val(data[0].name);
									body.find('#sl').val(data[0].sl);
									body.find('#je').val(data[0].je);
									body.find('#img').val(data[0].img);
									body.find('#date').val(data[0].date);
									body.find('#bz').val(data[0].bz);
								}
							});
							break;
						case 'LAYTABLE_TIPS':
							table.reload('ID-table-demo-search', {
								lineStyle: null // 恢复单行
							});
							layer.msg('已设为单行');
							break;
						case 'LAYTABLE_TIPS1':
							table.reload('ID-table-demo-search', {
								// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
								lineStyle: 'height: 95px;'
							});
							layer.msg('开启多行');
							break;
					case 'LAYTABLE_TIPS2':
							// table.reload('ID-table-demo-search', {
							// 	// 设置行样式,此处以设置多行高度为例。若为单行,则没必要设置改参数 - 注:v2.7.0 新增
								
							// });
							window.location.reload();
							// window.replace(location.href);
							layer.msg('刷新');
							break;
					};
				});

				//监听工具条
				table.on('tool(ID-table-demo-search)', function(obj) {
					var data = obj.data;
					// console.log(data);
					if (obj.event === 'detail') {
						layer.msg('ID:' + data.id + '😜' + data.name + '🤔'+ data.img , {
							icon: 6
						});
					} else if (obj.event === 'del') {
						layer.confirm('确定删除这条数据吗', function(
							index) {
							$.ajax({
								type: 'get',
								url: '/deleteGoods',
								data: {
									id: data.id
								},
								// dataType: 'json',
								success: function(data) {
									obj.del();
									layer.close(index);
									layer.msg('删除成功');
								},
								error: function(xhr) {
									layer.msg('删除失败' + xhr.status);
								}
							});
						});
					} else if (obj.event === 'edit') {
						// layer.alert('编辑行:<br>' + JSON.stringify(data));
						console.log(data);
						layer.open({
							title: '编辑商品信息',
							type: 2,
							area: ['80%', '80%'],
							shadeClose: true,
							// content: 'goods_edit.html',
							content: './views/edit.html',
							success: function(layero, index) {
								var body = layer.getChildFrame('body', index);
								var iframeWin = window[layero.find('iframe')[0][
								'namex']]; //得到iframe页的窗口对象,执行iframe页的方法:iframeWin.method();
								// console.log(body.html()) //得到iframe页的body内容
								// body.find(".classifyid").val(classifyid); //要修改的每个td的值存为变量传进去
								body.find('#uid').val(data.id);
								body.find('#name').val(data.name);
								body.find('#sl').val(data.sl);
								body.find('#je').val(data.je);
								body.find('#img').val(data.img);
								body.find('#date').val(data.date);
								body.find('#bz').val(data.bz);
							}
						});
					}
				});
			});
		</script>

		<script>
			function previewImg(obj) {
				var img = new Image();
				img.src = obj.src;
				var height = img.height; //获取图片高度
				var width = img.width; //获取图片宽度
				if (height > 1000 || width > 800) {
					height = height / 2;
					width = width / 2;
				}
				var imgHtml = "<img src='" + obj.src + "' style='width: " + width + "px;height:" + height + "px'/>";
				layer.open({
					type: 1,
					offset: 'auto',
					area: [width + 'px', height + 'px'],
					shadeClose: true, //点击外围关闭弹窗
					scrollbar: true, //不现实滚动条
					title: false, //不显示标题
					content: imgHtml, //捕获的元素,注意:最好该指定的元素要存放在body最外层,否则可能被其它的相对元素所影响
					cancel: function() {

					}
				});
			}
		</script>
	</body>
</html>

前端 弹出 添加页 views/add.html

<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>添加</title>
		<link rel="stylesheet" href="../layui/css/layui.css" />
	</head>
	<body style="padding: 30px;">

		<form class="layui-form" action="">
			<div class="layui-form-item">
				<label class="layui-form-label">商家名称</label>
				<div class="layui-input-block">
					<input type="text" name="name" required lay-verify="required" placeholder="请输入商品名称"
						autocomplete="off" class="layui-input">
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">数量</label>
				<div class="layui-input-inline">
					<input type="number" name="sl" required lay-verify="required" placeholder="请输入数量"
						autocomplete="off" class="layui-input">
				</div>
				<div class="layui-form-mid layui-word-aux"></div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">金额</label>
				<div class="layui-input-inline">
					<input type="number" name="je" required lay-verify="required" placeholder="请输入金额"
						autocomplete="off" class="layui-input">
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">单据图</label>
				<div class="layui-input-inline">
					<input type="text" name="img" required lay-verify="required" placeholder="请输入图片路径"
						id="img" autocomplete="off" class="layui-input">
				</div>
				<div class="layui-form-mid layui-word-aux"></div>
			</div>
			<div class="layui-form-item">
				<div class="layui-input-inline" style="padding-left: 110px;">
					<button type="button" class="layui-btn" id="ID-upload-demo-btn">
						<i class="layui-icon layui-icon-upload"></i> 单图片上传
					</button>
					<div style="width: 132px;">
						<div class="layui-upload-list">
							<img class="layui-upload-img" id="ID-upload-demo-img" style="width: 100%; height: 92px;">
							<div id="ID-upload-demo-text"></div>
						</div>
						<div class="layui-progress layui-progress-big" lay-showPercent="yes" lay-filter="filter-demo">
							<div class="layui-progress-bar" lay-percent=""></div>
						</div>
					</div>
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">日期</label>
				<div class="layui-input-inline">
					<div class="layui-input-inline layui-input-wrap">
						<div class="layui-input-prefix">
							<i class="layui-icon layui-icon-date"></i>
						</div>
						<input type="text" name="date" id="date" lay-verify="date" placeholder="yyyy-MM-dd"
							autocomplete="off" class="layui-input">
					</div>
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">备注</label>
				<div class="layui-input-inline">
					<input type="text" name="bz" required lay-verify="required" placeholder="请输入说胆" autocomplete="off"
						class="layui-input">
				</div>
			</div>

			<div class="layui-form-item">
				<div class="layui-input-block">
					<button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button>
					<button type="reset" class="layui-btn layui-btn-primary">重置</button>
				</div>
			</div>

		</form>

		<script src="../layui/layui.js"></script>
		<script>
			//Demo
			layui.use('form', function() {
				var form = layui.form;
				var $ = layui.jquery;
				var upload = layui.upload;
				var layer = layui.layer;
				var element = layui.element;
				var laydate = layui.laydate;

				// 日期
				laydate.render({
					elem: '#date',
					value: new Date()
				});

				// 单图片上传
				var uploadInst = upload.render({
					elem: '#ID-upload-demo-btn',
					url: '/upload', // 实际使用时改成您自己的上传接口即可。
					before: function(obj) {
						// 预读本地文件示例,不支持ie8
						obj.preview(function(index, file, result) {
							$('#ID-upload-demo-img').attr('src', result); // 图片链接(base64)
						});

						element.progress('filter-demo', '0%'); // 进度条复位
						layer.msg('上传中', {
							icon: 16,
							time: 0
						});
					},
					done: function(res) {
						// 若上传失败
						if (res.code > 0) {
							return layer.msg('上传失败');
						}
						// 上传成功的一些操作
						$('#img').val(res.data.src);
						$('#ID-upload-demo-text').html(''); // 置空上传失败的状态
					},
					error: function() {
						// 演示失败状态,并实现重传
						var demoText = $('#ID-upload-demo-text');
						demoText.html(
							'<span style="color: #FF5722;">上传失败</span> <a class="layui-btn layui-btn-xs demo-reload">重试</a>'
						);
						demoText.find('.demo-reload').on('click', function() {
							uploadInst.upload();
						});
					},
					// 进度条
					progress: function(n, elem, e) {
						element.progress('filter-demo', n + '%'); // 可配合 layui 进度条元素使用
						if (n == 100) {
							layer.msg('上传完毕', {
								icon: 1
							});
						}
					}
				});

				//监听提交
				form.on('submit(formDemo)', function(data) {
					// 提交的数据
					// layer.msg(JSON.stringify(data.field));
					// var formData = JSON.stringify(data.field);

					// console.log(index);
					$.ajax({
						type: 'post',
						dataType: 'json',
						url: '/addGoods',
						data: data.field,
						dataType: 'json',
						success: function(data) {
							if (data.err_code == 0) {
								// console.log(data.err_code);
								layer.msg('添加成功');
								setTimeout(function() {
									window.parent.location.href = '../index.html';
								}, 1100);
							}
							if (data.err_code == 1) {
								layer.msg('添加失败');
							}
							// alert('添加成功');
						}
					});
					return false;
				});

				
			});
		</script>
	</body>


</html>

前端 弹出 修改页 views/edit.html

<!DOCTYPE html>
<html lang="zh">
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1.0">
		<title>修改</title>
		<link rel="stylesheet" href="../layui/css/layui.css" />
	</head>
	<body style="padding: 30px;">

		<form class="layui-form" action="">
			<!-- 隐藏id -->
			<input type="hidden" name="id" id="uid">
			<div class="layui-form-item">
				<label class="layui-form-label">商家名称</label>
				<div class="layui-input-block">
					<input type="text" name="name" id="name" required lay-verify="required" placeholder="请输入商品名称"
						autocomplete="off" class="layui-input">
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">数量</label>
				<div class="layui-input-inline">
					<input type="number" name="sl" id="sl" required lay-verify="required" placeholder="请输入数量"
						autocomplete="off" class="layui-input">
				</div>
				<div class="layui-form-mid layui-word-aux"></div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">金额</label>
				<div class="layui-input-inline">
					<input type="number" name="je" id="je" required lay-verify="required" placeholder="请输入重量"
						autocomplete="off" class="layui-input">
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">单据图</label>
				<div class="layui-input-inline">
					<input type="text" name="img" required lay-verify="required" placeholder="请输入图片路径" id="img"
						autocomplete="off" class="layui-input">
				</div>
				<div class="layui-form-mid layui-word-aux"></div>
			</div>
			<div class="layui-form-item">
				<div class="layui-input-inline" style="padding-left: 110px;">
					<button type="button" class="layui-btn" id="ID-upload-demo-btn">
						<i class="layui-icon layui-icon-upload"></i> 单图片上传
					</button>
					<div style="width: 132px;">
						<div class="layui-upload-list">
							<img class="layui-upload-img" id="ID-upload-demo-img" style="width: 100%; height: 92px;">
							<div id="ID-upload-demo-text"></div>
						</div>
						<div class="layui-progress layui-progress-big" lay-showPercent="yes" lay-filter="filter-demo">
							<div class="layui-progress-bar" lay-percent=""></div>
						</div>
					</div>
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">日期</label>
				<div class="layui-input-inline">
					<div class="layui-input-inline layui-input-wrap">
						<div class="layui-input-prefix">
							<i class="layui-icon layui-icon-date"></i>
						</div>
						<input type="text" name="date" id="date" lay-verify="date" placeholder="yyyy-MM-dd"
							autocomplete="off" class="layui-input">
					</div>
				</div>
			</div>
			<div class="layui-form-item">
				<label class="layui-form-label">备注</label>
				<div class="layui-input-inline">
					<input type="text" name="bz" id="bz" required lay-verify="required" placeholder="请输入说明"
						autocomplete="off" class="layui-input">
				</div>
			</div>

			<div class="layui-form-item">
				<div class="layui-input-block">
					<button class="layui-btn" lay-submit lay-filter="formDemo">立即提交</button>
					<button type="reset" class="layui-btn layui-btn-primary">重置</button>
				</div>
			</div>

		</form>

		<script src="../layui/layui.js"></script>
		<script>
			//Demo
			layui.use('form', function() {
				var form = layui.form;
				var $ = layui.jquery;
				var laydate = layui.laydate;

				// 日期
				laydate.render({
					elem: '#date',
					value: new Date()
				});

				//监听提交
				form.on('submit(formDemo)', function(data) {
					// 提交的数据
					// layer.msg(JSON.stringify(data.field));
					// var formData = JSON.stringify(data.field);
					console.log(data.field);
					// console.log(index);
					$.ajax({
						type: 'post',
						dataType: 'json',
						url: '/editGoods',
						data: data.field,
						success: function(data) {
							if (data.err_code == 0) {
								layer.msg('修改成功');
								setTimeout(function() {
									window.parent.location.href = '../index.html';
								}, 1000);
							}
							if (data.err_code == 1) {
								layer.msg('修改失败');
							}
						}
					});
					return false;
				});
			});
		</script>
	</body>


</html>

根目录(注:upload 放图片的):

还没搞完的功能:

【1】按时间线搜索   

【2】搜索商家统计不完整 

【3】多选删除 图片命名 

【4】查看弹出详细内容

【5】用别人的api完成文字提取

【6】手机版页面

其他功能:

 外网访问我用的是DDNSTO-家庭网络监控  这个便宜访问用微信扫下就好,4m的速度就可以了!

电脑用家里旧的就好,如果有两台以上的,就用一个装个Pve 模拟上去,里面装多个系统设置自动启动 DDNSTO ,win11,win10,win7, mac os ,各种liux, Nas 就群晖,旁路由就 openWRT  这个旧电脑就活了,变成为自己服务 的个人服务器,远程也可用Todesk!!

远程硬件就用,米家的,开关,(mesh开关卡 实现)mesh网关(也可以用小米音箱来完成 语音控制电脑开关)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值