写了一个生成license模块,包括前端和后端,只有一个页面,就不想前后端分两个模块,后端用的koa,在koa基础上用了koa-views和koa-static做了前端,最终采用以下技术实现。
HTML/CSS Framework参考https://geekflare.com/best-css-frameworks/#anchor-materialize也先后尝试了一大堆,发现bootstrap已死,Skeleton过于简单了点,等等等,最后选了Materialize。
cd ~/Workspace
mkdir helloworld
cd helloworld
yarn init
yarn add koa
yarn add @koa/router
yarn add koa-views
yarn add koa-static
yarn add koa-body
yarn add pug
package.json
{
"name": "ls-license",
"version": "1.0.0",
"main": "./src/index.js",
"license": "MIT",
"type": "module",
"private": true,
"scripts": {
"dev-build": "nodemon build",
"build": "node build",
"dev": "nodemon run",
"run": "node run"
},
"dependencies": {
"@koa/router": "^10.1.1",
"chalk": "^5.0.0",
"config": "^3.3.6",
"fs-extra": "^10.0.0",
"koa": "^2.13.4",
"koa-body": "^4.2.0",
"koa-static": "^5.0.0",
"koa-views": "^8.0.0",
"loglevel": "^1.8.0",
"loglevel-plugin-prefix": "^0.8.4",
"moment": "^2.29.1",
"node-rsa": "^1.1.1",
"pug": "^3.0.2"
}
}
index.js
import Koa from 'koa';
import KoaBody from 'koa-body';
import serve from 'koa-static';
import views from 'koa-views';
import path from 'path';
import { fileURLToPath } from 'url';
import Routes from './routes/index.js';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const app = new Koa();
app
.use(serve(path.resolve(__dirname, './public'), {}))
.use(
KoaBody({
multipart: true,
formidable: {
keepExtensions: true,
maxFileSize: 10485760, //10 * 1024 * 1024,
},
})
)
.use(views(path.resolve(__dirname, './views'), { extension: 'pug' }))
.use(Routes.routes())
.use(Routes.allowedMethods())
.listen(8888);
routes/index.js
import KoaRouter from '@koa/router';
import { licenseController } from '../controllers/index.js';
const router = new KoaRouter();
router.get('/', async (ctx) => {
await ctx.render('index', {
options: {
smartools: 'Smartools',
kanzhun: 'Kanzhun!',
bluepool: 'Bluepoo',
},
});
});
router.post('/license', licenseController.issue);
export default router;
index.pug
html
head
title License Generator
link( href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet")
link(
type="text/css"
rel="stylesheet"
href="css/materialize.min.css"
)
meta(name="viewport" content="width=device-width, initial-scale=1.0")
body
div.container
h1 License Issuer
div.row
form.col.s12(action="./license" method="post")
div.row
div.col.s6
label System
select(name="system")
each val, i in options
option(value=i)= val
div.col.s6
label Years
input(type="text" name="years" value="1")
div.row
div.col.s12
label Locators
textarea.materialize-textarea(name="locator")
div.row
div.col.s12
button.btn(type="submit") Issue!
script(src="js/materialize.min.js")
script.
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems, {});
});