类别: 代码

Docker deploy static site

Posted on 2023-12-28 09:35:16
Comments: 0
FROM alpine:edge

WORKDIR /app

RUN apk add --no-cache
yarn
nginx

# 复制项目代码到容器中
COPY . /app

# 配置Yarn注册表并安装依赖项
RUN yarn config set registry "https://registry.npm.taobao.org" &&
yarn install &&
yarn cache clean

# 设置环境变量
ENV NODE_ENV=production

# 压缩生成的静态资源
RUN yarn build

# 复制Nginx配置文件
COPY nginx.conf /etc/nginx/nginx.conf

# 暴露容器内Nginx服务的端口
EXPOSE 8000

# 容器启动命令,启动Nginx并以守护进程方式运行
CMD ["nginx", "-g", "daemon off;"]


(爬虫抓取)最新省市区数据

Posted on 2022-07-20 09:17:38
Comments: 0
1. 背景

需要省市区数据, 搜索了一些 发现都是没有更新过的旧数据。


2. 思路

从民政部官网找了找数据, 有最新的,但是接口很复杂,也有过一些处理, 那么用爬虫抓一下来用..

3. 代码

city.agent.js

const superagent = require("superagent");
const cheerio = require("cheerio");
require("superagent-charset")(superagent);
const encode = require("./gbk.1");

function getCityData(city) {
return new Promise((resolve, reject) => {
superagent
.get(
`http://xzqh.mca.gov.cn/defaultQuery?shengji=${encode(
city
)}&diji=-1&xianji=-1`
)
.charset("gbk")
.set("accept", "html")
.end((err, res) => {
if (err) {
reject(err);
}
if (typeof res.text === "string") {
const $ = cheerio.load(res.text);
const info = $(".info_table tbody tr .name_left");
const arr = [];
let k = -1;
for (let i = 0; i < info.length; i++) {
const ssqid = info[`${i}`].parent.children[9].children[0]?.data;
if (!ssqid) {
continue;
}
if (!info[`${i}`].children[1].attribs) {
k++;
const city = info[`${i}`].children[0].attribs;
arr[k] = {
ssqid,
ssqname: city.value,
cities: [],
};
} else {
const area = info[`${i}`].children[1].attribs;
arr[k].cities.push({
ssqid,
ssqname: area.alt,
});
}
}
resolve(arr);
}
});
});
}
module.exports = getCityData;


gbk.1.js    // gbk解码   感谢   https://github.com/cnwhy/GBK.js

const GBK = require("./gbk.min.js");        // gbk 文件链接
function encode(str) {
return GBK.URI.encodeURI(str);
}

module.exports = encode;


city.js

const fs = require("fs");
const getCityData = require("./city.agent");
const provinceArr = [
"北京市(京)",
"天津市(津)",
"河北省(冀)",
"山西省(晋)",
"内蒙古自治区(内蒙古)",
"辽宁省(辽)",
"吉林省(吉)",
"黑龙江省(黑)",
"上海市(沪)",
"江苏省(苏)",
"浙江省(浙)",
"安徽省(皖)",
"福建省(闽)",
"江西省(赣)",
"山东省(鲁)",
"河南省(豫)",
"湖北省(鄂)",
"湖南省(湘)",
"广东省(粤)",
"广西壮族自治区(桂)",
"海南省(琼)",
"重庆市(渝)",
"四川省(川、蜀)",
"贵州省(黔、贵)",
"云南省(滇、云)",
"西藏自治区(藏)",
"陕西省(陕、秦)",
"甘肃省(甘、陇)",
"青海省(青)",
"宁夏回族自治区(宁)",
"新疆维吾尔自治区(新)",
"香港特别行政区(港)",
"澳门特别行政区(澳)",
"台湾省(台)",
];
async function InsertData() {
const data = [];
for (let i = 0; i < provinceArr.length; i++) {
const pro = provinceArr[i];
const current = {};
current.ssqname = pro.slice(0, pro.indexOf("("));
const city = await getCityData(pro);
current.city = city;
current.ssqid = String(Number(city[0]?.ssqid || 0) - 100);
data.push(current);
}
return data;
}
(async () => {
const s = await InsertData();
fs.writeFile("./city.agent.json", JSON.stringify(s), err => {
if(err) {
return console.log("err: ", err)
}
console.log("write success!")
})
})();


4. 说明

1. 民政局公开数据, 脚本只是为了获取最新省市区数据。

2. ssqid 直辖市 特区 还要手动改一下

3. 其它数据根据需要 可以自己添加一下

chainList transform to renderTree(Array)

Posted on 2022-05-16 22:42:01
Comments: 0

1. renderTree to chain

const renderTree = [
{
name: "A",
parent: "step1",
child: "Aa",
siblings: "B",
children: [
{
name: "Aa",
parent: "A",
child: "Aa1",
siblings: "Ab",
children: [
{ name: "Aa1", parent: "Aa", child: null, siblings: "Ab1" },
{
name: "Ab1",
parent: "Aa",
child: "Ab1-1",
siblings: "Ac1",
children: [
{
name: "Ab1-1",
parent: "Ab1",
child: null,
siblings: "Ab1-2",
},
{
name: "Ab1-2",
parent: "Ab1",
child: "Ab1-2-1",
siblings: "Ab1-3",
children: [
{
name: "Ab1-2-1",
parent: "Ab1-2",
child: null,
siblings: null,
},
],
},
{ name: "Ab1-3", parent: "Ab1", child: null, siblings: null },
],
},
{
name: "Ac1",
parent: "Aa",
child: "Ac1-1",
siblings: null,
children: [
{
name: "Ac1-1",
parent: "Ac1",
child: null,
siblings: "Ac1-2",
},
{
name: "Ac1-2",
parent: "Ac1",
child: "Ac1-2-1",
siblings: null,
children: [
{
name: "Ac1-2-1",
parent: "Ac1-2",
child: null,
siblings: null,
},
],
},
],
},
],
},
{ name: "Ab", parent: "A", child: null, siblings: "Ac" },
{ name: "Ac", parent: "A", child: null, siblings: "Ad" },
{
name: "Ad",
parent: "A",
child: "Ad1",
siblings: null,
children: [
{ name: "Ad1", parent: "Ad", child: null, siblings: "Ad2" },
{ name: "Ad2", parent: "Ad", child: null, siblings: null },
],
},
],
},
{
name: "B",
parent: "step1",
child: "B1",
siblings: "C",
children: [{ name: "B1", parent: "B", child: null, siblings: null }],
},
{ name: "C", parent: "step1", child: null, siblings: null },
];

// 简写
function deepClone(obj) {
return JSON.parse(JSON.stringify(obj));
}

const obj = {};
function arrayToChain(arr) {
for (let i = 0; i < arr.length; i++) {
const elm = deepClone(arr[i]);
delete elm.children;
obj[elm.name] = elm;
if (elm.children && elm.children.length > 0) {
arrayToChain(elm.children);
}
}
}
arrayToChain(renderTree);
console.log("obj:: ", obj);



2. chain to renderTree

const chainedList = {
A: {
name: "A",
parent: "step1",
child: "Aa",
siblings: "B",
},
B: {
name: "B",
parent: "step1",
child: "B1",
siblings: "C",
},
C: {
name: "C",
parent: "step1",
child: null,
siblings: null,
},
B1: {
name: "B1",
parent: "B",
child: null,
siblings: null,
},
Aa: {
name: "Aa",
parent: "A",
child: "Aa1",
siblings: "Ab",
},
Aa1: {
name: "Aa1",
parent: "Aa",
child: null,
siblings: "Ab1",
},
Ab1: {
name: "Ab1",
parent: "Aa",
child: "Ab1-1",
siblings: "Ac1",
},
"Ab1-1": {
name: "Ab1-1",
parent: "Ab1",
child: null,
siblings: "Ab1-2",
},
"Ab1-2": {
name: "Ab1-2",
parent: "Ab1",
child: "Ab1-2-1",
siblings: "Ab1-3",
},
"Ab1-3": {
name: "Ab1-3",
parent: "Ab1",
child: null,
siblings: null,
},
"Ab1-2-1": {
name: "Ab1-2-1",
parent: "Ab1-2",
child: null,
siblings: null,
},
Ac1: {
name: "Ac1",
parent: "Aa",
child: "Ac1-1",
siblings: null,
},
Ab: {
name: "Ab",
parent: "A",
child: null,
siblings: "Ac",
},
Ac: {
name: "Ac",
parent: "A",
child: null,
siblings: "Ad",
},
Ad: {
name: "Ad",
parent: "A",
child: "Ad1",
siblings: null,
},
Ad1: {
name: "Ad1",
parent: "Ad",
child: null,
siblings: "Ad2",
},
Ad2: {
name: "Ad2",
parent: "Ad",
child: null,
siblings: null,
},
"Ac1-1": {
name: "Ac1-1",
parent: "Ac1",
child: null,
siblings: "Ac1-2",
},
"Ac1-2": {
name: "Ac1-2",
parent: "Ac1",
child: "Ac1-2-1",
siblings: null,
},
"Ac1-2-1": {
name: "Ac1-2-1",
parent: "Ac1-2",
child: null,
siblings: null,
},
};
var chainedListArray = [];
for (const key in chainedList) {
chainedListArray.push(chainedList[key]);
}
const treeList = [];
let parent = null;
let siblingsKey = "";

const uncleKeys = {};

function chainToArrayTree(currentKey) {
if (currentKey) {
const current = chainedList[currentKey];
if (uncleKeys[currentKey]) uncleKeys[currentKey] = false;
console.log("parent:: ", parent);
if (!parent) {
treeList.push(current);
} else {
parent.children = Array.isArray(parent.children)
? [...parent.children, current]
: [current];
}
// have child
if (current.child) {
parent = current;
currentKey = current.child;
siblingsKey = chainedList[currentKey].siblings;
if (current.siblings) {
uncleKeys[current.siblings] = true;
}
chainToArrayTree(currentKey);
}
// no child but have siblings
else if (!current.child && current.siblings) {
parent = chainedList[current.parent];
currentKey = siblingsKey;
siblingsKey = chainedList[currentKey]?.siblings;
chainToArrayTree(currentKey);
}

// no child and bo siblings
else if (!current.child && !current.siblings) {
// if parent have siblings
if (chainedList[current.parent]?.siblings) {
currentKey = chainedList[current.parent].siblings;
parent = chainedList[chainedList[currentKey].parent];
siblingsKey = chainedList[currentKey].siblings;
chainToArrayTree(currentKey);
} else {
// if parent no siblings, current tree end, recycle to startKey"s siblings
console.log("currentLL::", current);
currentKey = findAncestorSiblings(current);
if (currentKey) {
parent = chainedList[chainedList[currentKey].parent];
siblingsKey = chainedList[currentKey].siblings || null;
chainToArrayTree(currentKey);
}
}
}
}
}

function findAncestorSiblings(current) {
const key = current?.parent || null;
if (key) {
const siblings = chainedList[key]?.siblings || null;
if (siblings && uncleKeys[siblings]) {
return siblings;
} else {
return findAncestorSiblings(chainedList[key]);
}
}
}

chainToArrayTree("A");
console.log("treeList: ", treeList);


BL React Coding

Posted on 2022-03-25 12:10:12
Comments: 0

App.tsx

import { useState, useEffect } from "react";
import axios from "axios";

interface IUserInfo {
id: number;
name: string;
username: string;
email: string;
phone: string;
website: string;
}

export default function IndexPage() {
const url = "/bl-api/users/1";
const [userData, setUserData] = useState({} as IUserInfo);
useEffect(() => {
axios
.get(url)
.then((data: IUserInfo | unknown) => {
if (data) {
setUserData(data);
}
})
.catch((e) => {
const data = {
id: 1,
name: "Ray Yin",
username: "rayyin",
email: "ray@bridgelegal.biz",
phone: "8727040355",
website: "bridgelegal.com",
};
setUserData(data);
});
}, []);
return (
// No need to touch code below
<div className="App">
<h2>User Data</h2>
<p>
<strong>Name: </strong>{" "}
{userData?.name || "(Need to populate name here)"}
</p>
<p>
{" "}
<strong>Website: </strong>
{userData?.website || "(Need to populate website here)"}
</p>
<p>
{" "}
<strong>Email: </strong>
{userData?.email || "(Need to populate email here)"}
</p>
<p>
{" "}
<strong>Phone: </strong>
{userData?.phone || "(Need to populate phone here)"}
</p>
</div>
);
}



count.tsx


import React from "react";
const { Component } = React;

interface IData {
id: number;
value: number;
}

// BL-Counter
class BLCounter extends Component {
constructor(props, context) {
super(props, context);
}
render() {
const { id, value, onIncrement } = this.props;
return (
<div className="bl-counter">
<b>{value}</b>
<div className="bl-counter-handler">
<button
className="button is-decrement bl-small"
onClick={() => onIncrement({ id, value: value - 1 })}
>
-
</button>
<button
className="button is-increment bl-small"
onClick={() => onIncrement({ id, value: value + 1 })}
>
+
</button>
</div>
</div>
);
}
}

function BLTotal({ sum }: { sum: number }) {
return <p> BLTotal: {sum}</p>;
}

export default function CountPage() {
const [data, setData] = React.useState<Array<IData>>([
{ id: 1, value: 0 },
{ id: 2, value: 0 },
{ id: 3, value: 0 },
]);

const totalNumber = React.useMemo(() => {
let i = 0;
data.forEach((elm: IData) => {
i += elm.value;
});
return i;
}, [data]);

React.useEffect(() => {
setData([...data, { id: 4, value: 0 }]);
}, []);
// state data for 3 bl-counters

function onChangeCount(payload: IData) {
const { id, value } = payload;
if (id && typeof value === "number") {
const newData = Array.from(data, (elm: IData) => {
if (elm.id === id) {
return { id, value };
} else {
return elm;
}
});
setData(newData);
}
}

return (
<div>
{data.map((counter: IData) => (
<BLCounter
key={counter.id}
id={counter.id}
value={counter.value}
onIncrement={(payload: IData) => onChangeCount(payload)}
onDecrement={(payload: IData) => onChangeCount(payload)}
/>
))}
<BLTotal sum={totalNumber} />
</div>
);
}



迁站后感想

Posted on 2021-11-24 20:06:51
Comments: 0

因为一些原因,又一次云服务器down掉,

再一次迁移,花了一些时间, 并且原来数据因为是手动定期备份,没有写定时任务备份,导致博客数据丢失了两篇,一篇是 关于 OAuth授权 包括Gitee Github等的实现, 一篇是Docker入门简单小结。 还有就是原来考虑不周全, 所有博文图片 选择保存到云服务器本地,这次直接全部没了,


经此一役, 还是选了七牛云的oss,

总结下了部署环境, nginx, mysql, redis, node及相关全局包以及权限 还有 node-sass 镜像下载依赖等问题,

再接再厉吧, 争取还是能保存每月一篇技术博客小结

1
2
3
4