hookehuyr

feat(路由): 新增签到模块相关页面和路由配置

添加签到模块的首页、扫码页和信息详情页
配置签到模块的路由路径
实现音频播放、图片预览等功能
1 /* 1 /*
2 * @Date: 2023-05-29 11:10:19 2 * @Date: 2023-05-29 11:10:19
3 * @LastEditors: hookehuyr hookehuyr@gmail.com 3 * @LastEditors: hookehuyr hookehuyr@gmail.com
4 - * @LastEditTime: 2025-02-10 16:19:29 4 + * @LastEditTime: 2025-08-26 15:46:05
5 * @FilePath: /map-demo/src/route.js 5 * @FilePath: /map-demo/src/route.js
6 * @Description: 文件描述 6 * @Description: 文件描述
7 */ 7 */
...@@ -112,4 +112,18 @@ export default [ ...@@ -112,4 +112,18 @@ export default [
112 title: '详情页', 112 title: '详情页',
113 }, 113 },
114 }, 114 },
115 + {
116 + path: '/checkin',
117 + component: () => import('@/views/checkin/map.vue'),
118 + meta: {
119 + title: '地图',
120 + },
121 + },
122 + {
123 + path: '/checkin/info',
124 + component: () => import('@/views/checkin/info.vue'),
125 + meta: {
126 + title: '详情页',
127 + },
128 + },
115 ]; 129 ];
......
1 +<!--
2 + * @Date: 2024-09-14 17:48:55
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-09-21 23:04:40
5 + * @FilePath: /map-demo/src/views/bieyuan/index.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="index-page">
10 + <div style="display: flex; flex-direction: column; align-items: center;">
11 + <van-image
12 + width="12rem"
13 + height="12rem"
14 + fit="contain"
15 + src="https://cdn.ipadbiz.cn/bieyuan/map/icon/index_logo@3x.png"
16 + />
17 + <div style="margin-top: 2rem; font-size: 0.95rem; letter-spacing: 5px; color: #47525F;">山水逢甘露,静心遇桃源</div>
18 + </div>
19 + <div @click="goTo" style="border: 1px solid #DD7850; padding: 0.8rem 5.5rem; border-radius: 5px; font-size: 1.15rem; color: #DD7850; background-color: white;">进&nbsp;入</div>
20 + </div>
21 +</template>
22 +
23 +<script setup>
24 +import { ref } from 'vue'
25 +import { useRoute, useRouter } from 'vue-router'
26 +
27 +//import { } from '@/utils/generateModules.js'
28 +//import { } from '@/utils/generateIcons.js'
29 +//import { } from '@/composables'
30 +const $route = useRoute();
31 +const $router = useRouter();
32 +
33 +const goTo = () => {
34 + $router.push({
35 + path: './map',
36 + query: {
37 + id: $route.query.id
38 + }
39 + });
40 + // 进入标记
41 + localStorage.setItem('first_in_bieyuan', 1);
42 +}
43 +
44 +onMounted(() => {
45 + // 记录第一次进入页面,之后判断是否第一次进入,直接跳转到MAP页面
46 + if (localStorage.getItem('first_in_bieyuan') === '1') {
47 + $router.push({
48 + path: './map',
49 + query: {
50 + id: $route.query.id
51 + }
52 + });
53 + }
54 +});
55 +</script>
56 +
57 +<style lang="less" scoped>
58 + .index-page {
59 + height: 100vh;
60 + display: flex;
61 + flex-direction: column;
62 + justify-content: space-evenly;
63 + align-items: center;
64 + background: linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5)),
65 + url('https://cdn.ipadbiz.cn/bieyuan/map/MAP@3x.png');
66 + background-size: contain;
67 + }
68 +</style>
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
This diff is collapsed. Click to expand it.
1 +<!--
2 + * @Date: 2024-09-15 11:45:13
3 + * @LastEditors: hookehuyr hookehuyr@gmail.com
4 + * @LastEditTime: 2024-09-18 11:15:56
5 + * @FilePath: /map-demo/src/views/bieyuan/scan.vue
6 + * @Description: 文件描述
7 +-->
8 +<template>
9 + <div class="scan-page">
10 + <!--<div class="scan_wrapper">
11 + <div class="scan_box">
12 + <!~~ 镜头区域 ~~>
13 + <video ref="video" id="video" class="scan-video" autoplay></video>
14 + </div>
15 + <div @click="openScan" class="scan_text">点击扫描二维码查看详情</div>
16 + </div>
17 + <div class="sys_logo">
18 + <van-image
19 + width="3rem"
20 + height="3rem"
21 + fit="contain"
22 + src="https://cdn.ipadbiz.cn/bieyuan/map/icon/scan_logo.png"
23 + />
24 + </div>-->
25 +
26 + <video ref="video" id="video" class="video vjs-fluid" autoplay></video>
27 + <div v-show="tipShow" class="tip">{{tipMsg}}</div>
28 + </div>
29 +</template>
30 +
31 +<script setup>
32 +import { ref } from "vue";
33 +import { useRoute, useRouter } from "vue-router";
34 +
35 +const $route = useRoute();
36 +const $router = useRouter();
37 +
38 +import { BrowserMultiFormatReader } from "@zxing/library";
39 +// import axios from 'axios'
40 +const codeReader = ref(null);
41 +
42 +const scanText = ref("");
43 +// 初始化相机
44 +const openScan = () => {
45 + codeReader.value = new BrowserMultiFormatReader();
46 + codeReader.value
47 + .getVideoInputDevices()
48 + .then((videoDevices) => {
49 + let firstDeviceId = videoDevices[videoDevices.length - 1].deviceId;
50 + if (videoDevices.length > 1) {
51 + // 一般通过判断摄像头列表项里的 label 字段,'camera2 0, facing back' 字符串含有 'back' 和 '0',大部分机型是这样,如果有些机型没有,那就还是默认获取最后一个
52 + firstDeviceId = videoDevices.find((el) => {
53 + return el.label.indexOf("back") > -1 && el.label.indexOf("0") > -1;
54 + })
55 + ? videoDevices.find((el) => {
56 + return el.label.indexOf("back") > -1 && el.label.indexOf("0") > -1;
57 + }).deviceId
58 + : videoDevices[videoDevices.length - 1].deviceId;
59 + }
60 + decodeFromInputVideoFunc(firstDeviceId);
61 + })
62 + .catch((err) => {
63 + console.log(err);
64 + });
65 +};
66 +
67 +// 扫码
68 +const decodeFromInputVideoFunc = (firstDeviceId) => {
69 + // 使用摄像头扫描
70 + codeReader.value.reset(); // 重置
71 + codeReader.value.decodeFromInputVideoDeviceContinuously(
72 + firstDeviceId,
73 + "video",
74 + (result, err) => {
75 + if (result) {
76 + alert(result.text);
77 + console.log("扫码结果", result);
78 + scanText.value = result.text;
79 + if (scanText.value) {
80 + // 识别成功关闭摄像头
81 + codeReader.value.reset();
82 + codeReader.value.stopContinuousDecodeFromInputVideoDevice();
83 + }
84 + }
85 + }
86 + );
87 +};
88 +
89 +onMounted(() => {});
90 +</script>
91 +
92 +
93 +<style lang="less" scoped>
94 +.scan-page {
95 + position: relative;
96 + height: 100vh;
97 + .scan_wrapper {
98 + display: flex;
99 + padding: 1rem;
100 + flex-direction: column;
101 + align-items: center;
102 + padding-top: 5rem;
103 + .scan_box {
104 + padding: 1rem;
105 + background-image: url('https://cdn.ipadbiz.cn/bieyuan/map/icon/scan_bg.png');
106 + background-size: contain;
107 + background-repeat: no-repeat;
108 + background-position: center center;
109 + height: 20rem;
110 + width: 90%;
111 + position: relative;
112 + overflow: hidden; /* 确保溢出内容被隐藏 */
113 + box-sizing: border-box; /* 包括 padding 在内的尺寸计算 */
114 + .scan-video {
115 + object-fit: cover; /* 保持视频内容的比例,同时填满容器 */
116 + position: absolute; /* 确保视频覆盖整个容器 */
117 + top: -1rem;
118 + left: -1rem;
119 + width: calc(100% - 2rem); /* 视频宽度减去左右1rem的padding */
120 + height: calc(100% - 2rem); /* 视频高度减去上下1rem的padding */
121 + padding: 2rem;
122 + object-fit: cover; /* 保持视频比例,同时填充容器 */
123 + }
124 + }
125 + .scan_text {
126 + font-size: 0.9rem;
127 + color: #DD7850;
128 + padding: 0.5rem 1rem;
129 + margin: 1rem;
130 + border: 1px solid #DD7850;
131 + border-radius: 5px;
132 + }
133 + }
134 + .sys_logo {
135 + position: absolute;
136 + bottom: 3rem;
137 + left: calc(50% - 1.5rem);
138 + }
139 +}
140 +</style>