6. Kết cấu của đề tài
2.3. Mô hình cơ sở dữ liệu
2.3.1. Sơ đồ cơ sở dữ liệu
Hình 2.5 Mô hình cơ sở dữ liệu của hệ thống hỗ trợ tìm thợ.
2.3.2. Chức năng của từng bảng và thuộc tính
Bảng 2.1 Chức năng của từng bảng trong database.
STT Tên bảng Chức năng
1 useraccounts Đây là bản chính lưu trữ thông tin của người dùng. UserAccountID: Số thứ tự tài khoản đã đăng ký của người dùng được tăng tự động khi tạo.
Email: Có thể dụng để đăng nhập và không được tạo trùng.
Username: Tài khoản để đăng nhập.
Password: Mật khẩu đã được mã hóa bằng MD5. FullName: Họ và tên của người dùng.
IsMale: Là nam hoặc không phải nam.
PhoneNumber: Số điện thoại người dùng mặc định là 0.
ProvinceID: Mã của Tỉnh, Thành Phố đang sống. DistrictID: Mã Quận, Huyện, Thành Phố đang sống.
WardID: Mã Phường, Xã đang sống. StreetName: Tên đường và số nhà.
Longitude: Kinh độ của người dùng được lấy từ GPS.
Birthday: Ngày sinh.
Image: Ảnh đai diện của người dùng. PersonID: Mã chứng minh nhân dân.
CreateDate: Ngày tạo tài khoản được tạo tự động khi tạo tài khoản.
StatusOnline: Trạng thái của người dùng khi sử dụng trong hệ thống.
StatusAccount: Trạng thái tài khoản có ba trạng thái đó là: 1 là tài khoản đã được active, 0 tài khoản chưa được active và -1 tài khoản đã bị chặn, mặc định là 0.
CodeActive: Mã là số được tạo random để xác thực tài khoản khi đăng ký mới.
PointsAverage: Điểm trung bình đánh giá qua từng giao dịch.
UserTypeID: Loại tài khoản. 2 usertype Chức năng phân loại tài khoản.
UserTypeID: Số thứ tự của tài khoản gồm 1, 2, 3. NameUserType
3 jobcategories Bảng này chứa thông tin danh mục ngành nghề do Admin thêm vào.
CategoryID: Số thứ tự danh mục được tạo tự động. NameJobCategory: Tên danh mục.
ImageStore: Ảnh đại diện của danh mục. 4 userjobcategories Chứa thông tin hồ sơ của thợ.
CategoryID: Mã danh mục.
UserWorkerID: Mã thợ đã đăng hồ sơ. Exprience: Năm kinh nghiệm.
Qualifications: Bằng cấp và trình độ chuyên môn trong danh mục.
GeneralInformation: Thông tin chung. CreateDate: Ngày tạo hồ sơ.
ActiveDate: Ngày admin duyệt hồ sơ.
ActiveStatus: Trạng thái của hồ sơ gồm 3 trạng thái 1 là đã duyệt, 0 là đang đợi duyệt (mặc định), -1 hồ sơ đã bị xóa.
UserAdminActive: Mã admin đã duyệt hồ sơ. 5 chathistories Bảng chứa thông tin một giao dịch đã tạo.
HistoryID: Số thứ tự giao dịch được tăng tự động. UserGuestID: Mã tài khoản khách muốn giao dịch. UserWorkerID: Mã tài khoản thợ.
DateCreate: Ngày tạo giao dịch này.
PointsGuest: Điểm đánh giá của khách khi giao dịch hoàn tất.
PointsWorker: Điểm đánh giá của thợ với khách khi giao dịch hoàn tất.
StatusEnd: Trạng thái của giao dịch này có 3 trạng thái: 1 đã giao dịch thành công, 0 đang giao dịch, -1 giao dịch đã bị hủy.
3 chatdetails Nội dung chat của khách và thợ được lưu trữ trong bảng.
HistoryID: Mã giao dịch.
TimeComment: Thời gian gửi tin nhắn. UserID: Người đã gửi tin nhắn.
Chương 3 : XÂY DỰNG HỆ THỐNG HỖ TRỢ TÌM KIẾM NHÓM THỢ THEO KHU VỰC NỀN TẢNG WEBSITE
3.1. Server API của hệ thống hỗ trợ tìm kiếm nhóm thợ theo khu vực
3.1.1. Giới thiệu chung về Web Server API của hệ thống hỗ trợ tìm kiếm nhóm thợ thợ
3.1.1.1. Giới thiệu
Web API nhằm mục đích trả về JSON từ database khi client yêu. Nó giúp Web Front-end và Mobile kết nối được với nhau.
3.1.1.2. Phân quyền người dùng
Hệ thống gồm có 3 nhóm quyền chính là:
- Khách (Người thuê thợ): Sử dụng App để vào hệ thống tìm kiếm thợ theo danh mục ngành nghề và khu vực đã chọn.
- Thợ: Thợ có thể sử dụng App hoặc web để đăng tin, cập nhật thông tin cá nhân
- Admin: Quản lý danh mục, duyệt được hồ sơ của thợ đã đăng, xem được thống kê của hệ thống, ...
3.1.2. Cài đặt môi trường lập trình và một số module cần thiết 3.1.2.1. Môi trường Node.js và NPM 3.1.2.1. Môi trường Node.js và NPM
Vào trang chủ của Node.js (https://nodejs.org/en/download/) để tài môi trường Node.js và cài đặt trong bản cài đặt đã có chứa sẵn chương trình npm. phiên bản mới nhất của node.js hiện tại là 8.11.1 và npm là 5.6.0. [1]
Để kiểm tra phiên bản của node.js hoặc npm thì ta dùng câu lệnh bên dưới.
node -v npm -v
Hình 3.1 Màn hình console hiển thị thông tin phiên bản của Node.js và NPM.
3.1.2.2. Cài các Module cần thiết sử dụng phần mềm NPM Cách sử dụng NPM Cách sử dụng NPM
Tạo một thư mục trống và mở cửa sổ CMD trong thư mục đó và chạy lệnh command như sau:
Một số câu hỏi được đặt ra để nhập vào thông tin dự án bạn có thể skip tất cả bằng cách nhấn nút enter hoặc điền đầy đủ thông tin vào.
Hình 3.2 Màn hình console khi gõ lệnh npm init.
Sau đó npm sẽ tạo một file pakage.json để chứa thông tin dự án và các module đã cài. Nếu di chuyển đi nơi khác hoặc triển khai dự án lên server thật thì chỉ cần có file này và chạy lệnh npm install thì các module sẽ được cài vào thư mục node_modules.
Cài đặt Module cần thiết
Sử dụng câu lệnh bên dưới để cài đặt các module cần thiết cho phía Web API.
npm install express body-parser express-validator dotenv debug http-errors jsonwebtoken mathjs md5 moment morgan multer mysql nodemailer
Hình 3.3 Thư mục node_modules chứa module đã cài đặt trong câu lệnh npm install.
3.1.3. Kết nối và truy vấn dữ liệu giữa Node.js và MySql 3.1.3.1. Kết nối với database Mysql 3.1.3.1. Kết nối với database Mysql
Tạo file pool.js để kết nối tới database.
const mysql = require('mysql');
const connection = mysql.createPool({ connectionLimit: 10,
user: process.env.FW_USER, port: process.env.FW_PORT, password: process.env.FW_PASS, database: process.env.FW_DATABASE }); module.exports = {connection};
Tạo tập tin helper.js trong thư mục helpers với nội dung như sau.
const db=require('../databases/pool').connection; function sendQueryToDatabase(queryStatement,
arrayValue) {
return new Promise((resolve, reject) => {
return db.query( queryStatement,arrayValue,(err, results) => {
if (err) { return reject(err); } resolve(results);
}); }); };
module.exports = { sendQueryToDatabase };
Hàm này là một hàm bất đồng bộ, hàm nhận vào 2 tham số queryStatement là câu lệnh truy vấn và arrayValue là một mảng giá trị, chức năng của hàm này là trả về dữ liệu cần lấy trong câu lệnh vừa truy vấn.
3.1.3.2. Truy vấn dữ liệu
Để truy vấn dữ liệu ta sử dụng hàm bất đồng bộ sendQueryToDatabase đã giới thiệu ở trên để sử dụng, ở đây tác giả tạo một server node.js tại port 3000.
const http = require(‘http’);
const router = require(‘express’).router(); const helper = require('../helpers/helper'); //Khai báo phương thức get có tên “get-user” kèm theo là một callback function
router.get(‘/get-user’,async function(req,res){ try{
let userID = req.query.useraccountid;//bắt query string có tên là useraccountid rồi gán vào biến let result = await
helper.sendQueryToDatabase( “SELECT * FROM
//Hàm dưới chuyển đổi dữ liệu từ object thành json và trả về cho Client
return res.json({"result": result});
}catch(err){//bắt lỗi xảy ra khi có lỗi khi truy vấn dữ liệu
return res.status(400).json({“err”: err.message}); }});
http.createServer(router).listen(3000);//chạy server trên port 3000
Câu lệnh trên sẽ trả về tất cả thông tin của một tài khoản dưới dạng JSON.
Hình 3.4 Server trả về dữ liệu dưới dạng JSON của tài khoản 100000001.
3.1.4. Chức năng của một số router có trong API
Bảng 3.1 Tên và một số chức năng của API
Tên router Phương
thức Chức năng
/api/account/login Post Đăng nhập, server sẽ trả về các dữ liệu cần thiết như json web token, ... để lưu trữ trong cookie.
/api/account/signup-for-both Post Đăng ký một tài khoản thợ hoặc khách, server gửi một mail xác minh tài khoản về mail người dùng đã đăng ký.
/api/account/verify Put Xác minh một tài khoản.
/api/account/profile/:useraccountid Get Lấy thông tin cá nhân của một người dùng với user id tương ứng.
/api/account/profile Put Cập nhật thông tin cá
nhân.
/api/account/put-change-password Put Thay đổi mật khẩu.
/api/account/put-forgot-password Put Khi quên mật khẩu thì dùng router này điền email
vào sau đó server tạo một mật khẩu rồi gửi về email đó.
/api/account/put-status-online Put Cập nhật trạng thái online. /api/category/get-all Get Lấy danh sách tất cả danh
mục.
/api/category/get-by-userworkerid Get Lấy danh sách các danh mục chưa gửi hồ sơ đăng ký.
/api/category/create-category Post Tạo mới một danh mục. /api/category/update-category Put Cập nhật một danh mục có
sẵn. /api/category/get-all-cv-by-
categoryid?categoryid=
Get Chức năng là lấy tất cả hồ sơ có trong một danh mục.
/api/cv/post Post Tạo mới một hồ sơ.
/api/cv/active-cv Put Active một CV.
/api/cv/active-
cv?categoryid=&userworkerid=
Delete Xóa một CV.
/api/cv/not-activated Get Lấy danh sách tất cả các cv chưa active.
/api/cv/activated-by-
query?categoryid=&provinceid=&distri ctid=&wardid=
Get Lọc danh sách hồ sơ theo từng danh mục và địa điểm /api/cv/get-all-cv-by-userid Get Lấy tất cả danh sách hồ sơ
theo mã tài khoản. /api/cv/get-all-cv-by-
categoryid?categoryid=
Get Lấy danh sách các hồ sơ của một danh mục bất kì. /api/location/geolocation Put Cập nhật thông tin vị trí. /api/upload/image-avatar Post Lưu trữ ảnh đại diện vào
server.
/api/upload/image-store Post Lưu trữ ảnh đại diện của danh mục vào server. /api/chat/create-chat-history Post Tạo mới một giao dịch. /api/chat/get-list-people-chated Get Lấy danh sách người đã
nhắn tin. /api/chat/get-message-
chated?historyid=&limit=&page=
Get Lấy về các tin nhắn đã nhắn.
/api/chat/put-cancel-transaction Put Hủy một giao dịch.
/api/chat/put-done-transaction Put Hoàn thành một giao dịch kèm theo đánh giá.
/api/chat/get-info-transaction-done-by- userid?useraccountid=&limit=&page=
Get Lấy tất cả thông tin của giao dịch theo mã tài khoản.
/api/statistical/get-all-user- worker?limit=&page=
Get Lấy danh sách các tài khoản người thợ.
/api/statistical/get-all-user- guest?limit=&page=
Get Lấy danh sách người khách.
/api/statistical/get-all-transaction- done?limit=&page=
Get Lấy danh sách giao dịch. /api/statistical/put-block-account-by- userid Put Chặn một người dùng. /api/statistical/put-enable-account-by- userid Put Mở chặn một người dùng. /api/dashboard/get-count-cv-by- categoryid
Get Tính tổng hồ sơ theo từng danh mục.
/api/dashboard/get-count-user-type Get Tính tổng tài khoản phân theo từng loại.
/api/dashboard/get-count-transaction Get Tính tổng giao dịch phân theo trạng thái.
3.2. Xây dựng Server Websocket sử dụng thư viện socket.io để làm ứng dụng nhắn tin thời gian thực nhắn tin thời gian thực
3.2.1. Giới thiệu chung về Server Websocket
Tác giả tạo Server Websocket bằng cách sử dụng thư viện Socket.io và môi trường Node.js được tải về từ chương trình NPM. Chức năng của server này là tạo ứng dụng nhắn tin thời gian thực giữa thợ với khách tìm thợ giúp gửi và bắt dữ liệu thời gian thực.
3.2.2. Cài đặt một số module cần thiết
Tác giả cài đặt một số module cần thiết cho việc nhắn tin thời gian thực bằng dòng command.
npm install express request socket.io
3.2.3. Chức năng của từng sự kiện trong Socket.io
Socket.io có 2 phương thức chính là:
socket.on(string event, callback data) sẽ thực hiện sự kiện lắng nghe từ client gửi lên.
socket.emit(string event, object data) sẽ thực hiện việc phát ra một sự kiện về client kèm theo dữ liệu.
socket.on('authorization', function (result) { token = result.access_token;
UserAccountID = result.UserAccountID;
callApi.PUT(seed.ACCOUNT.PUT_STATUS_ONLINE,
objectValue, token);//Gọi api cập nhật trạng thái online vào database.
});
Đoạn code trên với chức năng là lắng nghe sự kiện với tên authorization nhằm cập nhật giá trị một số loại biến và gọi API cập nhật trạng thái.
socket.on('array_room', function (result) {
result.map(function (value) {//Lặp qua một mảng và tạo một mảng mới.
socket.join(value + "");//tham gia vào room với tên được lưu trong biến value.
ArrayRoom.push(value + "");//Thêm giá trị vào mảng ArrayRoom.
socket.broadcast.to(value +
"").emit('is_online', UserAccountID);//Gửi trạng thái online tới từng phòng.
}); });
Đoạn code trên lắng nghe client gửi dữ liệu mã phòng lấy được nhờ vào cách gọi API lên và tiến hành tham gia vào từng room trong socket.io và gửi trạng thái online đến từng room đó.
socket.on('disconnect', function () { objectValue.StatusOnline = 0;
callApi.PUT( seed.ACCOUNT.PUT_STATUS_ONLINE, objectValue, token);//Gọi API để cập nhật trạng thái trên database
ArrayRoom.map(function (value){ //Gửi sự kiện offline tới từng room socket.broadcast.to(value +
"").emit( 'is_offline', UserAccountID); });
});
Khi Client tắt tab thì sự kiện này sẽ kích hoạt và sẽ thực thi gọi API để cập nhật trạng thái offline trên Database và một vòng lặp theo mảng nhằm mục đích gửi sự kiện offline vào các phòng Client này đã đặng nhập.
socket.on('send_message', function (result) { socket.broadcast.to(result.HistoryID +
"").emit('get_message', result);//Gửi tin nhắn vừa chat vào phòng cần gửi.
callApi.POST(seed.CHAT.NEW_MESSAGE, result, token);//Gọi API thêm mới một dòng chat vào database.
});
Ví dụ ở đây Client A, Client B đều online và đều đã vào chung một room chat, Client A gửi lên server một đoạn chat với thông tin là tới Client B và server sẽ gửi đoạn chat đó vào room chat mà 2 người đã tham gia vào Client B sẽ nhận được tin nhắn và hiển thị nó.
3.3. Giao diện Front-end sử dụng thư viện Angular.js 3.3.1. Giới thiệu 3.3.1. Giới thiệu
Ở đây tác giả sử dụng chủ đề đã được thiết kế sẵn có tên INSPINIA - Responsive Admin Theme. Sử dụng Angular.js để render ra HTML dùng dữ liệu JSON nhận từ server.
3.3.2. Giao diện Front-end của thợ 3.3.2.1. Đăng ký 3.3.2.1. Đăng ký
Hình 3.5 Giao diện đăng ký. Hình 3.6 Giao diện đăng ký khi bị lỗi.
3.3.2.2. Đăng nhập
Hình 3.7 Giao diện đăng nhập. Hình 3.8 Giao diện đăng nhập khi bị lỗi sai tài khoản hoặc mật khẩu.
Tại màn hình đăng nhập nếu lỡ quên mật khẩu thì có thể ấn vào dòng quên mật khẩu sau đó trang web sẽ hiển thị một popup người dùng có thể nhập email tài khoản đó vào để khôi phục tài khoản.
Sau khi đăng nhập thành công website sẽ tự động lấy vị trí hiện tại gửi lên server.
3.3.2.3. Trang cá nhân
Trong trang cá nhân, cột đầu tiên có tên là Chi tiết cá nhân nó chứa các thông tin của tài khoản, trạng thái online của tài khoản và nếu bạn là khách thì có thể chọn thợ thích hợp để nhắn tin trực tiếp với người đấy.
Với cột đầu tiên người dùng có thể xem các giao dịch đã được đánh giá bằng
cách click vào dòng để hiển thị popup thông tin
các giao dịch.
Hình 3.10 Giao diện Popup hiển thị lịch sử đã giao dịch
Cột thứ hai có tên là Danh sách hồ sơ chứa các thông tin các hồ sơ đã nộp và đã được kích hoạt bởi admin.
Click vào nếu muốn sửa thông tin cá nhân,
sau khi ấn nút sửa thông tin thì sẽ tự động chuyển tới trang để cập nhật thông tin cá nhân như hình dưới.
Hình 3.11 Giao diện cập nhật thông tin cá nhân.
Khi cập nhật thành công sẽ hiện một thông báo thành công và ngược lại nếu có lỗi trong quá trình cập nhật thì website sẽ hiển thị lỗi.
3.3.2.4. Hồ sơ Đăng hồ sơ Đăng hồ sơ
Hình 3.12 Giao diện đăng hồ sơ.
Ở dòng danh mục ngành nghề đó là một drop-down nhằm hiển thị danh sách các danh mục ngành nghề mà người thợ này chưa đăng ký.
Khi người dùng nhập tất cả các thông tin cần thiết và bắt đầu ấn đăng hồ sơ nếu gửi thành công sẽ hiển thị thông báo và ngược lại nếu có lỗi cũng sẽ hiển thị tên lỗi.
Danh sách hồ sơ đang đợi duyệt
Đây là giao diện danh sách hồ sơ đợi duyệt đây có thể tìm kiếm theo tên danh mục hoặc sắp xếp theo năm kinh nghiệm và ngày nạp hồ sơ.
Nếu muốn chỉnh sửa hồ sơ đang trong quá trình đợi thì có thể chọn vào nút để mở popup cập nhật thông tin hồ sơ.
Hình 3.14 Giao diện chỉnh sửa hồ sơ.
Hoặc có thể xóa hồ sơ nào đó bằng cách ấn vào nút sau đó website hiện lên popup xác nhận một lần nữa.
Danh sách hồ sơ đã duyệt
Hình 3.15 Giao diện danh sách các hồ sơ đã được admin duyệt.
Hình 3.16 Giao diện chat thời gian thực giữa thợ và khách.
Ở đây nếu màu nền của danh sách như Nguyễn Thành Đạt thì người đó chưa