diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1aa0ecb..2744752 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -7,7 +7,7 @@
"editor.tabSize": 2,
"editor.formatOnPaste": true,
"editor.guides.bracketPairs": "active",
- "files.autoSave": "afterDelay",
+ "files.autoSave": "off",
"git.confirmSync": false,
"workbench.startupEditor": "newUntitledFile",
"editor.suggestSelection": "first",
diff --git a/src/router/modules/test.ts b/src/router/modules/test.ts
new file mode 100644
index 0000000..543ae63
--- /dev/null
+++ b/src/router/modules/test.ts
@@ -0,0 +1,19 @@
+export default {
+ path: "/test",
+ redirect: "/test/403",
+ meta: {
+ icon: "material-symbols:import-contacts-outline",
+ title: "测试页面"
+ },
+ children: [
+ {
+ path: "/test/countdown",
+ name: "Countdown",
+ component: () => import("@/views/testPage/Countdown.vue"),
+ meta: {
+ title: "倒计时",
+ keepAlive: false
+ }
+ }
+ ]
+} as RouteConfigsTable;
diff --git a/src/utils/formatDate.ts b/src/utils/formatDate.ts
new file mode 100644
index 0000000..c11f7ea
--- /dev/null
+++ b/src/utils/formatDate.ts
@@ -0,0 +1,47 @@
+interface IDate {
+ [key: string]: number;
+}
+
+/** 正则格式化日期 */
+export const formatDate = (date: Date, dateFormat: string) => {
+ /* 单独格式化年份,根据y的字符数量输出年份
+ * 例如:yyyy => 2019
+ yy => 19
+ y => 9
+ */
+ if (/(y+)/.test(dateFormat)) {
+ dateFormat = dateFormat.replace(
+ RegExp.$1,
+ (date.getFullYear() + "").substr(4 - RegExp.$1.length)
+ );
+ }
+ /** 格式化月、日、时、分、秒 */
+ const o: IDate = {
+ "m+": date.getMonth() + 1,
+ "d+": date.getDate(),
+ "h+": date.getHours(),
+ "i+": date.getMinutes(),
+ "s+": date.getSeconds()
+ };
+ for (const k in o) {
+ if (new RegExp(`(${k})`).test(dateFormat)) {
+ /** 取出对应的值 */
+ const str = o[k] + "";
+ /* 根据设置的格式,输出对应的字符
+ * 例如: 早上8时,hh => 08,h => 8
+ * 但是,当数字>=10时,无论格式为一位还是多位,不做截取,这是与年份格式化不一致的地方
+ * 例如: 下午15时,hh => 15, h => 15
+ */
+ dateFormat = dateFormat.replace(
+ RegExp.$1,
+ RegExp.$1.length === 1 ? str : padLeftZero(str)
+ );
+ }
+ }
+ return dateFormat;
+};
+
+/** 日期时间补零 */
+export const padLeftZero = (str: string | any[]) => {
+ return ("00" + str).substr(str.length);
+};
diff --git a/src/views/testPage/Countdown.vue b/src/views/testPage/Countdown.vue
new file mode 100644
index 0000000..1a82350
--- /dev/null
+++ b/src/views/testPage/Countdown.vue
@@ -0,0 +1,67 @@
+
+
+
+
+
+
+ :
+
+
+ :
+
+
+
+
+
+
diff --git a/src/views/testPage/Flippers.vue b/src/views/testPage/Flippers.vue
new file mode 100644
index 0000000..705f667
--- /dev/null
+++ b/src/views/testPage/Flippers.vue
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
diff --git a/src/views/testPage/filpper.css b/src/views/testPage/filpper.css
new file mode 100644
index 0000000..a535243
--- /dev/null
+++ b/src/views/testPage/filpper.css
@@ -0,0 +1,184 @@
+.m-flipper {
+ display: inline-block;
+ position: relative;
+ width: 60px;
+ height: 100px;
+ line-height: 100px;
+ border: solid 1px #000;
+ border-radius: 10px;
+ background: #fff;
+ font-size: 66px;
+ color: #fff;
+ box-shadow: 0 0 6px rgb(0 0 0 / 50%);
+ text-align: center;
+ font-family: "Helvetica Neue";
+}
+
+.m-flipper .digital::before,
+.m-flipper .digital::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ right: 0;
+ background: #000;
+ overflow: hidden;
+ box-sizing: border-box;
+}
+
+.m-flipper .digital::before {
+ top: 0;
+ bottom: 50%;
+ border-radius: 10px 10px 0 0;
+ border-bottom: solid 1px #666;
+}
+
+.m-flipper .digital::after {
+ top: 50%;
+ bottom: 0;
+ border-radius: 0 0 10px 10px;
+ line-height: 0;
+}
+
+/* 向下翻 */
+.m-flipper.down .front::before {
+ z-index: 3;
+}
+
+.m-flipper.down .back::after {
+ z-index: 2;
+ transform-origin: 50% 0%;
+ transform: perspective(160px) rotateX(180deg);
+}
+
+.m-flipper.down .front::after,
+.m-flipper.down .back::before {
+ z-index: 1;
+}
+
+.m-flipper.down.go .front::before {
+ transform-origin: 50% 100%;
+ animation: frontFlipDown 0.6s ease-in-out both;
+ box-shadow: 0 -2px 6px rgb(255 255 255 / 30%);
+ backface-visibility: hidden;
+}
+
+.m-flipper.down.go .back::after {
+ animation: backFlipDown 0.6s ease-in-out both;
+}
+
+/* 向上翻 */
+.m-flipper.up .front::after {
+ z-index: 3;
+}
+
+.m-flipper.up .back::before {
+ z-index: 2;
+ transform-origin: 50% 100%;
+ transform: perspective(160px) rotateX(-180deg);
+}
+
+.m-flipper.up .front::before,
+.m-flipper.up .back::after {
+ z-index: 1;
+}
+
+.m-flipper.up.go .front::after {
+ transform-origin: 50% 0;
+ animation: frontFlipUp 0.6s ease-in-out both;
+ box-shadow: 0 2px 6px rgb(255 255 255 / 30%);
+ backface-visibility: hidden;
+}
+
+.m-flipper.up.go .back::before {
+ animation: backFlipUp 0.6s ease-in-out both;
+}
+
+@keyframes frontFlipDown {
+ 0% {
+ transform: perspective(160px) rotateX(0deg);
+ }
+
+ 100% {
+ transform: perspective(160px) rotateX(-180deg);
+ }
+}
+
+@keyframes backFlipDown {
+ 0% {
+ transform: perspective(160px) rotateX(180deg);
+ }
+
+ 100% {
+ transform: perspective(160px) rotateX(0deg);
+ }
+}
+
+@keyframes frontFlipUp {
+ 0% {
+ transform: perspective(160px) rotateX(0deg);
+ }
+
+ 100% {
+ transform: perspective(160px) rotateX(180deg);
+ }
+}
+
+@keyframes backFlipUp {
+ 0% {
+ transform: perspective(160px) rotateX(-180deg);
+ }
+
+ 100% {
+ transform: perspective(160px) rotateX(0deg);
+ }
+}
+
+.m-flipper .number0::before,
+.m-flipper .number0::after {
+ content: "0";
+}
+
+.m-flipper .number1::before,
+.m-flipper .number1::after {
+ content: "1";
+}
+
+.m-flipper .number2::before,
+.m-flipper .number2::after {
+ content: "2";
+}
+
+.m-flipper .number3::before,
+.m-flipper .number3::after {
+ content: "3";
+}
+
+.m-flipper .number4::before,
+.m-flipper .number4::after {
+ content: "4";
+}
+
+.m-flipper .number5::before,
+.m-flipper .number5::after {
+ content: "5";
+}
+
+.m-flipper .number6::before,
+.m-flipper .number6::after {
+ content: "6";
+}
+
+.m-flipper .number7::before,
+.m-flipper .number7::after {
+ content: "7";
+}
+
+.m-flipper .number8::before,
+.m-flipper .number8::after {
+ content: "8";
+}
+
+.m-flipper .number9::before,
+.m-flipper .number9::after {
+ content: "9";
+}
diff --git a/src/views/testPage/types.ts b/src/views/testPage/types.ts
new file mode 100644
index 0000000..b20487c
--- /dev/null
+++ b/src/views/testPage/types.ts
@@ -0,0 +1,6 @@
+export interface HTMLElementPlus extends HTMLElement {
+ flipUp: Function;
+ flipDown: Function;
+ setFront: Function;
+ setBack: Function;
+}