NodeJs actual combat - to-do list (6) - front-end drawing table to display details of to-do items

In the list shown in the previous sections, the creation time and completion time of the item are not visible, and the data display is relatively small. This section adds tables to display these structured data
insert image description here

Define the json data returned by the server

  1. Example of a row of data
 		{
    
    
            "itemName": "1111",
            "createTime": "2022-11-19 22:06:15",
            "completeTime": "2022-11-19 22:06:29",
            "todoStatus": "已完成"
        }
  1. Put multiple rows of data into a list
[
    {
    
    
        "itemName": "1111",
        "createTime": "2022-11-19 22:06:15",
        "completeTime": "2022-11-19 22:06:29",
        "todoStatus": "已完成"
    },
    {
    
    
        "itemName": "en1111",
        "createTime": "2022-11-19 22:06:20",
        "completeTime": "2022-11-19 22:06:33",
        "todoStatus": "已完成"
    }
]
  1. full json example
{
    
    
    "code": 1,
    "data": [
        {
    
    
            "itemName": "1111",
            "createTime": "2022-11-19 22:06:15",
            "completeTime": "2022-11-19 22:06:29",
            "todoStatus": "已完成"
        },
        {
    
    
            "itemName": "en1111",
            "createTime": "2022-11-19 22:06:20",
            "completeTime": "2022-11-19 22:06:33",
            "todoStatus": "已完成"
        }
    ],
    "msg": "查询成功"
}

Front-end drawing dynamic form

  1. Front-end add form
<table id="todo_table" cellpadding="0" cellspacing="0" border="1">
        <tr id ="todo_header">
            <th>待办事项</th>
            <th>创建时间</th>
            <th>完成时间</th>
            <th>是否已完成</th>
            <th>操作</th>
        </tr>  
</table>
  1. JQuery draws dynamic tables
      function initUlData(result) {
    
    
            if (result.code == '0') {
    
    
                alert(result.msg);
            } else {
    
    
                if (result.data == null) {
    
    
                    alert('服务器返回数据为空');
                    return ;
                }
                var todoHeader = $('#todo_header');
                $('#todo_table').empty();
                $('#todo_table').append(todoHeader);
                result.data.forEach(item => {
    
    
                    // $('#todo_ul').append( $('<li></li>').html(a));
                    var tr = $('<tr></tr>');
                    tr.append($('<td></td>').html(item.itemName));
                    tr.append($('<td></td>').html(item.createTime));
                    tr.append($('<td></td>').html(item.completeTime));
                    tr.append($('<td></td>').html(item.todoStatus));
                    var delButton = $('<input type="button" value="完成" />');
                    if (item.todoStatus = '已完成') {
    
    
                        delButton[0].disabled = true;
                    } else {
    
    
                        delButton.on('click', function(){
    
    
                            var tdNodes = this.parentNode.childNodes;
                            if (tdNodes.length > 1) {
    
    
                                complete(tdNodes[0].textContent);
                            }
                        });
                    }
                    tr.append(delButton);
                    $('#todo_table').append(tr);
                });
                focusItemText();
            }
        }

2.1 Create table rows

 var tr = $('<tr></tr>');

2.2 Create a cell, fill the cell html data, add it to the row, and put the last cell into the button

tr.append($('<td></td>').html(item.itemName));
tr.append($('<td></td>').html(item.createTime));
tr.append($('<td></td>').html(item.completeTime));
tr.append($('<td></td>').html(item.todoStatus));
var delButton = $('<input type="button" value="完成" />');
tr.append(delButton);

2.3 If the to-do item is completed, the button setting is disabled

if (item.todoStatus = '已完成') {
    
    
   delButton[0].disabled = true;
}

2.4 Add row data to the table

$('#todo_table').append(tr);
  1. full index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>待办列表</title>
    <script type="text/javascript" src="https://code.jquery.com/jquery-3.6.1.min.js"></script>
    <script type="text/javascript">
        $(function() {
            init();
            $("#add").on('click', function(){
                add();
            });
            $("#complete").on('click', function(){
                complete();
            });
        });

        
        function init() {
            $.ajax({
                url: "/query",
                method: 'GET',
                success: function(result) {
                    initUlData(result);
                }
            });
        }

        function add() {
            var item = $("#item_text").val().trim();
            if (item.length == 0) {
                alert('输入数据不能为空');
            }
            $.ajax({
                url: "/add",
                method: 'GET',
                data: {
                    item: item
                },
                success: function(result) {
                    initUlData(result);
                }
            });
        }

        function complete(item) {
            $.ajax({
                url: "/complete",
                method: 'GET',
                data: {
                    item: item
                },
                success: function(result) {
                    initUlData(result);
                }
            });
        }

        function initUlData(result) {
            if (result.code == '0') {
                alert(result.msg);
            } else {
                if (result.data == null) {
                    alert('服务器返回数据为空');
                    return ;
                }
                var todoHeader = $('#todo_header');
                $('#todo_table').empty();
                $('#todo_table').append(todoHeader);
                result.data.forEach(item => {
                    // $('#todo_ul').append( $('<li></li>').html(a));
                    var tr = $('<tr></tr>');
                    tr.append($('<td></td>').html(item.itemName));
                    tr.append($('<td></td>').html(item.createTime));
                    tr.append($('<td></td>').html(item.completeTime));
                    tr.append($('<td></td>').html(item.todoStatus));
                    var delButton = $('<input type="button" value="完成" />');
                    if (item.todoStatus == '已完成') {
                        delButton[0].disabled = true;
                    } else {
                        delButton[0].disabled = false;
                        delButton.on('click', function(){
                            var tdNodes = this.parentNode.childNodes;
                            if (tdNodes.length > 1) {
                                complete(tdNodes[0].textContent);
                            }
                        });
                    }
                    tr.append(delButton);
                    $('#todo_table').append(tr);
                });
                focusItemText();
            }
        }

        function focusItemText() {
            $('#item_text').val('');
            $('#item_text').focus();
        }
    </script>
</head>
<body>
    <h1>待办列表</h1>
    <form method="post" >
        <p><input id="item_text" type="text" name="item" /><input id="add" type="button" value="添加" /></p>
        <!-- <p><input id="complete" type="button" value="完成" /></p> -->
    </form>
    <!-- <ul id="todo_ul"></ul> -->
    <table id="todo_table" cellpadding="0" cellspacing="0" border="1">
        <tr id ="todo_header">
            <th>待办事项</th>
            <th>创建时间</th>
            <th>完成时间</th>
            <th>是否已完成</th>
            <th>操作</th>
        </tr>
        
    </table>
</body>
</html>

The backend returns list data

The data returned by the backend is encapsulated in the doQuery interface, only this method needs to be modified

function doQuery(response) {
    
    
	db.query('select item_name,create_time,complete_time,' + 
	'case todo_status when 0 then \'未完成\' when 1 then \'已完成\' end as todo_status from t_todo_list', (err, result) => {
    
    
		if (err) {
    
    
			console.log(err);
			var data = buildData(CODE_ERROR, [], '查询数据库失败');
			sendMsg(response, JSON.stringify(data));
			return;
		}
		var itemList = [];
		for (var i in result) {
    
    
			let item = {
    
    
				'itemName':'',
				'createTime':'',
				'completeTime':'',
				'todoStatus':''
			}
			item.itemName = result[i].item_name;
			item.createTime = formatDate(result[i].create_time);
			item.completeTime = formatDate(result[i].complete_time);
			item.todoStatus = result[i].todo_status;
			itemList.push(item);
		}
		var data = buildData(CODE_SUCCESS, itemList, '查询成功');
		sendMsg(response, JSON.stringify(data));
	});
}
  1. The data that needs to be displayed in the list includes creation time, completion time, item status, modify query SQL
select item_name,create_time,complete_time, case todo_status when 0 then '未完成' when 1 then '已完成' end as todo_status from t_todo_list
  1. The model of a row of data is as follows
			let item = {
    
    
				'itemName':'',
				'createTime':'',
				'completeTime':'',
				'todoStatus':''
			}
  1. Data needs to be formatted
function formatDate(date) {
    
    
	if (date == null) {
    
    
		return "";
	}
	return silly.format(date, 'YYYY-MM-DD HH:mm:ss');
}

The first line in the debug window shows the date before it was formatted
insert image description here

complete server.js

const http = require('http');
const fs = require('fs');
const parse = require('url').parse;
const mysql = require('mysql');
const silly = require('silly-datetime');
const db = mysql.createPool({
    
    
    host: "127.0.0.1",
    port: 3306,
    user: 'root',
    password: 'shootercheng',
    database: "test"
});

const hostname = '127.0.0.1';
const port = 3000;

const CODE_ERROR = 0;
const CODE_SUCCESS = 1;

function send404(response) {
    
    
    response.writeHead(404, {
    
    'Content-Type': 'text/plain'});
    response.write('Error 404: resource not found.');
    response.end();
}

function sendMsg(response, msg) {
    
    
	response.writeHead(200, {
    
    'Content-Type': 'application/json;charset=UTF-8'});
    response.write(msg);
    response.end();
}

function readFile(response, filePath) {
    
    
	fs.readFile(filePath, (err, data) => {
    
    
		if (err) {
    
    
			return send404(response);
		}
		var html = data.toString();
		// html = html.replace('%', Array.from(todoSet).join('</li><li>'));
		response.writeHead(200, {
    
    'Content-Type': 'text/html'});
		response.end(html);
	});
}

function findItemData(urlParse) {
    
    
	if (urlParse.query.length > 0) {
    
    
		var queryArray = urlParse.query.split('=');
		if (queryArray.length >= 2) {
    
    
			return decodeURI(queryArray[1]);
		}
	}
	return '';
}

function buildData(code, data, msg) {
    
    
	// 返回数据
	let retData = {
    
    
		'code':'',
		'data': [],
		'msg':''
	}
	retData.code = code;
	retData.data = data;
	retData.msg = msg;
	return retData;
}

/**
 * 获取当前时间
 * @returns
 */
function currentTime() {
    
    
    return silly.format(new Date(), 'YYYY-MM-DD HH:mm:ss');
}

/**
 * 格式日期
 * @param {*} date 
 * @returns 
 */
function formatDate(date) {
    
    
	if (date == null) {
    
    
		return "";
	}
	return silly.format(date, 'YYYY-MM-DD HH:mm:ss');
}

/**
 * 查询待办数据,并且输出到response
 * @param {*} response 
 */
function doQuery(response) {
    
    
	db.query('select item_name,create_time,complete_time,' + 
	'case todo_status when 0 then \'未完成\' when 1 then \'已完成\' end as todo_status from t_todo_list', (err, result) => {
    
    
		if (err) {
    
    
			console.log(err);
			var data = buildData(CODE_ERROR, [], '查询数据库失败');
			sendMsg(response, JSON.stringify(data));
			return;
		}
		var itemList = [];
		for (var i in result) {
    
    
			let item = {
    
    
				'itemName':'',
				'createTime':'',
				'completeTime':'',
				'todoStatus':''
			}
			item.itemName = result[i].item_name;
			item.createTime = formatDate(result[i].create_time);
			item.completeTime = formatDate(result[i].complete_time);
			item.todoStatus = result[i].todo_status;
			itemList.push(item);
		}
		var data = buildData(CODE_SUCCESS, itemList, '查询成功');
		sendMsg(response, JSON.stringify(data));
	});
}

/**
 * 添加待办事项
 * @param {*} response 
 * @param {*} itemData 
 */
function doAdd(response, itemData) {
    
    
	db.query('select count(*) as num from t_todo_list where item_name = ? and todo_status = ?', [itemData,'0'], (err, result) => {
    
    
        if (err) {
    
    
            console.log(err);
			var data = buildData(CODE_ERROR, [], '查询数据库失败');
			sendMsg(response, JSON.stringify(data));
			return;
        }
        if (result[0].num > 0) {
    
    
			var data = buildData(CODE_ERROR, [], itemData + '-待办事项已存在');
			sendMsg(response, JSON.stringify(data));
			return;
		}
		db.query('insert into t_todo_list(item_name, create_time, todo_status) values(?, ?, ?)', [itemData, currentTime(), '0'], (err, result) => {
    
    
			if (err) {
    
    
				console.log(err);
				var data = buildData(CODE_ERROR, [], itemData + '-待办事项添加到数据库失败');
				sendMsg(response, JSON.stringify(data));
				return;
			}
			doQuery(response);
		});
	});
}

/**
 * 完成待办事项
 * @param {*} response 
 * @param {*} itemData 
 */
function doCompelete(response, itemData) {
    
    
	db.query('select count(*) as num from t_todo_list where item_name = ? and todo_status = ?', [itemData, '0'], (err, result) => {
    
    
        if (err) {
    
    
            console.log(err);
			var data = buildData(CODE_ERROR, [], '查询数据库失败');
			sendMsg(response, JSON.stringify(data));
			return;
        }
        if (result[0].num == 0) {
    
    
			var data = buildData(CODE_ERROR, [], itemData + '-待办事项不存在');
			sendMsg(response, JSON.stringify(data));
			return;
		}
		db.query('update t_todo_list set complete_time = ?, todo_status = ? where item_name = ?', [currentTime(), '1', itemData], (err, result) => {
    
    
			if (err) {
    
    
				console.log(err);
				var data = buildData(CODE_ERROR, [], itemData + '-更新待办事项失败');
				sendMsg(response, JSON.stringify(data));
				return;
			}
			doQuery(response);
		});
	});
}

const server = http.createServer((request, response) => {
    
    
	var urlParse = parse(request.url);
	var urlPath = urlParse.pathname;
	var itemData;
	if (urlPath == '/add' || urlPath == '/complete') {
    
    
		itemData = findItemData(urlParse);
		if (itemData.length == 0) {
    
    
			var data = buildData(CODE_ERROR, [], '输入数据有误');
			return sendMsg(response, JSON.stringify(data));
		}
	}
	switch (urlPath) {
    
    
		case '/':
			var filePath = 'public/index.html';
    		var absPath = './' + filePath;
			readFile(response, absPath);
			break;
		case '/query':
			doQuery(response);
			break;
		case '/add':
			doAdd(response, itemData);
			break;
		case '/complete':
			doCompelete(response, itemData);
			break;
	}
});

server.listen(port, hostname, () => {
    
    
	console.log(`Server running at http://${
      
      hostname}:${
      
      port}/`)
})

verify

execute add

  1. 1111
  2. en1111
  3. In Chinese 1111
    insert image description here
    , you can see that the data button on the page has been completed is disabled, and the unfinished ones can be clicked to complete

Check if the data in the database is consistent with the page

insert image description here

Use the browser to debug the form drawing process

Open the browser developer tools, click source, click the number of lines of code plus breakpoints
insert image description here
Refresh the page, press F10 to see the table drawn line by line
insert image description here
insert image description here

project address

Gitee code repository: https://gitee.com/3281328128/todo_list/tree/mysql/

Guess you like

Origin blog.csdn.net/modelmd/article/details/127951913