<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport"
content="width=device-width,user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1"/>
<meta content="black" name="apple-mobile-web-app-status-bar-style"/>
<meta name="format-detection" content="telephone=no"/>
<meta name="full-screen" content="yes"/>
<meta name="x5-fullscreen" content="true"/>
<meta name="browsermode" content="application"/>
<meta name="x5-page-mode" content="app"/>
<meta name="apple-mobile-web-app-capable" content="yes"/>
<meta name="theme-color" content="#000000"/>
<meta name="description" content="Web site created using create-react-app"/>
<title> 电子衰弱卡二维码 </title>
<style>
* {
padding: 0;
margin: 0;
font-size: 2.7rem;
color: #000;
font-weight: 400;
font-family: Helvetica;
}
html {font-size: 1.7vw;}
.no_select {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
-khtml-user-select: none;
-o-user-select: none;
user-select: none;
}
body:before {
width: 100%;
height: 100%;
content: " ";
position: fixed;
z-index: -1;
top: 0;
left: 0;
background: #F9F9F9;
}
.main {
height: 100vh;
overflow-y: auto;
overflow-x: hidden;
padding: 3rem;
box-sizing: border-box;
}
.name_container {padding: 0 1rem;}
.name {
font-weight: 600;
margin-bottom: 0.6rem;
height: 5rem;
display: flex;
align-items: center;
}
.name_container .info {
color: #646464;
margin: 0.7rem 0;
font-size: 2.4rem;
font-weight: 600;
}
.name_container .info span {
color: #646464;
font-size: 2.4rem;
font-weight: 600;
}
.red_tip {
font-weight: 800;
margin-left: -1rem;
color: #e73827;
font-size: 3.0rem;
}
.time_container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.time_container .time {
display: flex;
flex-direction: row;
}
.time_container_style {
color: #4272ee;
font-weight: 800;
font-size: 3.3rem;
}
.time_container .time div {transform: translateY(-0.2rem);
margin: 0 0.1rem;
}
</style>
</head>
<body>
<div class="main">
<div class="name_container no_select"></div>
<div class="time_container"></div>
</div>
</body>
<script type="text/javascript">
/**
* utils
* */
const randAChar = () => {const n = Math.random() * 10;
const s = String.fromCharCode(Math.floor(Math.random() * 26) + 'a'.charCodeAt(0));
if (n > 5) {return s;} else {return (s).toUpperCase();}
};
// 随机一个字符串
const randCode = (n = Math.random() * 5) => {
let s = '';
for (let i = 0; i < n; i++) {s += randAChar();
}
return (((s + Math.ceil(Math.random() * 100) + Math.ceil(Math.random() * 100)).replace(/0/g, 'h')).replace('9', 'f') + randAChar()).toUpperCase();};
</script>
<script type="text/javascript">
/**
* element
* */
class Element {constructor(container) {
this.container = container;
this.cache = [];
this.code = randCode();}
render(nodes = []) {this.cache = this.createElements(nodes);
}
createElements(nodes = [], parent = '', container = this.container, cache = this.cache) {switch (typeof nodes) {
case "number":
case "boolean":
case "undefined":
case 'string':
let v = typeof nodes === 'undefined' ? '' : `${nodes}`;
const element = {text: v, key: parent + this.code, elementType: 'string'}
const {newContainer} = this.renderElements(element, container, cache[0]);
return v ? [{...element, element: newContainer}] : [];
default:
return nodes.map((i, index) => {const key = parent + (i.key ? `${i.key}` : `${index}`);
switch (typeof i) {
case "number":
case "boolean":
case "undefined":
case 'string':
let v = typeof i === 'undefined' ? '' : `${i}`;
const se = {text: v, key, elementType: 'string'};
const res = this.renderElements(se, container, cache[index]);
return {...se, element: res.newContainer};
default:
if (!i.tag || i.hidden) {return;}
const te = {...i, key, elementType: 'tag'}
const {newContainer, newCache} = this.renderElements(te, container, cache[index]);
return {
...te,
element: newContainer,
children: i.children ? this.createElements(i.children, key + '_', newContainer, newCache) : []}
}
});
}
}
renderElements(element, container, cacheElement) {if (!container) {
return {
newContainer: undefined,
newCache: []};
}
if (this.compare(element, cacheElement)) {
return {
newContainer: cacheElement.element,
newCache: cacheElement.children || []};
} else {
// 创立元素
let e;
switch (element.elementType) {
case "string":
e = document.createTextNode(element.text);
e['key'] = element['key']
break;
case "tag":
if (element.tag) {e = document.createElement(element.tag);
delete element.children;
delete element.element;
Object.keys(element).forEach((key) => {e[key] = element[key];
});
}
}
if (e) {if (cacheElement && cacheElement.element) {container.replaceChild(e, cacheElement.element)
} else {container.appendChild(e);
}
}
return {newContainer: e, newCache: []}
}
}
// 比拟对象
compare(element, cacheElement) {if (cacheElement === undefined) {return false;}
if (element.elementType === 'string') {return element.text === cacheElement.text && element.key === cacheElement.key;}
if (element.elementType === 'tag' && element.key !== cacheElement.key) {return false;}
let bool = true;
try {(function _compare(element, cacheElement) {Object.keys(element).forEach((key) => {if (element['elementType'] === 'tag' && typeof element[key] !== "object" && element[key] !== cacheElement[key] && key !== 'children') {throw new Error('false');
}
if (typeof element[key] === "object" && key !== 'element' && key !== 'children') {_compare(element[key], cacheElement[key] || {});
}
});
}(element, cacheElement));
} catch (e) {bool = false;}
return bool;
}
}
</script>
<script type="text/javascript">
/**
* time
* */
class Time extends Element {constructor(containerClassName = 'time_container') {super();
// 工夫符号
this.units = Object.freeze(['-', '-', '\u00a0', ':', ':']);
// 工夫容器
this.container = document.getElementsByClassName(containerClassName)[0];
}
// 工夫格局转换
rdn(number) {if (`${number}`.length === 1) {return `${0}${number}`
} else {return number;}
}
// 获取工夫
getTimes() {const nowDate = new Date();
const nowYear = nowDate.getFullYear();
const nowMonth = nowDate.getMonth() + 1;
const nowDay = nowDate.getDate();
const nowHour = nowDate.getHours();
const nowMinutes = nowDate.getMinutes();
const nowSeconds = nowDate.getSeconds();
return [{value: nowYear, name: 'year'},
{value: this.rdn(nowMonth), name: 'month'},
{value: this.rdn(nowDay), name: 'day'},
{value: this.rdn(nowHour), name: 'hour'},
{value: this.rdn(nowMinutes), name: 'minutes'},
{value: this.rdn(nowSeconds), name: 'seconds'}
];
}
renderTimeElement() {const nodes = this.getTimes().map((i, index) => {
return {
tag: 'div',
className: 'time time_container_style',
children: [`${i.value}`,
{tag: this.units[index] ? 'div' : '',
children: this.units[index],
className: 'time_container_style'
}
]
}
});
this.render(nodes);
}
run() {this.renderTimeElement();
setInterval(this.renderTimeElement.bind(this), 1000);
return this;
}
}
</script>
<script type="text/javascript">
/**
* user
* */
class User extends Element {constructor(userInfo) {super();
this.userInfo = userInfo;
this.container = document.getElementsByClassName('name_container')[0];
this.id = userInfo.id.replace(/(\d{4})\d{10}(\d{4})/, '$1**********$2');
this.phone = userInfo.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}
run() {
this.render([{
tag: 'div',
className: 'name',
children: [
this.userInfo.name,
{
hidden: this.userInfo.isInoculation,
tag: 'span',
className: 'red_tip',
children: '(请尽快接种新冠疫苗)'
}
]
}, {
tag: 'div',
className: 'info',
children: [
'证件号码:',
{
tag: 'span',
children: this.id
}
]
}, {
tag: 'div',
className: 'info',
children: [
'电话号码:',
{
tag: 'span',
children: this.phone
}
]
}]);
return this;
}
}
</script>
<script type="text/javascript">
/**
* router
* */
</script>
<script type="text/javascript">
// 用户信息
const userInfo = {
id: '000000000000000000',
phone: '00000000000',
name: '张三',
isInoculation: true,
}
let time = null;
let user = null;
function run() {time = new Time();
time.run();
user = new User(userInfo);
user.run();}
window.onload = () => {run();
}
</script>
</html>