Static Init

This commit is contained in:
chenhao 2026-06-03 11:55:13 +08:00
parent 28f100b54e
commit caac6a1004
67 changed files with 24347 additions and 2 deletions

View File

@ -1,2 +1,3 @@
# template-h5
# Pan.Template.H5
h5底版

45
index.html Normal file
View File

@ -0,0 +1,45 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<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>

2841
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

34
package.json Normal file
View 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"
}
}

140
public/css/common.less Normal file
View 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
View 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;
}

569
public/css/ly.less Normal file
View File

@ -0,0 +1,569 @@
@import 'gm.less';
@import 'common.less';
.cente {
.box;
.box-align-center;
}
.home {
.box;
.box-tb;
.box-align-center;
.b_l_w;
width: 1600px;
position: relative;
margin: 0 auto;
hr {
border: none;
width: 100%;
height: 2px;
background: #ebebeb;
margin-top: 31px;
z-index: 1;
margin-bottom: 34px;
}
>div {
.b_l_w;
}
.el-header {
padding: 0 120px;
}
.el-main {
padding: 0 120px;
}
.title {
.box;
.box-align-center;
height: 100px;
.t-title {
font-size: 24px;
font-weight: bold;
color: #fe4343;
line-height: 100px;
min-width: 104px;
margin-right: 29px;
}
.t-tabs {
margin-top: 10px;
font-size: 20px;
font-weight: normal;
line-height: 29px;
letter-spacing: 2px;
color: #2d2d2d;
margin-right: 300px;
.el-tabs__item.is-active,
.el-tabs__item:hover {
color: #fe4343;
}
.el-tabs__item {
height: 90px;
}
.el-tabs__active-bar {
background-color: #fe4343;
width: 30px;
height: 5px;
border-radius: 2.5px;
}
}
.search-box {
.r;
.box;
width: 500px;
.search {
.box;
.box-align-center;
width: 420px;
height: 42px;
padding: 13px 17px;
background-color: #f5f7f8;
border-radius: 8px 0px 0px 8px;
border: solid 1px #e7e7e7;
img {
width: 16px;
margin-right: 10px;
}
span {
min-width: 36px;
font-size: 16px;
color: #666666;
letter-spacing: 1.6px;
margin-right: 14px;
}
.van-icon {
font-size: 10px;
color: #666666;
margin-right: 15px;
}
input {
border: none;
outline: none;
background: none;
width: 300px;
height: 30px;
z-index: 1;
font-size: 16px;
color: #666666;
letter-spacing: 1.6px;
}
.option {
.box;
min-width: 100px;
}
.el-select__wrapper {
border: none;
background: none;
font-size: 16px;
line-height: 29px;
letter-spacing: 1.6px;
color: #666666;
box-shadow: none;
padding-left: 0px;
min-width: 100px;
border-right: 1px solid #ebebeb;
img {
width: 16px;
}
}
}
button {
width: 80px;
background-color: #fe4343;
border: none;
border-radius: 0px 8px 8px 0px;
.box;
.box-pack-center;
img {
width: 24px;
}
}
}
}
.f-title {
font-size: 24px;
font-weight: bold;
color: #2d2d2d;
line-height: 40px;
min-width: 104px;
margin-right: 32px;
}
.hotspot {
.box;
.box-align-center;
padding: 23px 0 17px 0;
.right {
.r;
.box;
.box-align-center;
height: 80px;
max-width: 950px;
overflow: hidden;
overflow-x: auto;
-ms-overflow-style: none;
scrollbar-width: none;
scroll-behavior: smooth;
.chosebox {
.box;
.c-tb {
.box;
.box-tb;
.c-title {
font-size: 16px;
letter-spacing: 1.6px;
}
.c-time {
font-size: 12px;
margin-top: 12px;
}
}
.c-lr {
.box;
.box-lr;
.box-align-center;
margin-left: 30px;
.c-countdown {
font-size: 24px;
font-weight: bold;
margin-right: 5px;
}
.c-day {
writing-mode: vertical-lr;
font-size: 12px;
}
}
}
.el-tabs__item.is-active,
.el-tabs__item:hover {
color: #fe4343 !important;
border: solid 1px #ffe6e6;
background-color: #fcf2f2;
}
.el-tabs__item {
padding: 0;
background-color: #ffffff;
border-radius: 5px;
margin-right: 18px;
border: solid 2px #f5f5f5;
height: 63px !important;
width: 175px !important;
color: #b1b1b1;
}
.el-tabs--bottom.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,
.el-tabs--bottom.el-tabs--card>.el-tabs__header .el-tabs__item:last-child,
.el-tabs--top.el-tabs--border-card>.el-tabs__header .el-tabs__item:last-child,
.el-tabs--top.el-tabs--card>.el-tabs__header .el-tabs__item:last-child {
padding: 0;
}
.el-tabs--card>.el-tabs__header .el-tabs__nav {
border: none;
}
.el-tabs--card>.el-tabs__header .el-tabs__item:first-child {
border: solid 2px #f5f5f5;
}
--el-border-color-light:none;
}
.arrow {
.box;
.box-align-center;
.text-center;
.box-pack-center;
width: 40px;
height: 40px;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15);
border-radius: 50%;
font-size: 22px;
margin-left: -50px;
margin-top: -10px;
z-index: 10;
background: #fff;
}
.leftarrow {
.r;
.box;
.box-align-center;
.text-center;
.box-pack-center;
width: 40px;
height: 40px;
box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.15);
border-radius: 50%;
font-size: 22px;
margin-right: -350px;
margin-top: -10px;
z-index: 10;
background: #fff;
}
}
.hp_img {
height: 380px;
margin-bottom: 61px;
.box;
>div {
img {
margin-bottom: 19px;
height: 180px;
}
}
img {
height: 380px;
margin-right: 22px;
}
}
.element {
.e-title {
.box;
.el-tabs__item {
background-color: #f6f7f9;
border-radius: 18px;
margin-right: 15px;
}
.el-tabs--card>.el-tabs__header .el-tabs__item {
border-left: none;
}
.el-tabs--card>.el-tabs__header .el-tabs__nav {
border: none;
}
.el-tabs__item.is-active,
.el-tabs__item:hover {
color: #fe4343;
background: #fee9e9;
}
--el-border-color-light:none;
}
.e_img {
.box;
margin-bottom: 60px;
.ex-box {
position: relative;
width: 250px;
height: 277px;
background-color: #f6f7f9;
border-radius: 10px 10px 0 0;
img {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
.base-box {
.box;
.box-pack-between;
.box-align-center;
padding: 0px 16px 0;
height: 43px;
width: 250px;
background-color: #eff1f4;
border-radius: 0 0 10px 10px;
span {
font-size: 14px;
font-weight: bold;
color: #2d2d2d;
}
.el-icon {
font-size: 10px;
color: #2d2d2d;
}
}
}
}
.liveimg {
.box;
width: 100%;
img {
border-radius: 10px;
}
.legend {
.box;
.box-pack-between;
.box-align-center;
padding: 0 16px;
margin-top: -46px;
width: 640px;
height: 46px;
background-color: #000000;
opacity: 0.5;
border-radius: 10px;
color: #ffffff;
font-size: 16px;
}
.l-leftbox {
margin-right: 20px;
}
.l-rightbox {
.box;
.box-lr;
.box-pack-between;
min-width: 720px;
min-height: 420px;
flex-wrap: wrap;
overflow: hidden;
img {
height: 200px;
margin: 0 20px 20px 0;
}
}
}
.fontimg {
.box;
.box-lr;
margin: 42px 0 60px 0;
min-width: 1380px;
flex-wrap: wrap;
>div {
.box;
.box-tb;
span {
font-size: 16px;
color: #2d2d2d;
margin: 0 0 32px 8px;
}
}
img {
width: 324px;
margin-right: 20px;
margin-bottom: 14px;
}
}
.mlist {
.box-lr;
.box-pack-between;
min-width: 1360px;
margin-top: 20px;
column-count: 6;
flex-flow: column wrap;
img {
width: 210px;
height: auto;
margin-bottom: 20px;
border-radius: 10px;
}
}
.end {
position: absolute;
bottom: -80px;
left: 750px;
font-size: 14px;
color: #999999;
line-height: 50px;
}
.el-dialog {
.box;
background-color: #ffffff;
border-radius: 30px;
padding: 40px 30px;
.el-dialog__header.show-close {
padding: 0;
}
.dialog {
.box;
.box-lr;
}
.more {
.box;
.box-tb;
width: 349px;
margin-left: 37px;
span {
font-size: 14px;
color: #444444;
margin-bottom: 10px;
margin-top: 7px;
}
button {
width: 340px;
height: 46px;
background-color: #fe4343;
border-radius: 10px;
border: none;
color: #ffffff;
margin-top: 10px;
}
hr {
margin: 27px 0 23px 0;
}
.tbox {
.box;
.box-tb;
}
.btmbox {
.box;
.box-tb;
.xbox {
.box;
.box-align-center;
margin-bottom: 15px;
}
span {
.box;
.box-align-center;
font-weight: bold;
color: #222222;
margin: 0 14px 0 0;
}
.imgbox {
.box;
.box-lr;
height: 310px;
overflow: hidden;
>div {
margin-right: 20px;
img {
width: 104px;
margin-bottom: 20px;
border-radius: 5px;
}
}
}
}
}
}
.el-overlay-dialog {
top: -50px;
}
}

BIN
public/images/all.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 484 B

BIN
public/images/car1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

BIN
public/images/car2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 550 KiB

BIN
public/images/e-i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
public/images/e-i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

BIN
public/images/e-i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

BIN
public/images/e-i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
public/images/e-i5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
public/images/f-i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
public/images/f-i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

BIN
public/images/f-i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
public/images/f-i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
public/images/f-i5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
public/images/f-i6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
public/images/f-i7.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
public/images/f-i8.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
public/images/hp-i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

BIN
public/images/hp-i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

BIN
public/images/hp-i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

BIN
public/images/hp-i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 179 KiB

BIN
public/images/hp-i5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

BIN
public/images/hp-i6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
public/images/i-i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

BIN
public/images/i-i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

BIN
public/images/i-i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

BIN
public/images/i-i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
public/images/i-i5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

BIN
public/images/i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 KiB

BIN
public/images/i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 956 B

BIN
public/images/i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 714 B

BIN
public/images/i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

BIN
public/images/l-i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 493 KiB

BIN
public/images/l-i2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

BIN
public/images/l-i3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

BIN
public/images/l-i4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

BIN
public/images/l-i5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

BIN
public/images/m-i1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
public/images/search.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 B

235
public/js/canvas2image.js Normal file
View 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

File diff suppressed because it is too large Load Diff

5
public/js/jquery-1.11.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

47
src/App.vue Normal file
View 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

File diff suppressed because it is too large Load Diff

11
src/api/common.js Normal file
View 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
View 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
View 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
View 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
View 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");

61
src/router.js Normal file
View File

@ -0,0 +1,61 @@
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: '/Home',
name: 'Home',
component: () => import('./views/Home.vue'),
meta: {
noLogin: true,
}
},
{
path: '/List',
name: 'List',
component: () => import('./views/List.vue'),
meta: {
noLogin: true,
}
},
{
path: '/:pathMatch(.*)',
redirect: '/404'
},
];
export default routes;

20
src/store/index.js Normal file
View 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
View 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
View 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

24
src/views/404.vue Normal file
View 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>

22
src/views/Clear.vue Normal file
View File

@ -0,0 +1,22 @@
<template>
</template>
<script>
export default {
mounted() {
setTimeout(() => {
localStorage.clear();
location.replace('#/');
}, 0);
},
data() {
return {
}
},
methods: {
}
}
</script>

535
src/views/Home.vue Normal file
View File

@ -0,0 +1,535 @@
<script>
import { ref } from 'vue';
export default {
setup() {
const active = ref(0);
const activeName = ref('first')
const eleactive = ref('first')
const tab_active = ref('first')
const liveactive = ref('first')
const value = ref('全部')
const options = ref([
{
value: 'Option1',
label: '全部',
},
{
value: 'Option2',
label: 'Option2',
},
{
value: 'Option3',
label: 'Option3',
},
{
value: 'Option4',
label: 'Option4',
},
{
value: 'Option5',
label: 'Option5',
},
])
const chosevalue = ref([
{
id: 1,
title: '腊八节',
time: '2025-01-07',
countdown: 1,
name: 'first',
},
{
id: 2,
title: '年货不打烊',
time: '2025-01-07',
countdown: 3,
name: 'second',
},
{
id: 3,
title: '乙巳蛇年',
time: '2025-01-07',
countdown: 3,
name: 'third',
},
{
id: 4,
title: '春节',
time: '2025-01-29',
countdown: 22,
name: 'fourth',
},
{
id: 5,
title: '开工大吉',
time: '2025-02-25',
countdown: 29,
name: 'fifth',
},
{
id: 6,
title: '开工大吉',
time: '2025-02-25',
countdown: 29,
name: 'sixth',
},
])
const elemt = ref([
{
id: 1,
title: '春节免抠',
name: 'first',
},
{
id: 2,
title: '特效',
name: 'second',
},
{
id: 3,
title: '中国风',
name: 'third',
},
{
id: 4,
title: '电商通用',
name: 'fourth',
},
{
id: 5,
title: '3D系列',
name: 'fifth',
},
{
id: 6,
title: '插画元素',
name: 'sixth',
},
{
id: 7,
title: '图标',
name: 'seventh',
},
{
id: 8,
title: '交通运输',
name: 'eighth',
},
{
id: 9,
title: '人物',
name: 'ninth',
},
])
const industry = ref([
{
id: 1,
title: '地产行业',
name: 'first',
},
{
id: 2,
title: '餐饮行业',
name: 'second',
},
{
id: 3,
title: '教育培训',
name: 'third',
},
{
id: 4,
title: '金融行业',
name: 'fourth',
},
{
id: 5,
title: '美妆护肤',
name: 'fifth',
},
{
id: 6,
title: '电商行业',
name: 'sixth',
},
{
id: 7,
title: '企业服务',
name: 'seventh',
},
{
id: 8,
title: '室内家居',
name: 'eighth',
},
{
id: 9,
title: '汽车服务',
name: 'ninth',
},
])
const live = ref([
{
id: 1,
title: '摄影照片',
name: 'first',
},
{
id: 2,
title: '实拍视频',
name: 'second',
},
])
const elemtimg = ref([
{
id: 1,
name: '边框',
img: '/images/e-i1.png',
},
{
id: 2,
name: '优惠券',
img: '/images/e-i2.png',
},
{
id: 3,
name: '金币红包',
img: '/images/e-i3.png',
},
{
id: 4,
name: '人物购物车',
img: '/images/e-i4.png',
},
{
id: 5,
name: '彩带',
img: '/images/e-i5.png',
},
])
const industryimg = ref([
{
id: 1,
name: '金融长图',
img: '/images/i-i1.png',
},
{
id: 2,
name: '金融科技海报',
img: '/images/i-i2.png',
},
{
id: 3,
name: '金融ppt',
img: '/images/i-i3.png',
},
{
id: 4,
name: '金融摄影',
img: '/images/i-i4.png',
},
{
id: 5,
name: '金融banner',
img: '/images/i-i5.png',
},
])
return {
active,
options,
value,
chosevalue,
activeName,
elemt,
elemtimg,
eleactive,
industry,
live,
industryimg,
liveactive,
tab_active,
};
},
methods: {
scrollRight() {
const element = document.getElementById("right");
element.scrollLeft -= 193;
console.log('click');
},
scrollLeft() {
const element = document.getElementById("right");
element.scrollLeft += 193;
console.log('click');
},
}
};
</script>
<template>
<div class="cente">
<div class="home">
<el-container>
<el-header>
<div class="title">
<span class="t-title">素材中心</span>
<el-tabs v-model="active" class="t-tabs" @tab-click="handleClick">
<el-tab-pane label="设计" name="first"></el-tab-pane>
<el-tab-pane label="图标" name="second"></el-tab-pane>
<el-tab-pane label="照片" name="third"></el-tab-pane>
<el-tab-pane label="PPT" name="fourth"></el-tab-pane>
<el-tab-pane label="字体" name="fifth"></el-tab-pane>
<el-tab-pane label="视频" name="sixth"></el-tab-pane>
</el-tabs>
<div class="search-box">
<div class="search">
<el-select v-model="value" style="width: 115px">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"
:disabled="item.disabled" />
<template #label="{ label }">
<div class="option">
<img src="/images/all.png" alt="">
<span>{{ label }}</span>
</div>
</template>
</el-select>
<input type="text" />
</div>
<button>
<img src="/images/search.png" alt="">
</button>
</div>
</div>
</el-header>
<hr>
<el-main>
<!-- 营销热点 -->
<div>
<div class="hotspot">
<span class="f-title">
营销热点
</span>
<div class="leftarrow" v-show="tab_active !== 'first'" id="myButton" @click="scrollRight">
<el-icon>
<ArrowLeft />
</el-icon>
</div>
<div class="right" ref="right" id="right">
<el-tabs v-model="tab_active" type="card" @tab-click="handleClick" v-for="list in chosevalue"
:key="list.id" scrollable="true">
<el-tab-pane :label="list.title" :name="list.name">
<template #label>
<div class="chosebox">
<div class="c-tb">
<span class="c-title">
{{ list.title }}
</span>
<span class="c-time">
{{ list.time }}
</span>
</div>
<div class="c-lr">
<span class="c-countdown">
{{ list.countdown }}
</span>
<span class="c-day">
天后
</span>
</div>
</div>
</template>
</el-tab-pane>
</el-tabs>
</div>
<div class="arrow" v-show="tab_active !== 'sixth'" @click="scrollLeft">
<el-icon>
<ArrowRight />
</el-icon>
</div>
</div>
<div class="hp_img">
<img src="/images/hp-i1.png" alt="">
<img src="/images/hp-i2.png" alt="">
<img src="/images/hp-i3.png" alt="">
<img src="/images/hp-i4.png" alt="">
<div>
<img src="/images/hp-i5.png" alt="">
<img src="/images/hp-i6.png" alt="">
</div>
</div>
</div>
<!-- 免抠元素 -->
<div>
<div class="element">
<div class="e-title">
<span class="f-title">
免抠元素
</span>
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick"
v-for="list in elemt" :key="list.id">
<el-tab-pane :label="list.title" :name="list.name"></el-tab-pane>
</el-tabs>
</div>
<div class="e_img">
<div v-for="list in elemtimg" :key="list.id" style="margin-right: 28px;">
<div class="ex-box">
<img :src="list.img" alt="">
</div>
<div class="base-box">
<span>{{ list.name }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</div>
</div>
</div>
</div>
</div>
<!-- 行业专区 -->
<div>
<div class="element">
<div class="e-title">
<span class="f-title">
行业专区
</span>
<el-tabs v-model="eleactive" type="card" class="demo-tabs" @tab-click="handleClick"
v-for="list in industry" :key="list.id">
<el-tab-pane :label="list.title" :name="list.name"></el-tab-pane>
</el-tabs>
</div>
<div class="e_img">
<div v-for="list in industryimg" :key="list.id" style="margin-right: 28px;">
<div class="ex-box">
<img :src="list.img" alt="">
</div>
<div class="base-box">
<span>{{ list.name }}</span>
<el-icon>
<ArrowRight />
</el-icon>
</div>
</div>
</div>
</div>
</div>
<!-- 实拍 -->
<div>
<div class="element">
<div class="e-title">
<span class="f-title">
实拍
</span>
<el-tabs v-model="liveactive" type="card" class="demo-tabs" @tab-click="handleClick"
v-for="list in live" :key="list.id">
<el-tab-pane :label="list.title" :name="list.name"></el-tab-pane>
</el-tabs>
</div>
</div>
<div class="liveimg">
<div class="l-leftbox">
<img src="/images/l-i1.png" alt="">
<div class="legend">
<span>新年</span>
<el-icon>
<ArrowRight />
</el-icon>
</div>
</div>
<div class="l-rightbox">
<img src="/images/l-i2.png" alt="">
<img src="/images/l-i3.png" alt="">
<img src="/images/l-i4.png" alt="">
<img src="/images/l-i5.png" alt="">
</div>
</div>
</div>
<!-- 字体 -->
<div>
<div class="element">
<div class="e-title">
<span class="f-title">
字体
</span>
</div>
</div>
<div class="fontimg">
<div>
<img src="/images/f-i1.png" alt="">
<span>毛笔</span>
</div>
<div>
<img src="/images/f-i2.png" alt="">
<span>硬笔书法</span>
</div>
<div>
<img src="/images/f-i3.png" alt="">
<span>电商海报</span>
</div>
<div>
<img src="/images/f-i4.png" alt="">
<span>卡通</span>
</div>
<div>
<img src="/images/f-i5.png" alt="">
<span>黑体</span>
</div>
<div>
<img src="/images/f-i6.png" alt="">
<span>宋体</span>
</div>
<div>
<img src="/images/f-i7.png" alt="">
<span>隶书</span>
</div>
<div>
<img src="/images/f-i8.png" alt="">
<span>创意</span>
</div>
</div>
</div>
<span class="end">
没有更多了
</span>
<el-backtop :right="100" :bottom="100" />
</el-main>
</el-container>
</div>
</div>
</template>

69
src/views/Index.vue Normal file
View File

@ -0,0 +1,69 @@
<template>
<router-view v-slot="{ Component }">
<keep-alive :include="cacheRoutes">
<component :is="Component" :key="$route.fullPath" @changeTabbar="changeActive" @updateCart="updateCart" />
</keep-alive>
</router-view>
<!-- <van-tabbar v-model="data.DefaultActive" placeholder @change="changeActive" active-color="#f53b32"
inactive-color="#666" fixed>
<van-tabbar-item v-for="(item, index) in data.Tabbars" :name="item.Name" :badge="getBadge(item)" :dot="item.Dot"
@click="refresh(item.Name)">
<span>{{ item.Label }}</span>
<template #icon="props">
<img :src="props.active ? item.Icon_Active : item.Icon_Inactive" />
</template>
</van-tabbar-item>
</van-tabbar> -->
<div>
</div>
</template>
<script>
export default {
name: 'Index',
mounted() {
this.init();
},
beforeRouteEnter() {
if (this)
this.updateCart();
},
computed: {
getBadge() {
return (e) => {
if (e.Name == 'Cart')
return this.cartQty || '';
return '';
}
}
},
data() {
return {
data: {},
sysConfig: {},
cartQty: 0,
cacheRoutes: this.$router.getRoutes().filter(x => x.meta.cache).map(x => x.name),
}
},
methods: {
init() {
},
refresh(e) {
if (e == this.data.DefaultActive)
location.reload();
},
changeActive(e) {
this.data.DefaultActive = e;
location.replace(`#/${e}`);
location.reload();
},
},
beforeRouteEnter(to, from, next) {
next(vm => {
vm.updateCart();
});
}
}
</script>

275
src/views/List.vue Normal file
View File

@ -0,0 +1,275 @@
<script>
import { ref } from 'vue';
export default {
setup() {
const active = ref(0);
const value = ref('全部')
const activeName = ref('first')
const formatactive = ref('first')
const dialogVisible = ref(false)
const options = ref([
{
value: 'Option1',
label: '全部',
},
{
value: 'Option2',
label: 'Option2',
},
{
value: 'Option3',
label: 'Option3',
},
{
value: 'Option4',
label: 'Option4',
},
{
value: 'Option5',
label: 'Option5',
},
])
const elemt = ref([
{
id: 1,
title: '海报',
name: 'first',
},
{
id: 2,
title: '展板',
name: 'second',
},
{
id: 3,
title: '公众号',
name: 'third',
},
{
id: 4,
title: '邀请函',
name: 'fourth',
},
{
id: 5,
title: '易拉宝',
name: 'fifth',
},
{
id: 6,
title: '宣传单',
name: 'sixth',
},
{
id: 7,
title: '画册',
name: 'seventh',
},
{
id: 8,
title: '包装',
name: 'eighth',
},
{
id: 9,
title: '名片',
name: 'ninth',
},
{
id: 10,
title: '样机',
name: 'tenth',
},
])
const format = ref([
{
id: 1,
title: '横版',
name: 'first',
},
{
id: 2,
title: '竖版',
name: 'second',
},
])
return {
active,
options,
value,
elemt,
activeName,
format,
formatactive,
dialogVisible,
};
},
};
</script>
<template>
<div class="cente">
<div class="home">
<el-container>
<el-header>
<div class="title">
<span class="t-title">素材中心</span>
<el-tabs v-model="active" class="t-tabs" @tab-click="handleClick">
<el-tab-pane label="设计" name="first"></el-tab-pane>
<el-tab-pane label="图标" name="second"></el-tab-pane>
<el-tab-pane label="照片" name="third"></el-tab-pane>
<el-tab-pane label="PPT" name="fourth"></el-tab-pane>
<el-tab-pane label="字体" name="fifth"></el-tab-pane>
<el-tab-pane label="视频" name="sixth"></el-tab-pane>
</el-tabs>
<div class="search-box">
<div class="search">
<el-select v-model="value" style="width: 115px">
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value"
:disabled="item.disabled" />
<template #label="{ label }">
<div class="option">
<img src="/images/all.png" alt="">
<span>{{ label }}</span>
</div>
</template>
</el-select>
<input type="text" />
</div>
<button>
<img src="/images/search.png" alt="">
</button>
</div>
</div>
</el-header>
<hr>
<el-main>
<div class="element">
<div class="e-title">
<span style="font-size:14px ;margin-right: 16px;color: #999999;line-height: 40px;">场景</span>
<el-tabs v-model="activeName" type="card" class="demo-tabs" @tab-click="handleClick" v-for="list in elemt"
:key="list.id">
<el-tab-pane :label="list.title" :name="list.name"></el-tab-pane>
</el-tabs>
</div>
<div class="e-title">
<span style="font-size:14px ;margin-right: 16px;color: #999999;line-height: 40px;">版式</span>
<el-tabs v-model="formatactive" type="card" class="demo-tabs" @tab-click="handleClick"
v-for="list in format" :key="list.id">
<el-tab-pane :label="list.title" :name="list.name"></el-tab-pane>
</el-tabs>
</div>
</div>
<div class="mlist">
<img class="item" src="/images/m-i1.png" alt="" @click="dialogVisible = true">
<img class="item" src="/images/hp-i5.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt=""><img src="/images/m-i1.png" alt=""
@click="dialogVisible = true">
<img class="item" src="/images/hp-i5.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt=""><img src="/images/m-i1.png" alt=""
@click="dialogVisible = true">
<img class="item" src="/images/hp-i5.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt=""><img src="/images/m-i1.png" alt=""
@click="dialogVisible = true">
<img class="item" src="/images/hp-i5.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt=""><img src="/images/m-i1.png" alt=""
@click="dialogVisible = true">
<img class="item" src="/images/hp-i5.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt=""><img src="/images/m-i1.png" alt=""
@click="dialogVisible = true">
<img class="item" src="/images/hp-i5.png" alt="">
<img class="item" src="/images/l-i2.png" alt="">
<img class="item" src="/images/l-i3.png" alt="">
<img class="item" src="/images/f-i1.png" alt="">
<img class="item" src="/images/hp-i2.png" alt="">
</div>
<el-dialog v-model="dialogVisible" width="1100px" :before-close="handleClose">
<div class="dialog">
<img src="/images/i1.png" alt="" style="height: 720px;">
<div class="more">
<img src="/images/i4.png" style="width: 22px;position: absolute;right: 32px;" alt="">
<div class="tbox">
<span>素材ID20037324</span>
<span>素材分类广告设计</span>
<span>颜色模式RGB</span>
<span>尺寸像素2953×6398px</span>
<span>文件大小50.9M</span>
<span style="display: flex;">文件格式 <img src="/images/i3.png" alt="" style="height: 20px;"></span>
<span>推荐软件Photoshop CC</span>
</div>
<button>立即下载</button>
<hr>
<div class="btmbox">
<div class="xbox">
<span>
更多相似素材
</span>
<el-icon>
<ArrowRight />
</el-icon>
</div>
<div class="imgbox">
<div>
<img src="/images/hp-i1.png" alt="">
<img src="/images/hp-i1.png" alt="">
</div>
<div>
<img src="/images/i2.png" alt="">
<img src="/images/hp-i1.png" alt="">
</div>
<div>
<img src="/images/hp-i1.png" alt="">
<img src="/images/hp-i1.png" alt="">
</div>
</div>
</div>
</div>
</div>
</el-dialog>
<span class="end">
没有更多了
</span>
<el-backtop :right="100" :bottom="100" />
</el-main>
</el-container>
</div>
</div>
</template>

28
src/views/SyncAuth.vue Normal file
View File

@ -0,0 +1,28 @@
<template>
</template>
<script>
export default {
mounted() {
if (this.token)
localStorage.setItem('member_token', this.token);
if (this.miniopenid)
localStorage.setItem('miniopenid', this.miniopenid);
if (this.target)
location.replace(`#/${this.target}`);
else
location.replace('#/');
},
data() {
return {
token: decodeURIComponent(this.$route.query.token || ''),
miniopenid: decodeURIComponent(this.$route.query.miniopenid || ''),
target: decodeURIComponent(this.$route.query.target || ''),
}
},
methods: {
}
}
</script>

43
tsconfig.json Normal file
View File

@ -0,0 +1,43 @@
{
"compilerOptions": {
"target": "esnext",
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"@/*": [
"src/*"
]
},
"types": [
"vite/client",
"node"
],
"lib": [
"esnext",
"dom",
"dom.iterable",
"scripthost"
],
"resolveJsonModule": true,
"allowJs": true
},
"include": [
"src/**/*.ts",
"src/**/*.d.ts",
"src/**/*.tsx",
"src/**/*.vue",
"src/**/*.js",
"src/**/*.json",
"public/js/canvas2image.js"
],
"exclude": [
"node_modules",
"dist"
]
}

41
vite.config.js Normal file
View File

@ -0,0 +1,41 @@
import vue from "@vitejs/plugin-vue";
import Components from "unplugin-vue-components/vite";
import { VantResolver } from "@vant/auto-import-resolver";
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default {
server: {
host: '0.0.0.0',
port: 9992,
// 是否开启 https
https: false,
},
plugins: [
vue(),
Components({
resolvers: [VantResolver()],
}),
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
css: {
postcss: {
plugins: [
// require('postcss-px-to-viewport')({
// viewportWidth: 375, // 设计稿的宽度
// unitPrecision: 5,
// viewportUnit: 'vw',
// selectorBlackList: ['ignore', 'tab-bar'],
// minPixelValue: 1,
// mediaQuery: false
// })
]
}
}
};