xiongzhu 3 лет назад
Родитель
Сommit
34b5073edf

+ 47 - 4
src/App.vue

@@ -1,19 +1,59 @@
 <script setup>
 import { RouterView } from "vue-router";
 import { ChevronLeftIcon } from "vue-feather-icons";
+import { ref, watch } from "vue";
+import { useRoute, useRouter } from "vue-router";
+const route = useRoute();
+const router = useRouter();
+const title = ref("苏康码");
+watch(
+    () => route.name,
+    () => {
+        console.log(
+            `MyCoolComponent - watch route.name changed to ${route.name}`
+        );
+        // Do something here...
+
+        // Optionally you can set immediate: true config for the watcher to run on init
+        //}, { immediate: true });
+        switch (route.name) {
+            case "home":
+            case "list":
+                title.value = "苏康码";
+                break;
+            case "pass":
+                title.value = "通信行程卡";
+                break;
+            case "settings":
+                title.value = "设置";
+                break;
+            default:
+                title.value = "苏康码";
+                break;
+        }
+    }
+);
+const back = () => {
+    if (route.name !== "home") {
+        router.go(-1);
+    }
+};
 </script>
 
 <template>
     <div class="nav-bar">
-        <div class="left"></div>
-        <div class="title">苏康码</div>
+        <div class="nav-back" @click="back">
+            <div class="left"></div>
+            <div class="title">{{ title }}</div>
+        </div>
+        <div style="flex-grow: 1"></div>
         <img class="capsule" src="./assets/capsule.png" />
     </div>
     <div class="nav-bar-placeholder"></div>
     <RouterView />
 </template>
 
-<style lang="less">
+<style lang="less" scoped>
 .nav-bar-placeholder {
     height: 40px;
 }
@@ -29,7 +69,10 @@ import { ChevronLeftIcon } from "vue-feather-icons";
     .title {
         font-size: 20px;
         font-weight: bold;
-        flex-grow: 1;
+    }
+    .nav-back {
+        display: flex;
+        align-items: center;
     }
     .capsule {
         height: 28px;

BIN
src/assets/banner-bg1.png


BIN
src/assets/gif_green.gif


BIN
src/assets/green.png


BIN
src/assets/guangdian.png


BIN
src/assets/hours.png


BIN
src/assets/img_CAICT@3x.png


BIN
src/assets/img_bg.png


BIN
src/assets/img_tel@3x.png


BIN
src/assets/liantong.png


+ 4 - 0
src/assets/main.css

@@ -1,3 +1,7 @@
+html {
+    font-size: 52px;
+}
+
 html body {
     padding: 0;
     margin: 0;

BIN
src/assets/yidong0.png


+ 6 - 1
src/router/index.js

@@ -1,6 +1,8 @@
 import { createRouter, createWebHashHistory } from "vue-router";
 import HomeView from "../views/HomeView.vue";
-
+import List from "../views/List.vue";
+import Pass from '../views/Pass.vue'
+import Settings from '../views/Settings.vue'
 const router = createRouter({
     history: createWebHashHistory(),
     routes: [
@@ -9,6 +11,9 @@ const router = createRouter({
             name: "home",
             component: HomeView,
         },
+        { path: "/list", name: "list", component: List },
+        { path: "/pass", name: "pass", component: Pass },
+        { path: "/settings", name: "settings", component: Settings },
     ],
 });
 

+ 11 - 0
src/stores/config.js

@@ -0,0 +1,11 @@
+import { ref } from "vue";
+import { defineStore } from "pinia";
+
+export const useConfigStore = defineStore("config", () => {
+    const config = ref(JSON.parse(localStorage.getItem("config") || "{}"));
+    function save(val) {
+        config.value = val;
+        localStorage.setItem("config", JSON.stringify(val));
+    }
+    return { config, save };
+});

+ 48 - 15
src/views/HomeView.vue

@@ -5,12 +5,17 @@ import SwiperClass, { Pagination } from "swiper";
 import { Swiper, SwiperSlide } from "vue-awesome-swiper";
 import { addDays, parse, format, set } from "date-fns";
 import { ref } from "vue";
+import { useRouter } from "vue-router";
+import { useConfigStore } from "../stores/config";
 
 // import swiper module styles
 import "swiper/css";
 import "swiper/css/pagination";
 // more module style...
 
+const configStore = useConfigStore();
+const config = configStore.config;
+const router = useRouter();
 const currentTime = ref(format(new Date(), "MM-dd HH:mm:ss"));
 setInterval(() => {
     currentTime.value = format(new Date(), "MM-dd HH:mm:ss");
@@ -24,23 +29,33 @@ const testTime = set(addDays(new Date(), -1), {
 const year = format(testTime, "yyyy");
 const monthDay = format(testTime, "MM-dd");
 const time = format(testTime, "HH:mm:ss");
+
+const counter = ref(0);
+
+const clickImg = () => {
+    counter.value++;
+    if (counter.value === 5) {
+        router.push("/settings");
+    }
+    setTimeout(() => {
+        counter.value = 0;
+    }, 3000);
+};
 </script>
 
 <template>
     <div class="header">
         <div class="row1">
-            <img src="../assets/logo.png" class="icon" />
+            <img src="../assets/logo.png" class="icon" @click="clickImg" />
             <div class="title">苏康码·绿码</div>
-            <div class="name">熊竹</div>
+            <div class="name">{{ config.name }}</div>
         </div>
         <div class="row2">
             <div class="phone">
-                {{ "15077886171".replace(/(.{3})\d{4}(.*)/, "$1****$2") }}
+                {{ config.phone.replace(/(.{3})\d{4}(.*)/, "$1****$2") }}
             </div>
             <div class="id">
-                {{
-                    "321002199408304614".replace(/(.{3}).*(.{3})/, "$1******$2")
-                }}
+                {{ config.id.replace(/(.{3}).*(.{3})/, "$1******$2") }}
             </div>
         </div>
     </div>
@@ -65,13 +80,13 @@ const time = format(testTime, "HH:mm:ss");
             </div>
         </div>
     </div>
-    <swiper>
+    <swiper :initialSlide="1">
         <swiper-slide>
             <div class="slider detail">
                 <div class="sample">
                     <div class="row">
                         <div class="title">采样点:</div>
-                        <div class="content">托乐嘉售楼处</div>
+                        <div class="content">{{ config.address }}</div>
                     </div>
                     <div class="row">
                         <div class="title">检测时间:</div>
@@ -92,7 +107,7 @@ const time = format(testTime, "HH:mm:ss");
                         数据来源:江苏省卫生健康委员会,反映近30天内最近一次核酸检测情况,数据在不断汇聚和完善中。
                     </div>
                 </div>
-                <div class="btn">
+                <div class="btn" @click="$router.push('/list')">
                     <img
                         src="../assets/hs-detail.png"
                         class="icon"
@@ -106,13 +121,11 @@ const time = format(testTime, "HH:mm:ss");
         <swiper-slide>
             <div class="slider code-info">
                 <div class="info1">
-                    <div class="box">
+                    <div class="box b48">
                         <div class="title">核酸(省内)</div>
                         <div class="content">
-                            <div class="text1">阴性</div>
-                            <div class="text2">
-                                {{ year }}<br />{{ monthDay }}
-                            </div>
+                            <div class="text1">48</div>
+                            <div class="text2">小时<br />阴性</div>
                         </div>
                         <div class="footer">
                             <div class="icon right"></div>
@@ -135,7 +148,7 @@ const time = format(testTime, "HH:mm:ss");
                         </div>
                     </div>
                 </div>
-                <div class="info2">
+                <div class="info2" @click="$router.push('/pass')">
                     <img
                         src="../assets/xingcheng.png"
                         class="icon"
@@ -383,6 +396,26 @@ const time = format(testTime, "HH:mm:ss");
                     font-size: 16px;
                 }
             }
+            &.b48 {
+                box-shadow: 0 0 0.24rem 0 #34bf4b;
+                border: 3px solid #34bf4b;
+                color: #34bf4b;
+                .title {
+                }
+                .content {
+                    .text1 {
+                        font-family: Helvetica;
+                        font-weight: 800;
+                        font-size: 44px;
+                        margin-right: 7px;
+                    }
+                    .text2 {
+                        font-size: 16px;
+                        font-weight: 500;
+                        line-height: 18px;
+                    }
+                }
+            }
         }
     }
     .info2 {

+ 149 - 0
src/views/List.vue

@@ -0,0 +1,149 @@
+<script setup>
+import { addSeconds, addDays, format, set, differenceInHours } from "date-fns";
+import { useConfigStore } from "../stores/config";
+const configStore = useConfigStore();
+const name = configStore.config.name;
+const address = configStore.config.address;
+const time = set(new Date(), { hours: 18, minutes: 1, seconds: 1 });
+const data = [1, 2, 3].map((i) => {
+    let t = addSeconds(
+        addDays(time, -i),
+        i > 1 ? -parseInt(2500 + Math.random() * 2500) : 0
+    );
+    let h = differenceInHours(new Date(), t);
+    return {
+        name,
+        address,
+        time: format(t, "yyyy-MM-dd HH:mm:ss"),
+        active: h <= 48,
+    };
+});
+</script>
+<template>
+    <div class="head">
+        <div class="title">核酸检测结果</div>
+        <div class="id">
+            <span style="margin-right: 10px">身份证号:</span>
+            <span>{{
+                configStore.config.id.replace(/(.{6}).*(.{4})/, "$1********$2")
+            }}</span>
+        </div>
+        <div class="back" @click="$router.go(-1)">返回</div>
+    </div>
+    <div
+        class="item"
+        :class="{ active: item.active }"
+        v-for="(item, i) in data"
+    >
+        <div class="bg">江苏省卫生健康委员会</div>
+        <img src="../assets/hours.png" class="hours" />
+        <div class="row">
+            <span class="title">姓名:</span>
+            <span class="text">{{ item.name }}</span>
+        </div>
+        <div class="row">
+            <span class="title">采样点:</span>
+            <span class="text">{{ item.address }}</span>
+        </div>
+        <div class="row">
+            <span class="title">检测时间:</span>
+            <span class="text t">{{ item.time }}</span>
+        </div>
+        <div class="row">
+            <span class="title">检测结果:</span>
+            <span class="text r">阴性</span>
+        </div>
+    </div>
+</template>
+<style lang="less" scoped>
+.head {
+    height: 107px;
+    background: url("../assets/banner-bg1.png") no-repeat;
+    background-size: 100% 100%;
+    padding: 20px 20px 0 20px;
+    position: relative;
+    .title {
+        font-size: 18px;
+        font-weight: 600;
+        margin-bottom: 5px;
+        margin-top: 2px;
+        color: #fff;
+    }
+    .id {
+        font-size: 15px;
+        color: #fff;
+        line-height: 30px;
+    }
+    .back {
+        position: absolute;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        right: 18px;
+        top: 14px;
+        z-index: 20;
+        border-radius: 12px;
+        height: 24px;
+        width: 60px;
+        color: #fff;
+        border: 1px solid #fff;
+        font-size: 16px;
+    }
+}
+.item {
+    background: #fff;
+    position: relative;
+    padding: 10px 0 10px 20px;
+    margin-top: 15px;
+    .bg {
+        z-index: 10;
+        position: absolute;
+        top: 30%;
+        left: 20%;
+        transform: rotate(-345deg);
+        font-weight: bold;
+        font-size: 22px;
+        color: #e6e9ec;
+        letter-spacing: 0;
+        text-align: center;
+    }
+    .row {
+        z-index: 100;
+        position: relative;
+        line-height: 24px;
+        .title {
+            width: 80px;
+            color: #898989;
+            font-size: 16px;
+            display: inline-block;
+            margin-bottom: 8px;
+        }
+        .text {
+            color: #494949;
+            font-size: 17px;
+        }
+    }
+    .hours {
+        display: none;
+    }
+    &.active {
+        border-top: 1px solid #159000;
+        border-bottom: 1px solid #159000;
+        background: #ecfff3;
+        .t {
+            color: red;
+        }
+        .r {
+            font-weight: bold;
+            color: rgb(0, 201, 2);
+        }
+        .hours {
+            display: block;
+            width: 72px;
+            position: absolute;
+            right: 10px;
+            top: 10px;
+        }
+    }
+}
+</style>

+ 244 - 0
src/views/Pass.vue

@@ -0,0 +1,244 @@
+<script setup>
+import { useConfigStore } from "../stores/config";
+import { format } from "date-fns";
+const config = useConfigStore().config;
+const time = format(new Date(), "yyyy-MM-dd HH:mm:ss");
+</script>
+<template>
+    <div class="pass">
+        <div class="container">
+            <div class="banner-img-holder imgholder2"></div>
+            <div class="main">
+                <div class="top green"></div>
+                <p class="hidden-tel">
+                    {{
+                        config.phone.replace(/(.{3})\d{4}(.*)/, "$1****$2")
+                    }}的动态行程卡
+                </p>
+                <p class="update">更新于:{{ time }}</p>
+                <div class="info">
+                    <div class="img-holder green-bg">
+                        <img src="../assets/gif_green.gif" class="qr-img" />
+                    </div>
+                </div>
+                <div class="bott">
+                    <div class="loc">
+                        您于前7天内到达或途经:<span>{{ config.city }}</span>
+                    </div>
+                </div>
+            </div>
+            <div class="tip">
+                结果包含您在前7天内到访的国家(地区)与停留4小时以上的国内城市<br /><br />
+                色卡仅对到访地作提醒,不关联健康状况
+            </div>
+            <div class="foot-box">
+                <footer class="footer-comp">
+                    <div>
+                        <p style="font-size: 0.24rem; color: white">
+                            ————————— 本服务联合提供 —————————
+                        </p>
+                    </div>
+                    <div class="caict">
+                        <img src="../assets/img_CAICT@3x.png" class="caict1" />
+                        <img src="../assets/img_CAICT@3x.png" class="caict2" />
+                        <img src="../assets/yidong0.png" class="caict3" />
+                        <img src="../assets/liantong.png" class="caict4" />
+                        <img src="../assets/guangdian.png" class="caict5" />
+                    </div>
+                </footer>
+            </div>
+        </div>
+        <div
+            class="bottom-info"
+            style="display: flex; background: rgb(248, 248, 248); width: 100%"
+        >
+            <div
+                style="
+                    color: rgb(68, 68, 68);
+                    text-align: left;
+                    padding-top: 0.1rem;
+                    font-size: 0.24rem;
+                    padding-left: 0.55rem;
+                    padding-bottom: 0.1rem;
+                    display: flex;
+                    width: 100%;
+                "
+            >
+                <div style="margin-left: 0.2rem; width: 39%">
+                    <div
+                        style="
+                            font-weight: bold;
+                            margin-bottom: 0.12rem;
+                            margin-top: 0.2rem;
+                        "
+                    >
+                        一证通查来了!
+                    </div>
+                    <div style="font-size: 0.2rem">立即点击进入</div>
+                </div>
+                <div
+                    style="
+                        padding: 0.2rem;
+                        background-color: rgb(0, 0, 0);
+                        color: rgb(255, 255, 255);
+                        border-radius: 0.1rem;
+                    "
+                >
+                    <div style="font-weight: bold; margin-bottom: 0.12rem">
+                        全国移动电话卡“⼀证通查”
+                    </div>
+                    <div style="font-size: 0.2rem; text-align: center">
+                        防范诈骗,保护你我
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+</template>
+<style lang="less" scoped>
+.pass {
+    background: rgb(57, 165, 105);
+    min-height: 100vh;
+}
+* {
+    text-align: center;
+}
+p {
+    margin: 0;
+}
+.container {
+    background: url("../assets/img_bg.png") no-repeat;
+    background-size: 100% 100%;
+    position: relative;
+    margin-top: -0.45rem;
+    .banner-img-holder {
+        position: relative;
+        width: 100%;
+        height: 0;
+        padding-top: 2.62rem;
+    }
+    .main {
+        width: 6.4rem;
+        min-height: 7.12rem;
+        margin: 0 auto 0 auto;
+        background-color: #fff;
+        border-radius: 0.24rem;
+        -webkit-box-shadow: 0 0 0.24rem 0 #dedede;
+        box-shadow: 0 0 0.24rem 0 #dedede;
+        overflow: hidden;
+        .top {
+            background: url("../assets/green.png");
+            background-size: 100%;
+            height: 0.64rem;
+            overflow: hidden;
+        }
+        .hidden-tel {
+            color: #46464c;
+            font-size: 0.35rem;
+            font-weight: 700;
+            padding: 0.4rem 0 0.32rem;
+            line-height: 1.2;
+        }
+        .update {
+            font-size: 0.35rem;
+            color: #94949e;
+            letter-spacing: 0;
+            text-align: center;
+            padding-bottom: 0.36rem;
+        }
+        .info {
+            .img-holder {
+                width: 3.6rem;
+                height: 3.6rem;
+                margin: 0 auto;
+                display: flex;
+                justify-content: center;
+                align-items: center;
+                .qr-img {
+                    width: 100%;
+                    height: 100%;
+                }
+            }
+        }
+        .bott {
+            width: 5.67rem;
+            margin: 0.36rem auto 0;
+            color: #94949e;
+            padding-bottom: 0.3rem;
+            padding-top: 0.15rem;
+            font-size: 0.24rem;
+            display: -webkit-box;
+            display: -ms-flexbox;
+            display: flex;
+            justify-content: flex-start;
+            align-items: center;
+            border-top: 1px solid #e4e4e4;
+            .loc {
+                text-align: left;
+                font-size: 18px;
+                line-height: 24px;
+                span {
+                    color: black;
+                    font-weight: bold;
+                }
+            }
+        }
+    }
+    .tip {
+        margin-top: 0.32rem;
+        font-size: 0.2rem;
+        color: #fff;
+    }
+    .foot-box {
+        .footer-comp {
+            color: #94949e;
+            width: 7.5rem;
+            padding: 0.35rem 0;
+            margin: 0 auto;
+            .caict {
+                margin: 0.15rem auto 0;
+                display: -webkit-box;
+                display: -ms-flexbox;
+                display: flex;
+                flex-shrink: 0;
+                flex-direction: row;
+                justify-content: center;
+                width: 100%;
+                img {
+                    width: 20%;
+                    object-fit: cover;
+                }
+                .caict1 {
+                    margin-top: 0.015rem;
+                    height: 0.28rem;
+                    width: 1.54rem;
+                }
+                .caict2 {
+                    height: 0.3rem;
+                    width: 1rem;
+                    margin-left: 0.185rem;
+                }
+                .caict3 {
+                    height: 0.34rem;
+                    width: 1.2rem;
+                    margin-left: 0.185rem;
+                }
+                .caict4 {
+                    height: 0.33rem;
+                    width: 1.18rem;
+                    margin-left: 0.185rem;
+                }
+                .caict5 {
+                    height: 0.34rem;
+                    width: 1.3rem;
+                    margin-left: 0.15rem;
+                }
+            }
+        }
+    }
+}
+.bottom-info {
+    position: fixed;
+    bottom: 0;
+}
+</style>

+ 54 - 0
src/views/Settings.vue

@@ -0,0 +1,54 @@
+<template>
+    <div>
+        <cell-group inset style="margin-top: 20px">
+            <field
+                v-model="config.name"
+                label="姓名"
+                placeholder="请输入姓名"
+            />
+            <field v-model="config.id" label="身份证" placeholder="身份证" />
+            <field v-model="config.phone" label="手机" placeholder="手机" />
+            <field
+                v-model="config.address"
+                label="采样地址"
+                placeholder="采样地址"
+            />
+            <field v-model="config.city" label="途经" placeholder="途经" />
+        </cell-group>
+        <div style="padding: 20px 16px">
+            <v-button type="primary" block round @click="save"> 保存 </v-button>
+            <v-button
+                type="primary"
+                block
+                round
+                @click="back"
+                style="margin-top: 10px"
+                plain
+            >
+                返回
+            </v-button>
+        </div>
+    </div>
+</template>
+
+<script setup>
+import { CellGroup, Field, Button as vButton, Toast } from "vant";
+import { ref } from "vue";
+import { useConfigStore } from "../stores/config";
+import { useRouter } from "vue-router";
+
+const router = useRouter();
+
+const configStore = useConfigStore();
+const config = ref({ ...configStore.config });
+
+const save = () => {
+    configStore.save(config.value);
+    Toast.success("保存成功");
+};
+const back = () => {
+    router.go(-1);
+};
+</script>
+
+<style lang="less" scoped></style>