init
3
.gitignore
vendored
@ -423,3 +423,6 @@ docs/_book
|
||||
# TODO: where does this rule come from?
|
||||
test/
|
||||
|
||||
dist/
|
||||
|
||||
package-lock.json
|
46
index.html
Normal file
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="shortcut icon" href="#" />
|
||||
<link rel="icon" type="image/x-icon" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||
<title>素材网</title>
|
||||
|
||||
<link rel="stylesheet/less" type="text/css" href="/css/ly.less" />
|
||||
|
||||
<script src="js/jquery-1.11.3.min.js"></script>
|
||||
<script src="js/html2canvas.min.js"></script>
|
||||
<script src="js/canvas2image.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app" v-cloak></div>
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
</body>
|
||||
|
||||
<style>
|
||||
[v-cloak] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Light mode */
|
||||
@media (prefers-color-scheme: light) {
|
||||
body {
|
||||
--base-nav-bar-bg-color: #ededed;
|
||||
--base-nav-bar-color: #111;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
--base-nav-bar-bg-color: #111;
|
||||
--base-nav-bar-color: #ededed;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
</html>
|
34
package.json
Normal file
@ -0,0 +1,34 @@
|
||||
{
|
||||
"name": "pan.template.h5",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"axios": "^1.7.9",
|
||||
"canvas2image": "^1.0.5",
|
||||
"element-plus": "^2.9.4",
|
||||
"html2canvas": "^1.4.1",
|
||||
"jquery": "^3.7.1",
|
||||
"pan.template.h5": "file:",
|
||||
"postcss-px-to-viewport": "^1.1.1",
|
||||
"vant": "^4.9.9",
|
||||
"vue": "^3.2.45",
|
||||
"vue-fast-marquee": "^1.0.6",
|
||||
"vue-qr": "^4.0.9",
|
||||
"vue-router": "^4.5.0",
|
||||
"vuex": "^4.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^22.10.5",
|
||||
"@vant/auto-import-resolver": "^1.0.1",
|
||||
"@vitejs/plugin-vue": "^4.3.4",
|
||||
"less": "^4.2.0",
|
||||
"unplugin-auto-import": "^19.1.0",
|
||||
"unplugin-vue-components": "^0.25.2",
|
||||
"vite": "^4.5.5"
|
||||
}
|
||||
}
|
BIN
public/.DS_Store
vendored
Normal file
140
public/css/common.less
Normal file
@ -0,0 +1,140 @@
|
||||
body {
|
||||
.b_l_w;
|
||||
font-size: 3.2vw;
|
||||
}
|
||||
|
||||
.bg(@e, @url) {
|
||||
&::before {
|
||||
content: '';
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
left: 0;
|
||||
top: 0;
|
||||
background-color: @e;
|
||||
background-image: @url;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 100% auto;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
|
||||
.f5 {
|
||||
.bg(#f5f5f5, none);
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
[v-cloak] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
body,
|
||||
.van-pull-refresh {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
.van-toast {
|
||||
width: max-content !important;
|
||||
}
|
||||
|
||||
.van-nav-bar--fixed {
|
||||
z-index: 999 !important;
|
||||
}
|
||||
|
||||
.van-tabbar__placeholder {
|
||||
.b_l_w;
|
||||
}
|
||||
|
||||
.van-nav-bar {
|
||||
|
||||
.van-nav-bar__text,
|
||||
.van-icon {
|
||||
color: #000 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.van-nav-bar__placeholder {
|
||||
.van-nav-bar .van-icon {
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
|
||||
.van-tabbar {
|
||||
.b_l_w;
|
||||
height: 20vw !important;
|
||||
|
||||
.van-tabbar-item__icon img {
|
||||
height: 10vw;
|
||||
margin: -2vw 0 0;
|
||||
}
|
||||
|
||||
.van-tabbar-item__text {
|
||||
font-size: 3.2vw;
|
||||
}
|
||||
}
|
||||
|
||||
.tabs {
|
||||
--van-tabs-line-height: 12vw;
|
||||
--van-tab-font-size: 4.267vw;
|
||||
|
||||
.van-tabs__line {
|
||||
border-radius: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.van-image-preview__cover {
|
||||
left: 0 !important;
|
||||
bottom: 0 !important;
|
||||
top: initial !important;
|
||||
width: 100%;
|
||||
height: 12vw !important;
|
||||
}
|
||||
|
||||
.van-uploader {
|
||||
|
||||
.van-uploader__input-wrapper {
|
||||
.b_l_w;
|
||||
.box;
|
||||
.box-tb;
|
||||
.box-align-center;
|
||||
|
||||
>p {
|
||||
font-size: 3.467vw;
|
||||
color: #1b1b1b;
|
||||
}
|
||||
}
|
||||
|
||||
.Avatar {
|
||||
width: 33.333vw;
|
||||
height: 33.333vw;
|
||||
margin: 0 0 5vw;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 2vw;
|
||||
width: 9.333vw;
|
||||
height: 9.333vw;
|
||||
.y50;
|
||||
background: url(/images/upload-picture.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
.y50;
|
||||
}
|
||||
}
|
||||
}
|
334
public/css/gm.less
Normal file
@ -0,0 +1,334 @@
|
||||
::after,
|
||||
::before,
|
||||
* {
|
||||
word-wrap: break-word;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.mx-auto {
|
||||
margin: 0 auto !important;
|
||||
}
|
||||
|
||||
.bs {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.f(@e, @u) {
|
||||
font-size: unit(@e, @u);
|
||||
}
|
||||
|
||||
.r(@e, @u) {
|
||||
border-radius: unit(@e, @u);
|
||||
}
|
||||
|
||||
.mt(@e, @u) {
|
||||
margin-top: unit(@e, @u);
|
||||
}
|
||||
|
||||
.mb(@e, @u) {
|
||||
margin-bottom: unit(@e, @u);
|
||||
}
|
||||
|
||||
.b_k {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.y50 {
|
||||
border-radius: 50%;
|
||||
object-fit: cover !important;
|
||||
}
|
||||
|
||||
.w(@e, @u) {
|
||||
width: unit(@e, @u);
|
||||
}
|
||||
|
||||
.w {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.h {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.w100 {
|
||||
width: 100% !important;
|
||||
|
||||
img {
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.p-r {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.p-a {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.p-f {
|
||||
position: fixed;
|
||||
}
|
||||
|
||||
.div_chao {
|
||||
white-space: nowrap;
|
||||
overflow-x: auto;
|
||||
|
||||
.inline {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
.dis {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dis-l {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.songti {
|
||||
font-family: 宋体;
|
||||
}
|
||||
|
||||
.b_l {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.b_r {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.r {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.b_l_w {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.w1 {
|
||||
width: 100%;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.text-center {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-left {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.text-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.text-hide(@line) {
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis;
|
||||
display: -webkit-box !important;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: @line;
|
||||
}
|
||||
|
||||
.text-hide-1 {
|
||||
overflow: hidden !important;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.gray(@a, @b) {
|
||||
filter: grayscale(@a) invert(@b);
|
||||
}
|
||||
|
||||
.brightness(@a, @b) {
|
||||
filter: brightness(@a) invert(@b);
|
||||
}
|
||||
|
||||
/*伸缩盒子模型*/
|
||||
.box {
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
/*从左至右*/
|
||||
|
||||
.box-lr {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
|
||||
/*从右至左*/
|
||||
|
||||
.box-rl {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
|
||||
/*从上至下*/
|
||||
|
||||
.box-tb {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
|
||||
/*从下至上*/
|
||||
|
||||
.box-bt {
|
||||
flex-direction: column-reverse;
|
||||
}
|
||||
|
||||
|
||||
/*主轴居中*/
|
||||
|
||||
.box-pack-center {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.middle {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
/*justify-content: space-evenly;*/
|
||||
}
|
||||
|
||||
.middle::before,
|
||||
.middle::after {
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
|
||||
/*主轴居左*/
|
||||
|
||||
.box-pack-start {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
|
||||
/*主轴居右*/
|
||||
|
||||
.box-pack-end {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
|
||||
/*主轴左右不留白*/
|
||||
|
||||
.box-pack-between {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
|
||||
/*主轴左右留白*/
|
||||
|
||||
.box-pack-around {
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
/*自动间隔,每个元素的间隔相等*/
|
||||
|
||||
.box-middle {
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
/*交叉轴居中对齐*/
|
||||
|
||||
.box-align-center {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
|
||||
/*交叉轴居左对齐*/
|
||||
|
||||
.box-align-start {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
|
||||
/*交叉轴居右对齐*/
|
||||
|
||||
.box-align-end {
|
||||
align-items: flex-end;
|
||||
}
|
||||
|
||||
|
||||
/**单个指定的子元素自定义对齐方式,可以不同于其他子元素对齐方式**/
|
||||
|
||||
|
||||
/**指定子元素居中对齐**/
|
||||
|
||||
.self-align-center {
|
||||
align-self: center;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
|
||||
/**指定子元素顶部对齐**/
|
||||
|
||||
.self-align-start {
|
||||
align-self: flex-start;
|
||||
}
|
||||
|
||||
|
||||
/**指定子元素底部对齐**/
|
||||
|
||||
.self-align-end {
|
||||
align-self: flex-end;
|
||||
}
|
||||
|
||||
|
||||
/**指定子元素拉伸**/
|
||||
|
||||
.self-align-stretch {
|
||||
align-self: stretch;
|
||||
}
|
||||
|
||||
|
||||
/**子元素换行**/
|
||||
|
||||
.box-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
|
||||
/**子元素不换行**/
|
||||
|
||||
.box-nowrap {
|
||||
flex-wrap: nowrap;
|
||||
}
|
||||
|
||||
|
||||
/*允许子元素伸展(1倍)*/
|
||||
|
||||
.flex {
|
||||
flex-grow: 1;
|
||||
/*如果值是2 那么当前元素就是其他元素宽的2倍了*/
|
||||
}
|
||||
|
||||
/* flex:1 是 flex-grow、flex-shrink、flex-basis的缩写。故其取值可以考虑以下情况:
|
||||
flex-grow:0表示不会拉伸 flex-shrink:1表示 可以缩小
|
||||
flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值是 0 1 auto*/
|
||||
|
||||
/*允许子元素收缩(1倍)*/
|
||||
|
||||
.shrink {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
|
||||
/**水平居中*/
|
||||
|
||||
.box-center-center {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
1495
public/css/ly.less
Normal file
BIN
public/images/.DS_Store
vendored
Normal file
BIN
public/images/about-banner.png
Normal file
After Width: | Height: | Size: 1.3 MiB |
BIN
public/images/about-i1.png
Normal file
After Width: | Height: | Size: 519 KiB |
BIN
public/images/banner.png
Normal file
After Width: | Height: | Size: 2.2 MiB |
BIN
public/images/btm-i1.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
public/images/btm-i2.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
public/images/btm-i3.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
public/images/btm-i4.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/images/btm-i5.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/images/btm-i6.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/images/btm-logo.png
Normal file
After Width: | Height: | Size: 8.0 KiB |
BIN
public/images/bus-i1.png
Normal file
After Width: | Height: | Size: 456 KiB |
BIN
public/images/business-banner.png
Normal file
After Width: | Height: | Size: 515 KiB |
BIN
public/images/cert-bg.png
Normal file
After Width: | Height: | Size: 143 KiB |
BIN
public/images/cert-i1.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
public/images/cert-i2.png
Normal file
After Width: | Height: | Size: 143 KiB |
BIN
public/images/cert-i3.png
Normal file
After Width: | Height: | Size: 136 KiB |
BIN
public/images/cert-i4.png
Normal file
After Width: | Height: | Size: 69 KiB |
BIN
public/images/com-bg.png
Normal file
After Width: | Height: | Size: 1.2 MiB |
BIN
public/images/contact-banner.png
Normal file
After Width: | Height: | Size: 692 KiB |
BIN
public/images/contact-icon1.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
public/images/contact-icon2.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
public/images/contact-icon3.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
public/images/cul-i5.png
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
public/images/culture-i1.png
Normal file
After Width: | Height: | Size: 130 KiB |
BIN
public/images/culture-i2.png
Normal file
After Width: | Height: | Size: 126 KiB |
BIN
public/images/culture-i3.png
Normal file
After Width: | Height: | Size: 112 KiB |
BIN
public/images/culture-i4.png
Normal file
After Width: | Height: | Size: 134 KiB |
BIN
public/images/detail-i1.png
Normal file
After Width: | Height: | Size: 530 KiB |
BIN
public/images/detail-i2.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/detail-i3.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
public/images/detail-i4.png
Normal file
After Width: | Height: | Size: 809 B |
BIN
public/images/detail-i5.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
public/images/detail-i6.png
Normal file
After Width: | Height: | Size: 895 B |
BIN
public/images/detail-i7.png
Normal file
After Width: | Height: | Size: 935 B |
BIN
public/images/develop-bg.png
Normal file
After Width: | Height: | Size: 369 KiB |
BIN
public/images/develop-i1.png
Normal file
After Width: | Height: | Size: 5.6 KiB |
BIN
public/images/develop-i2.png
Normal file
After Width: | Height: | Size: 5.2 KiB |
BIN
public/images/develop-i3.png
Normal file
After Width: | Height: | Size: 6.8 KiB |
BIN
public/images/e-i1.png
Normal file
After Width: | Height: | Size: 150 KiB |
BIN
public/images/e-i2.png
Normal file
After Width: | Height: | Size: 110 KiB |
BIN
public/images/e-i3.png
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
public/images/intro-i1.png
Normal file
After Width: | Height: | Size: 419 KiB |
BIN
public/images/list-i1.png
Normal file
After Width: | Height: | Size: 176 KiB |
BIN
public/images/list-i2.png
Normal file
After Width: | Height: | Size: 201 KiB |
BIN
public/images/list-i3.png
Normal file
After Width: | Height: | Size: 274 KiB |
BIN
public/images/list-i4.png
Normal file
After Width: | Height: | Size: 202 KiB |
BIN
public/images/list-i5.png
Normal file
After Width: | Height: | Size: 233 KiB |
BIN
public/images/list-i6.png
Normal file
After Width: | Height: | Size: 226 KiB |
BIN
public/images/logo.png
Normal file
After Width: | Height: | Size: 8.9 KiB |
BIN
public/images/maps.png
Normal file
After Width: | Height: | Size: 509 KiB |
BIN
public/images/news-banner.png
Normal file
After Width: | Height: | Size: 837 KiB |
BIN
public/images/news-i1.png
Normal file
After Width: | Height: | Size: 102 KiB |
BIN
public/images/newspage-i1.png
Normal file
After Width: | Height: | Size: 530 KiB |
BIN
public/images/office-i1.png
Normal file
After Width: | Height: | Size: 475 KiB |
BIN
public/images/office-i2.png
Normal file
After Width: | Height: | Size: 421 KiB |
BIN
public/images/office-i3.png
Normal file
After Width: | Height: | Size: 185 KiB |
BIN
public/images/office-i4.png
Normal file
After Width: | Height: | Size: 172 KiB |
BIN
public/images/op-i1.png
Normal file
After Width: | Height: | Size: 50 KiB |
BIN
public/images/op-i2.png
Normal file
After Width: | Height: | Size: 72 KiB |
BIN
public/images/op-i3.png
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
public/images/op-i4.png
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
public/images/op-i5.png
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
public/images/op-i6.png
Normal file
After Width: | Height: | Size: 55 KiB |
BIN
public/images/op-i7.png
Normal file
After Width: | Height: | Size: 76 KiB |
BIN
public/images/part-banner.png
Normal file
After Width: | Height: | Size: 741 KiB |
BIN
public/images/part-i1.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
public/images/part-i2.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
BIN
public/images/part-i3.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
public/images/scheme.png
Normal file
After Width: | Height: | Size: 738 KiB |
BIN
public/images/team-i1.png
Normal file
After Width: | Height: | Size: 9.2 KiB |
235
public/js/canvas2image.js
Normal file
@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Canvas2Image v0.1
|
||||
* Copyright (c) 2008 Jacob Seidelin, jseidelin@nihilogic.dk
|
||||
* MIT License [http://www.opensource.org/licenses/mit-license.php]
|
||||
*/
|
||||
|
||||
var Canvas2Image = (function () {
|
||||
|
||||
// check if we have canvas support
|
||||
var bHasCanvas = false;
|
||||
var oCanvas = document.createElement("canvas");
|
||||
if (oCanvas.getContext("2d")) {
|
||||
bHasCanvas = true;
|
||||
}
|
||||
|
||||
// no canvas, bail out.
|
||||
if (!bHasCanvas) {
|
||||
return {
|
||||
saveAsBMP: function () { },
|
||||
saveAsPNG: function () { },
|
||||
saveAsJPEG: function () { }
|
||||
}
|
||||
}
|
||||
|
||||
var bHasImageData = !!(oCanvas.getContext("2d").getImageData);
|
||||
var bHasDataURL = !!(oCanvas.toDataURL);
|
||||
var bHasBase64 = !!(window.btoa);
|
||||
|
||||
var strDownloadMime = "image/octet-stream";
|
||||
|
||||
// ok, we're good
|
||||
var readCanvasData = function (oCanvas) {
|
||||
var iWidth = parseInt(oCanvas.width);
|
||||
var iHeight = parseInt(oCanvas.height);
|
||||
return oCanvas.getContext("2d").getImageData(0, 0, iWidth, iHeight);
|
||||
}
|
||||
|
||||
// base64 encodes either a string or an array of charcodes
|
||||
var encodeData = function (data) {
|
||||
var strData = "";
|
||||
if (typeof data == "string") {
|
||||
strData = data;
|
||||
} else {
|
||||
var aData = data;
|
||||
for (var i = 0; i < aData.length; i++) {
|
||||
strData += String.fromCharCode(aData[i]);
|
||||
}
|
||||
}
|
||||
return btoa(strData);
|
||||
}
|
||||
|
||||
// creates a base64 encoded string containing BMP data
|
||||
// takes an imagedata object as argument
|
||||
var createBMP = function (oData) {
|
||||
var aHeader = [];
|
||||
|
||||
var iWidth = oData.width;
|
||||
var iHeight = oData.height;
|
||||
|
||||
aHeader.push(0x42); // magic 1
|
||||
aHeader.push(0x4D);
|
||||
|
||||
var iFileSize = iWidth * iHeight * 3 + 54; // total header size = 54 bytes
|
||||
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
||||
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
||||
aHeader.push(iFileSize % 256); iFileSize = Math.floor(iFileSize / 256);
|
||||
aHeader.push(iFileSize % 256);
|
||||
|
||||
aHeader.push(0); // reserved
|
||||
aHeader.push(0);
|
||||
aHeader.push(0); // reserved
|
||||
aHeader.push(0);
|
||||
|
||||
aHeader.push(54); // dataoffset
|
||||
aHeader.push(0);
|
||||
aHeader.push(0);
|
||||
aHeader.push(0);
|
||||
|
||||
var aInfoHeader = [];
|
||||
aInfoHeader.push(40); // info header size
|
||||
aInfoHeader.push(0);
|
||||
aInfoHeader.push(0);
|
||||
aInfoHeader.push(0);
|
||||
|
||||
var iImageWidth = iWidth;
|
||||
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
||||
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
||||
aInfoHeader.push(iImageWidth % 256); iImageWidth = Math.floor(iImageWidth / 256);
|
||||
aInfoHeader.push(iImageWidth % 256);
|
||||
|
||||
var iImageHeight = iHeight;
|
||||
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
||||
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
||||
aInfoHeader.push(iImageHeight % 256); iImageHeight = Math.floor(iImageHeight / 256);
|
||||
aInfoHeader.push(iImageHeight % 256);
|
||||
|
||||
aInfoHeader.push(1); // num of planes
|
||||
aInfoHeader.push(0);
|
||||
|
||||
aInfoHeader.push(24); // num of bits per pixel
|
||||
aInfoHeader.push(0);
|
||||
|
||||
aInfoHeader.push(0); // compression = none
|
||||
aInfoHeader.push(0);
|
||||
aInfoHeader.push(0);
|
||||
aInfoHeader.push(0);
|
||||
|
||||
var iDataSize = iWidth * iHeight * 3;
|
||||
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
||||
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
||||
aInfoHeader.push(iDataSize % 256); iDataSize = Math.floor(iDataSize / 256);
|
||||
aInfoHeader.push(iDataSize % 256);
|
||||
|
||||
for (var i = 0; i < 16; i++) {
|
||||
aInfoHeader.push(0); // these bytes not used
|
||||
}
|
||||
|
||||
var iPadding = (4 - ((iWidth * 3) % 4)) % 4;
|
||||
|
||||
var aImgData = oData.data;
|
||||
|
||||
var strPixelData = "";
|
||||
var y = iHeight;
|
||||
do {
|
||||
var iOffsetY = iWidth * (y - 1) * 4;
|
||||
var strPixelRow = "";
|
||||
for (var x = 0; x < iWidth; x++) {
|
||||
var iOffsetX = 4 * x;
|
||||
|
||||
strPixelRow += String.fromCharCode(aImgData[iOffsetY + iOffsetX + 2]);
|
||||
strPixelRow += String.fromCharCode(aImgData[iOffsetY + iOffsetX + 1]);
|
||||
strPixelRow += String.fromCharCode(aImgData[iOffsetY + iOffsetX]);
|
||||
}
|
||||
for (var c = 0; c < iPadding; c++) {
|
||||
strPixelRow += String.fromCharCode(0);
|
||||
}
|
||||
strPixelData += strPixelRow;
|
||||
} while (--y);
|
||||
|
||||
var strEncoded = encodeData(aHeader.concat(aInfoHeader)) + encodeData(strPixelData);
|
||||
|
||||
return strEncoded;
|
||||
}
|
||||
|
||||
|
||||
// sends the generated file to the client
|
||||
var saveFile = function (strData) {
|
||||
document.location.href = strData;
|
||||
}
|
||||
|
||||
var makeDataURI = function (strData, strMime) {
|
||||
return "data:" + strMime + ";base64," + strData;
|
||||
}
|
||||
|
||||
// generates a <img> object containing the imagedata
|
||||
var makeImageObject = function (strSource) {
|
||||
var oImgElement = document.createElement("img");
|
||||
oImgElement.src = strSource;
|
||||
return oImgElement;
|
||||
}
|
||||
|
||||
var scaleCanvas = function (oCanvas, iWidth, iHeight) {
|
||||
if (iWidth && iHeight) {
|
||||
var oSaveCanvas = document.createElement("canvas");
|
||||
oSaveCanvas.width = iWidth;
|
||||
oSaveCanvas.height = iHeight;
|
||||
oSaveCanvas.style.width = iWidth + "px";
|
||||
oSaveCanvas.style.height = iHeight + "px";
|
||||
|
||||
var oSaveCtx = oSaveCanvas.getContext("2d");
|
||||
|
||||
oSaveCtx.drawImage(oCanvas, 0, 0, oCanvas.width, oCanvas.height, 0, 0, iWidth, iHeight);
|
||||
return oSaveCanvas;
|
||||
}
|
||||
return oCanvas;
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
saveAsPNG: function (oCanvas, bReturnImg, iWidth, iHeight) {
|
||||
if (!bHasDataURL) {
|
||||
return false;
|
||||
}
|
||||
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
|
||||
var strData = oScaledCanvas.toDataURL("image/png");
|
||||
if (bReturnImg) {
|
||||
return makeImageObject(strData);
|
||||
} else {
|
||||
saveFile(strData.replace("image/png", strDownloadMime));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
saveAsJPEG: function (oCanvas, bReturnImg, iWidth, iHeight) {
|
||||
if (!bHasDataURL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
|
||||
var strMime = "image/jpeg";
|
||||
var strData = oScaledCanvas.toDataURL(strMime);
|
||||
|
||||
// check if browser actually supports jpeg by looking for the mime type in the data uri.
|
||||
// if not, return false
|
||||
if (strData.indexOf(strMime) != 5) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bReturnImg) {
|
||||
return makeImageObject(strData);
|
||||
} else {
|
||||
saveFile(strData.replace(strMime, strDownloadMime));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
saveAsBMP: function (oCanvas, bReturnImg, iWidth, iHeight) {
|
||||
if (!(bHasImageData && bHasBase64)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var oScaledCanvas = scaleCanvas(oCanvas, iWidth, iHeight);
|
||||
|
||||
var oData = readCanvasData(oScaledCanvas);
|
||||
var strImgData = createBMP(oData);
|
||||
if (bReturnImg) {
|
||||
return makeImageObject(makeDataURI(strImgData, "image/bmp"));
|
||||
} else {
|
||||
saveFile(makeDataURI(strImgData, strDownloadMime));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
})();
|
3718
public/js/html2canvas.min.js
vendored
Normal file
5
public/js/jquery-1.11.3.min.js
vendored
Normal file
BIN
src/.DS_Store
vendored
Normal file
47
src/App.vue
Normal file
@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<router-view />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
watch: {
|
||||
$route(to, from) {
|
||||
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
show: false,
|
||||
showData: 0,
|
||||
shown: false,
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.init();
|
||||
},
|
||||
methods: {
|
||||
init() {
|
||||
|
||||
},
|
||||
onRefresh() {
|
||||
location.reload();
|
||||
},
|
||||
getShareLink() {
|
||||
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<style>
|
||||
.van-pull-refresh__track {
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.van-toast {
|
||||
width: max-content !important;
|
||||
}
|
||||
</style>
|
14780
src/api/area.json
Normal file
11
src/api/common.js
Normal file
@ -0,0 +1,11 @@
|
||||
import http from '../utils/http';
|
||||
|
||||
const CommonAPI = {
|
||||
Post(name, data, index, size) {
|
||||
if (index)
|
||||
return http.post(`Common/${name}`, { data: data, PageIndex: index, PageSize: size });
|
||||
return http.post(`Common/${name}`, { data: data });
|
||||
},
|
||||
}
|
||||
|
||||
export default CommonAPI;
|
37
src/api/location.js
Normal file
@ -0,0 +1,37 @@
|
||||
export function getCurrentPosition() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (navigator.geolocation) {
|
||||
navigator.geolocation.getCurrentPosition(
|
||||
(position) => {
|
||||
resolve({
|
||||
latitude: position.coords.latitude,
|
||||
longitude: position.coords.longitude
|
||||
});
|
||||
},
|
||||
(error) => {
|
||||
reject(error);
|
||||
},
|
||||
{
|
||||
enableHighAccuracy: true,
|
||||
timeout: 5000,
|
||||
maximumAge: 0
|
||||
}
|
||||
);
|
||||
} else {
|
||||
reject(new Error('Geolocation is not supported'));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 获取城市代码
|
||||
export async function getCityCode() {
|
||||
try {
|
||||
const position = await getCurrentPosition();
|
||||
const url = `https://restapi.amap.com/v3/geocode/regeo?key=${AMAP_KEY}&location=${position.longitude},${position.latitude}`;
|
||||
const response = await axios.get(url);
|
||||
return response.data?.regeocode?.addressComponent?.citycode;
|
||||
} catch (error) {
|
||||
console.error('获取城市代码失败:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
17
src/api/member.js
Normal file
@ -0,0 +1,17 @@
|
||||
import http from '../utils/http'
|
||||
|
||||
const MemberAPI = {
|
||||
WXAuthorize(data) {
|
||||
return http.get('Wechat/Authorize', { path: data });
|
||||
},
|
||||
Login(data) {
|
||||
return http.get('Auth/Token', data);
|
||||
},
|
||||
Post(name, data, index, size) {
|
||||
if (index)
|
||||
return http.post(`Member/${name}`, { data: data, PageIndex: index, PageSize: size });
|
||||
return http.post(`Member/${name}`, { data: data });
|
||||
},
|
||||
}
|
||||
|
||||
export default MemberAPI;
|
21
src/api/pay.js
Normal file
@ -0,0 +1,21 @@
|
||||
import http from '../utils/http'
|
||||
|
||||
const PayAPI = {
|
||||
PayInfo(data) {
|
||||
return http.post('Member/PayInfo', { data: data });
|
||||
},
|
||||
WalletPay(data) {
|
||||
return http.post('Member/WalletPay', { data, data });
|
||||
},
|
||||
Wechat_JS(data) {
|
||||
return http.get('Pay/Wechat_JS', data);
|
||||
},
|
||||
AliPay_H5(data) {
|
||||
return http.get('Pay/AliPay_H5', data);
|
||||
},
|
||||
// Wechat_Mini(data) {
|
||||
// return http.get('Pay/Wechat_Mini', data);
|
||||
// },
|
||||
}
|
||||
|
||||
export default PayAPI;
|
288
src/main.js
Normal file
@ -0,0 +1,288 @@
|
||||
import $ from 'jquery';
|
||||
import { createApp, h, render } from "vue";
|
||||
import App from "./App.vue";
|
||||
import store from './store';
|
||||
// import { initPreload } from './api/amap';
|
||||
import { createRouter, createWebHashHistory } from "vue-router";
|
||||
import ElementPlus from 'element-plus'
|
||||
import 'element-plus/dist/index.css'
|
||||
|
||||
|
||||
// // 初始化预加载
|
||||
// initPreload().then(() => {
|
||||
// console.log('地区数据预加载完成');
|
||||
// }).catch(err => {
|
||||
// console.error('地区数据预加载失败:', err);
|
||||
// });
|
||||
import routes from "./router";
|
||||
import less from "less";
|
||||
import axios from 'axios';
|
||||
import "vue-fast-marquee/style.css";
|
||||
import Marquee from 'vue-fast-marquee';
|
||||
import VueQr from "vue-qr/src/packages/vue-qr.vue";
|
||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||
import {
|
||||
showToast,
|
||||
showLoadingToast,
|
||||
showSuccessToast,
|
||||
showFailToast,
|
||||
showNotify,
|
||||
showDialog,
|
||||
showConfirmDialog,
|
||||
showImagePreview,
|
||||
closeToast
|
||||
} from "vant";
|
||||
import "vant/es/notify/style";
|
||||
import "vant/es/dialog/style";
|
||||
import "vant/es/toast/style";
|
||||
import "vant/es/image-preview/style";
|
||||
|
||||
const app = createApp(App);
|
||||
app.config.globalProperties.$ = $;
|
||||
app.use(ElementPlus);
|
||||
app.component("VueQr", VueQr)
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
const router = createRouter({
|
||||
history: createWebHashHistory(),
|
||||
routes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
if (to.meta.cache && savedPosition)
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve(savedPosition);
|
||||
});
|
||||
else
|
||||
return { top: 0 };
|
||||
}
|
||||
});
|
||||
|
||||
app.use(router);
|
||||
|
||||
app.use(store);
|
||||
app.use(Marquee);
|
||||
const getStore = (e) => {
|
||||
return store.state[e];
|
||||
}
|
||||
app.config.globalProperties.$getStore = getStore;
|
||||
|
||||
app.config.globalProperties.$showDialog = showDialog;
|
||||
app.config.globalProperties.$showConfirmDialog = showConfirmDialog;
|
||||
app.config.globalProperties.$showNotify = showNotify;
|
||||
app.config.globalProperties.$showToast = showToast;
|
||||
app.config.globalProperties.$showLoadingToast = showLoadingToast;
|
||||
app.config.globalProperties.$showSuccessToast = showSuccessToast;
|
||||
app.config.globalProperties.$showFailToast = showFailToast;
|
||||
app.config.globalProperties.$closeToast = closeToast;
|
||||
app.config.globalProperties.$showImagePreview = showImagePreview;
|
||||
|
||||
app.config.globalProperties.$toMoney = (e, label) => {
|
||||
const num = parseFloat(e).toFixed(2);
|
||||
const [a, b] = num.split('.');
|
||||
return `${a}.<${label}>${b}</${label}>`;
|
||||
};
|
||||
|
||||
app.config.globalProperties.$autoToast = (val, msg, type = 'Fail', isThrow = true) => {
|
||||
if (val) {
|
||||
app.config.globalProperties[`$show${type}Toast`](msg);
|
||||
if (isThrow)
|
||||
throw msg;
|
||||
}
|
||||
};
|
||||
|
||||
let skeleton;
|
||||
app.config.globalProperties.$showSkeleton = () => {
|
||||
if (!skeleton)
|
||||
skeleton = h(BaseSkeleton);
|
||||
render(skeleton, document.body);
|
||||
document.body.appendChild(skeleton.el);
|
||||
};
|
||||
app.config.globalProperties.$closeSkeleton = () => {
|
||||
if (skeleton && document.body.contains(skeleton.el))
|
||||
document.body.removeChild(skeleton.el);
|
||||
};
|
||||
|
||||
app.config.globalProperties.$navigate = (e) => {
|
||||
if (window.__wxjs_environment === 'miniprogram') {
|
||||
const index = e.indexOf('?');
|
||||
let query = '';
|
||||
if (index > -1)
|
||||
query = e.slice(index);
|
||||
const data = router.resolve({ path: e });
|
||||
wx.miniProgram.navigateTo({
|
||||
url: `/pages/webview/webview?url=${encodeURIComponent(`${location.origin}/${data.href}${query}`)}`,
|
||||
});
|
||||
}
|
||||
else { router.push(e); }
|
||||
};
|
||||
app.config.globalProperties.$ls = {
|
||||
set: (e, obj) => {
|
||||
localStorage.setItem(e, obj);
|
||||
},
|
||||
get: (e) => {
|
||||
return localStorage.getItem(e);
|
||||
},
|
||||
remove: (e) => {
|
||||
localStorage.removeItem(e);
|
||||
}
|
||||
};
|
||||
app.config.globalProperties.$ss = {
|
||||
set: (e, obj) => {
|
||||
sessionStorage.setItem(e, obj);
|
||||
},
|
||||
get: (e) => {
|
||||
return sessionStorage.getItem(e);
|
||||
},
|
||||
remove: (e) => {
|
||||
sessionStorage.removeItem(e);
|
||||
}
|
||||
};
|
||||
|
||||
app.config.globalProperties.$conf = {
|
||||
apiUrl: import.meta.env.VITE_API_URL,
|
||||
ossUrl: import.meta.env.VITE_OSS_URL,
|
||||
};
|
||||
app.config.globalProperties.$unsigned = (e) => { return e > 0 ? e : 0 };
|
||||
app.config.globalProperties.$truncate = (e, p, a) => {
|
||||
return `${e.substring(0, p)}...${e.substring(e.length - a)}`;
|
||||
};
|
||||
app.config.globalProperties.$token = (e) => {
|
||||
const token = localStorage.getItem(e).split('.');
|
||||
return {
|
||||
header: JSON.parse(atob(token[0])),
|
||||
payload: JSON.parse(atob(token[1])),
|
||||
}
|
||||
};
|
||||
app.config.globalProperties.$file = (e) => {
|
||||
e = e || 'base/avatar.png';
|
||||
if (e.startsWith('http://') || e.startsWith('https://'))
|
||||
return e;
|
||||
else
|
||||
return import.meta.env.VITE_OSS_URL + e;
|
||||
};
|
||||
app.config.globalProperties.$openUrl = (e) => {
|
||||
window.open(e);
|
||||
};
|
||||
app.config.globalProperties.$refresh = () => { window.location.replace('#/refresh?key=' + app.config.globalProperties.$route.name) };
|
||||
app.config.globalProperties.$verify = (permissions, module, type) => {
|
||||
return permissions.indexOf(`${module}:${type}`) > -1;
|
||||
};
|
||||
app.config.globalProperties.$substring = (e, begin, end) => {
|
||||
if (typeof e !== 'string') {
|
||||
return '';
|
||||
}
|
||||
return e.length > end ? e.substring(begin, end) + "..." : e;
|
||||
}
|
||||
app.config.globalProperties.$fileSize = (e) => {
|
||||
let level = 0;
|
||||
while (e >= 1024 && level < 4) {
|
||||
e /= 1024;
|
||||
level++;
|
||||
}
|
||||
return `${e.toFixed(2)}${['B', 'KB', 'MB', 'GB'][level]}`;
|
||||
};
|
||||
app.config.globalProperties.$compressFiles = (files) => {
|
||||
const fileArray = Array.isArray(files) ? files : [files];
|
||||
|
||||
const promises = fileArray.map(file => {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!(file instanceof File)) {
|
||||
return reject(new Error('Invalid file type'));
|
||||
}
|
||||
imageConversion.compressAccurately(file, 400)
|
||||
.then(res => {
|
||||
res = new File([res], file.name, { type: res.type, lastModified: Date.now() });
|
||||
resolve(res);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('压缩失败', err);
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
};
|
||||
|
||||
app.config.globalProperties.$uploadFiles = (files) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const config = {
|
||||
headers: {
|
||||
'Content-Type': "multipart/form-data",
|
||||
'Member-Token': localStorage.getItem('member_token'),
|
||||
}
|
||||
};
|
||||
axios.post(`${import.meta.env.VITE_API_URL}File/MemberUpload`, files, config).then(data => {
|
||||
if (data?.data) {
|
||||
if (data.data?.errcode) {
|
||||
reject(data.data);
|
||||
}
|
||||
else {
|
||||
//上传成功
|
||||
resolve(data.data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
reject({ errmsg: '上传失败' });
|
||||
}
|
||||
}).catch(err => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
app.config.globalProperties.$distance = (e) => {
|
||||
if (e < 1)
|
||||
return `${e * 1000}m`;
|
||||
return `${e}km`;
|
||||
};
|
||||
app.config.globalProperties.$goIndex = () => {
|
||||
if (window.__wxjs_environment == 'miniprogram') {
|
||||
wx.miniProgram.reLaunch({
|
||||
url: `/pages/index/index`,
|
||||
});
|
||||
}
|
||||
else {
|
||||
location.replace('#/');
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 100);
|
||||
}
|
||||
}
|
||||
|
||||
app.config.globalProperties.$CheckStates = [{ label: '待审核', color: 'primary' }, { label: '已通过', color: 'success' }, { label: '已拒绝', color: 'danger' }];
|
||||
|
||||
// api
|
||||
import MemberAPI from './api/member';
|
||||
import CommonAPI from './api/common';
|
||||
import PayAPI from './api/pay';
|
||||
app.config.globalProperties.$MemberAPI = MemberAPI;
|
||||
app.config.globalProperties.$CommonAPI = CommonAPI;
|
||||
app.config.globalProperties.$PayAPI = PayAPI;
|
||||
|
||||
app.config.globalProperties.$isWechat = () => { return navigator.userAgent.toLowerCase().match(/MicroMessenger/i) == 'micromessenger' };
|
||||
app.config.globalProperties.$isWechatMini = () => { return window.__wxjs_environment == 'miniprogram' };
|
||||
app.config.globalProperties.$openLocation = (lon, lat, name = '', address = '') => {
|
||||
if (wx && app.config.globalProperties.$isWechat())
|
||||
wx.openLocation({
|
||||
longitude: lon,
|
||||
latitude: lat,
|
||||
name: name,
|
||||
address: address,
|
||||
scale: 18,
|
||||
});
|
||||
else
|
||||
window.open(`http://api.map.baidu.com/marker?location=${lat},${lon}&coord_type=gcj02&title=${name}&content=${address}&output=html`);
|
||||
};
|
||||
|
||||
app.config.globalProperties.$isLogin = () => {
|
||||
if (!localStorage.getItem('member_token'))
|
||||
return false;
|
||||
const token = app.config.globalProperties.$token('member_token');
|
||||
return token.header.exp > Date.now() && (window.__wxjs_environment != 'miniprogram' || localStorage.getItem('miniopenid'));
|
||||
}
|
||||
|
||||
app.config.globalProperties.$validPhone = (e) => {
|
||||
return /^1(3|4|5|6|7|8|9)\d{9}$/.test(e);
|
||||
}
|
||||
app.mount("#app");
|
111
src/router.js
Normal file
@ -0,0 +1,111 @@
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Index',
|
||||
component: () => import('./views/Index.vue'),
|
||||
children: [
|
||||
|
||||
],
|
||||
meta: { noLogin: true, }
|
||||
},
|
||||
{
|
||||
path: '/SyncAuth',
|
||||
name: 'SyncAuth',
|
||||
component: () => import('./views/SyncAuth.vue'),
|
||||
meta: {
|
||||
title: '同步认证',
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/Clear',
|
||||
name: 'Clear',
|
||||
component: () => import('./views/Clear.vue'),
|
||||
meta: {
|
||||
title: '清除缓存',
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/404',
|
||||
name: '404',
|
||||
component: () => import('./views/404.vue'),
|
||||
meta: {
|
||||
title: '404',
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/Layout',
|
||||
name: 'Layout',
|
||||
component: () => import('./views/Layout.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
},
|
||||
children: [
|
||||
{
|
||||
path: '/Home',
|
||||
name: 'Home',
|
||||
component: () => import('./views/Home.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/Business',
|
||||
name: 'Business',
|
||||
component: () => import('./views/Business.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/About',
|
||||
name: 'About',
|
||||
component: () => import('./views/About.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/News',
|
||||
name: 'News',
|
||||
component: () => import('./views/News.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/Detail',
|
||||
name: 'Detail',
|
||||
component: () => import('./views/Detail.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/Partners',
|
||||
name: 'Partners',
|
||||
component: () => import('./views/Partners.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/Contact',
|
||||
name: 'Contact',
|
||||
component: () => import('./views/Contact.vue'),
|
||||
meta: {
|
||||
noLogin: true,
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
path: '/:pathMatch(.*)',
|
||||
redirect: '/404'
|
||||
},
|
||||
|
||||
];
|
||||
|
||||
export default routes;
|
20
src/store/index.js
Normal file
@ -0,0 +1,20 @@
|
||||
// store.js
|
||||
import { createStore } from 'vuex';
|
||||
|
||||
const store = createStore({
|
||||
state: {
|
||||
imageSrc: null,
|
||||
},
|
||||
mutations: {
|
||||
setImageSrc(state, src) {
|
||||
state.imageSrc = src;
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
updateImageSrc({ commit }, src) {
|
||||
commit('setImageSrc', src);
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export default store;
|
36
src/utils/http.js
Normal file
@ -0,0 +1,36 @@
|
||||
import {request} from './request'
|
||||
const http = {
|
||||
get(url, params) {
|
||||
const config = {
|
||||
method: 'get',
|
||||
url: url
|
||||
}
|
||||
if (params) config.params = params
|
||||
return request(config)
|
||||
},
|
||||
post(url, params) {
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: url
|
||||
}
|
||||
if (params) config.data = params
|
||||
return request(config)
|
||||
},
|
||||
put(url, params) {
|
||||
const config = {
|
||||
method: 'put',
|
||||
url: url
|
||||
}
|
||||
if (params) config.params = params
|
||||
return request(config)
|
||||
},
|
||||
delete(url, params) {
|
||||
const config = {
|
||||
method: 'post',
|
||||
url: url
|
||||
}
|
||||
if (params) config.params = params
|
||||
return request(config)
|
||||
}
|
||||
}
|
||||
export default http
|
68
src/utils/request.js
Normal file
@ -0,0 +1,68 @@
|
||||
import axios from 'axios'
|
||||
|
||||
export function request(config) {
|
||||
const instance = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_URL,
|
||||
timeout: 60000,
|
||||
})
|
||||
instance.interceptors.request.use(config => {
|
||||
config.headers['Member-Token'] = localStorage.getItem('member_token') || '';
|
||||
config.headers['Content-Type'] = 'application/json';
|
||||
if (config.data) {
|
||||
config.data.ts = Date.now();
|
||||
} else {
|
||||
config.data = {
|
||||
data: {},
|
||||
ts: Date.now(),
|
||||
};
|
||||
}
|
||||
return config;
|
||||
}, error => {
|
||||
return Promise.error(error)
|
||||
}
|
||||
)
|
||||
instance.interceptors.response.use(rep => {
|
||||
if (rep.data.errcode) {
|
||||
if (rep.data.errcode == 41000) {
|
||||
localStorage.setItem('member_token', rep.data.access_token);
|
||||
return new Promise((resolve, reject) => {
|
||||
axios.request(rep.config).then(data => {
|
||||
if (data.data.errcode)
|
||||
reject(data.data);
|
||||
else
|
||||
resolve(data.data);
|
||||
}).catch(err => {
|
||||
if (err.isAxiosError) {
|
||||
switch (err.code) {
|
||||
case 'ERR_NETWORK': reject('服务器连接失败');
|
||||
case 'ECONNABORTED': reject('网络繁忙,请重试');
|
||||
default: reject(err.message);
|
||||
}
|
||||
}
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
else if ([41001, 40001, 40002].includes(rep.data.errcode)) {
|
||||
localStorage.removeItem('member_token');
|
||||
location.replace('#/Login');
|
||||
return Promise.reject({ errcode: rep.data.errcode, errmsg: '请先登录' });
|
||||
}
|
||||
else
|
||||
return Promise.reject(rep.data);
|
||||
}
|
||||
else
|
||||
return Promise.resolve(rep.data);
|
||||
}, error => {
|
||||
if (error.isAxiosError) {
|
||||
switch (error.code) {
|
||||
case 'ERR_NETWORK': return Promise.reject('服务器连接失败');
|
||||
case 'ECONNABORTED': return Promise.reject('网络繁忙,请重试');
|
||||
default: return Promise.reject(error.message);
|
||||
}
|
||||
}
|
||||
return Promise.reject(error)
|
||||
})
|
||||
return instance(config);
|
||||
}
|
||||
export default request
|
BIN
src/videos/test.mp4
Normal file
24
src/views/404.vue
Normal file
@ -0,0 +1,24 @@
|
||||
<template>
|
||||
<van-empty image="error" description="抱歉,该页面不存在" />
|
||||
<div class="b_l_w" style="display: flex; justify-content: center;">
|
||||
<van-button type="primary" @click="back">返回</van-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
back() {
|
||||
this.$router.back();
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
271
src/views/About.vue
Normal file
@ -0,0 +1,271 @@
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const culture = ref([
|
||||
{
|
||||
id: 1,
|
||||
img: '/images/culture-i1.png',
|
||||
num: '01',
|
||||
title: '企业使命',
|
||||
content: '让生活更美好',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
img: '/images/culture-i2.png',
|
||||
num: '02',
|
||||
title: '经营理念',
|
||||
content: '致诚、致勤、致善、致远',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
img: '/images/culture-i3.png',
|
||||
num: '03',
|
||||
title: '核心价值观',
|
||||
content: '共创、共享、共赢',
|
||||
brtext: '利他、感恩、有爱',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
img: '/images/culture-i4.png',
|
||||
num: '04',
|
||||
title: '企业宗旨',
|
||||
content: '科学创新、无私奉献',
|
||||
brtext: '服务社会、造福于民',
|
||||
},
|
||||
])
|
||||
|
||||
return {
|
||||
culture,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onlefticon() {
|
||||
const element = document.getElementById("certimgs");
|
||||
element.scrollLeft -= 333;
|
||||
console.log("element.scrollLeft");
|
||||
},
|
||||
onrighticon() {
|
||||
const element = document.getElementById("certimgs");
|
||||
element.scrollLeft += 333;
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="about">
|
||||
<div class="banner">
|
||||
<img src="/images/about-banner.png" alt="" style="width: 100%;">
|
||||
</div>
|
||||
|
||||
<div class="profile">
|
||||
<div class="pbox">
|
||||
<div class="fonts">
|
||||
<b class="big-ft">ABOUT</b>
|
||||
<span class="title-ft">
|
||||
企业
|
||||
<p class="red-title-ft">
|
||||
简介
|
||||
</p>
|
||||
</span>
|
||||
<span class="en-title-ft">
|
||||
COMPANY PROFILE
|
||||
</span>
|
||||
<span class="p1">
|
||||
<p>
|
||||
浙江好运徕品牌运营管理有限公司,座落于美丽的杭州市滨江区,是一家以互联网技术为核心,集科、工、贸于一体的综合性电商企业。业务范围涵盖软件系统开发、技术咨询、大数据服务、品牌运营管理、市场营销策划、产品供应链、线下实体商家拓客引流解决方案等领域。公司拥有国内领先的技术团队和一流的运营管理团队。本着“科学创新、无私奉献、服务社会、造福于民”的企业宗旨,和“共创、共享、共赢”的经营理念,以及“利他,感恩,有爱”的核心价值观。
|
||||
</p>
|
||||
<p>
|
||||
公司历时多年调研,倾力开发出一个全新的数字电商平台——<b>好运徕数字生活</b>。该平台拥有优越于传统电商平台的商业逻辑,能够很好地赋能百业实体,帮助商家进行数字化转型升级,解决当下全国实体商家所共同面临的“获客难”的痛点问题,继而帮助众多商家快速实现拓客增收。
|
||||
</p>
|
||||
<p>
|
||||
好运徕云平台的上线落地,可以加快全国乡村振兴步伐,带动再就业,拉动内循环,促进绿色消费,实现共同富裕,必将为繁荣我国实体经济注入新的活力!能够真正实现“为政府解忧,为百姓谋福利,为社会做贡献”的巨大社会价值意义!
|
||||
</p>
|
||||
</span>
|
||||
</div>
|
||||
<div class="imgs">
|
||||
<img src="/images/about-i1.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="videobox">
|
||||
<span class="b-font">
|
||||
COMPANY VIDEO
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
企业
|
||||
<p class="red-ft">
|
||||
视频
|
||||
</p>
|
||||
</span>
|
||||
<video src="/src/videos/test.mp4" controls loop="false" disablepictureinpicture controlslist="nodownload"
|
||||
style="width: 960px;border: solid 11px #000;border-radius: 6px;cursor: pointer;"></video>
|
||||
</div>
|
||||
|
||||
<div class="develop">
|
||||
<span class="b-font">
|
||||
DEVELOPMENT STRATEGY
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
发展
|
||||
<p class="red-ft">
|
||||
规划
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<div class="d-imgs">
|
||||
<img src="/images/develop-i1.png" alt="">
|
||||
<hr>
|
||||
<img src="/images/develop-i2.png" alt="">
|
||||
<hr>
|
||||
<img src="/images/develop-i3.png" alt="">
|
||||
</div>
|
||||
|
||||
<div class="d-fonts">
|
||||
<div class="ftbox">
|
||||
<b>数字电商板块布局</b>
|
||||
<span>
|
||||
依托数字电商平台,快速实现公司的三个宏伟目标:庞大的用户数据(超6亿的粉丝量);完善的渠道建设(全国每个城市都有服务商);平台及公司的品牌塑造。
|
||||
</span>
|
||||
</div>
|
||||
<div class="ftbox">
|
||||
<b>落地千城万店计划</b>
|
||||
<span>
|
||||
在全国每个城市都落地以大健康产业和民生产业为主的品牌连锁计划,惠及平台全国数亿会员的同时,还能帮我们的党和国家政府解决诸多社会问题。
|
||||
</span>
|
||||
</div>
|
||||
<div class="ftbox">
|
||||
<b>大力发展公益事业</b>
|
||||
<span>
|
||||
成立慈善基金会和自己品牌旗下的公益基金,在全国各地捐建养老社区和希望小学,以及其它惠民工程,打造最受人民欢迎和社会尊敬的民族企业。
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="botm">
|
||||
<div class="widbox">
|
||||
<div class="btm-ft">
|
||||
<span class="b-ft">2983</span>
|
||||
<span class="s-ft">运营中心</span>
|
||||
</div>
|
||||
<div class="btm-ft">
|
||||
<span class="b-ft">31W+</span>
|
||||
<span class="s-ft">全国推广大使</span>
|
||||
</div>
|
||||
<div class="btm-ft">
|
||||
<span class="b-ft">300W+</span>
|
||||
<span class="s-ft">优质商家入驻</span>
|
||||
</div>
|
||||
<div class="btm-ft">
|
||||
<span class="b-ft">3亿+</span>
|
||||
<span class="s-ft">粉丝用户</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="culture">
|
||||
<span class="b-font">
|
||||
CORPORATE CULTURE
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
企业
|
||||
<p class="red-ft">
|
||||
文化
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<div class="cul-imgs">
|
||||
<div class="cul-box" v-for="item in culture" :style="{ backgroundImage: 'url(' + item.img + ')' }">
|
||||
<span class="cul-num">
|
||||
{{ item.num }}
|
||||
</span>
|
||||
<hr>
|
||||
<p>
|
||||
{{ item.title }}
|
||||
</p>
|
||||
<span>
|
||||
{{ item.content }}
|
||||
<br>
|
||||
{{ item.brtext }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cul-btm">
|
||||
<img src="/images/cul-i5.png" alt="">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="certification">
|
||||
<span class="b-font">
|
||||
COMPANY QUALIFICATION
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
荣誉
|
||||
<p class="red-ft">
|
||||
资质
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<span class="cert-ft">
|
||||
公司先后被评为“品牌强国·品牌创新 100 强”、“品牌强国·新质生产力企业”、“电商行业领先品牌”、“品牌强国·绿色消费积分创新领军品牌”、
|
||||
“2024 新时代中国最佳商业模式创新企业”、“2024 新时代中国最具投资合作价值创业创富平台”、“CCTV 爱心慈善企业”、“AAA 级信用企业”等荣誉称号。
|
||||
董事长个人先后获得“品牌强国·新质生产力工匠先锋人物”、“2024 新时代中国经济模式十大创新人物”、“CCTV爱心慈善大使”等荣誉称号。
|
||||
</span>
|
||||
|
||||
<div class="certificate">
|
||||
<ArrowLeft class="arrow" @click="onlefticon" />
|
||||
<div class="certimgs" id="certimgs">
|
||||
<img src="/images/cert-i1.png" alt="">
|
||||
<img src="/images/cert-i2.png" alt="">
|
||||
<img src="/images/cert-i3.png" alt="">
|
||||
<img src="/images/cert-i4.png" alt="">
|
||||
<img src="/images/cert-i1.png" alt="">
|
||||
<img src="/images/cert-i2.png" alt="">
|
||||
<img src="/images/cert-i3.png" alt="">
|
||||
<img src="/images/cert-i4.png" alt="">
|
||||
</div>
|
||||
<ArrowRight class="arrow" @click="onrighticon" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="office">
|
||||
<span class="b-font">
|
||||
OFFICE ENVIRONMENT
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
办公
|
||||
<p class="red-ft">
|
||||
环境
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<div class="officeimgs">
|
||||
<img src="/images/office-i1.png" alt="">
|
||||
<div class="xbox">
|
||||
<img src="/images/office-i2.png" alt="">
|
||||
<div class="ybox">
|
||||
<img src="/images/office-i3.png" alt="">
|
||||
<img src="/images/office-i4.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
156
src/views/Business.vue
Normal file
@ -0,0 +1,156 @@
|
||||
<script>
|
||||
import { ref } from 'vue';
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const list = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: '软件系统开发',
|
||||
desc: '定制化软件开发,满足企业多样化需求,提升运营效率',
|
||||
img: '/images/list-i1.png',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: '技术咨询',
|
||||
desc: '提供专业的技术咨询服务,助力企业解决复杂技术难题',
|
||||
img: '/images/list-i2.png',
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: '大数据服务',
|
||||
desc: '通过大数据分析与应用,驱动企业决策与业务增长',
|
||||
img: '/images/list-i3.png',
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: '品牌运营管理',
|
||||
desc: '全方位品牌策划与管理,提升品牌价值与市场影响力',
|
||||
img: '/images/list-i4.png',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: '市场营销策划',
|
||||
desc: '定制化营销策略,帮助企业实现精准获客与业绩增长',
|
||||
img: '/images/list-i5.png',
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: '产品供应链',
|
||||
desc: '优化供应链管理,确保产品高效流通与成本控制',
|
||||
img: '/images/list-i6.png',
|
||||
},
|
||||
])
|
||||
return {
|
||||
list,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="business">
|
||||
<div class="banner">
|
||||
<img src="/images/business-banner.png" alt="">
|
||||
</div>
|
||||
|
||||
<div class="area">
|
||||
<span class="b-font">
|
||||
OPERATIONAL AREA
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
业务
|
||||
<p class="red-ft">
|
||||
领域
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<div class="list">
|
||||
<div class="lbox" v-for="item in list" :key="item.id">
|
||||
<img :src="item.img" alt="">
|
||||
<span class="l-b-font">{{ item.title }}</span>
|
||||
<span class="l-s-font">{{ item.desc }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="scheme">
|
||||
<div>
|
||||
<p>线下实体商家拓客引流解决方案</p>
|
||||
<hr>
|
||||
<span>
|
||||
商家通过让利活动吸引消费者消费并获得余额,余额激励再次消费,形成良性循环。这不仅提升了客户粘性,还促
|
||||
使消费者回流,为商家带来持续客流。同时,通过口碑传播吸引新客户,实现引流和品牌影响力的双重提升,最终达到商家与消费者的双赢。
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="commodel">
|
||||
<span class="b-font">
|
||||
COMMERCIAL MODEL
|
||||
</span>
|
||||
|
||||
<span class="black-ft">
|
||||
商业
|
||||
<p class="red-ft">
|
||||
模式
|
||||
</p>
|
||||
</span>
|
||||
|
||||
<span class="title">
|
||||
世界上最伟大的商业模式——
|
||||
<b>
|
||||
利他
|
||||
</b>
|
||||
</span>
|
||||
|
||||
<div class="details">
|
||||
<span>“利他”商业模式以共赢为核心,通过赋能商家、惠及消费者、成就创业者,构建了
|
||||
一个多方受益的商业生态,真正体现了“利他即利己”的核心理念。
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="example">
|
||||
<div class="ebox">
|
||||
<span>01</span>
|
||||
<hr>
|
||||
<b>联盟商家</b>
|
||||
<p>
|
||||
全国数千万实体商家免费入驻,赠送云拓客系统工具,赋能商家精准引流,快速增收!
|
||||
</p>
|
||||
<img src="/images/e-i1.png" alt="">
|
||||
</div>
|
||||
<hr style="width: 1px;height: 435px;background-color: #eaeaea;border: none;">
|
||||
<div class="ebox">
|
||||
<span>02</span>
|
||||
<hr>
|
||||
<b>创业者</b>
|
||||
<p>
|
||||
为创业者提供低门槛、高回报的创业机会,帮助其快速搭建财富通道。
|
||||
</p>
|
||||
<img src="/images/e-i2.png" alt="">
|
||||
</div>
|
||||
<hr style="width: 1px;height: 435px;background-color: #eaeaea;border: none;">
|
||||
<div class="ebox">
|
||||
<span>03</span>
|
||||
<hr>
|
||||
<b>消费者</b>
|
||||
<p>
|
||||
为全国十四亿消费者打造一个优质的消费
|
||||
渠道,实现自用省钱、分享赚钱。
|
||||
</p>
|
||||
<img src="/images/e-i3.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
22
src/views/Clear.vue
Normal file
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
setTimeout(() => {
|
||||
localStorage.clear();
|
||||
location.replace('#/');
|
||||
}, 0);
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|