first commit

This commit is contained in:
编码猿
2024-09-27 02:06:13 +08:00
commit 852d94fbb9
36760 changed files with 3274413 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
> 1%
last 2 versions

View File

@@ -0,0 +1,5 @@
[*.{js,jsx,ts,tsx,vue}]
indent_style = space
indent_size = 2
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -0,0 +1,17 @@
module.exports = {
root: true,
env: {
node: true
},
'extends': [
'plugin:vue/essential',
'@vue/standard'
],
rules: {
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
},
parserOptions: {
parser: 'babel-eslint'
}
}

View File

@@ -0,0 +1,24 @@
# shop 2222
## Project setup
```
npm install
```
### Compiles and hot-reloads for development
```
npm run serve
```
### Compiles and minifies for production
```
npm run build
```
### Lints and fixes files
```
npm run lint
```
### Customize configuration
See [Configuration Reference](https://cli.vuejs.org/config/).

View File

@@ -0,0 +1,5 @@
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,35 @@
{
"name": "shop",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"amfe-flexible": "^2.2.1",
"axios": "^0.19.0",
"core-js": "^3.4.3",
"jsonwebtoken": "^8.5.1",
"node-rsa": "^1.0.7",
"vant": "^2.2.15",
"vue": "^2.6.10",
"vue-router": "^3.1.3"
},
"devDependencies": {
"@vue/cli-plugin-babel": "^4.1.0",
"@vue/cli-plugin-eslint": "^4.1.0",
"@vue/cli-plugin-router": "^4.1.0",
"@vue/cli-service": "^4.1.0",
"@vue/eslint-config-standard": "^4.0.0",
"babel-eslint": "^10.0.3",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"postcss-pxtorem": "^4.0.1",
"style-resources-loader": "^1.3.2",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"vue-template-compiler": "^2.6.10"
}
}

View File

@@ -0,0 +1,11 @@
module.exports = {
plugins: {
'autoprefixer': {
overrideBrowserslist: ['Android >= 4.0', 'iOS >= 7', 'ie >= 8']
},
'postcss-pxtorem': {
rootValue: 37.5,
propList: ['*']
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 983 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 952 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 910 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 865 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<meta name="renderer" content="webkit">
<meta http-equiv="Cache-Control" content="no-siteapp" />
<meta name="screen-orientation" content="portrait">
<meta name="full-screen" content="yes">
<meta name="x5-fullscreen" content="true">
<meta name="browsermode" content="application">
<meta name="x5-page-mode" content="app">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta name="apple-touch-fullscreen" content="yes">
<title>shop</title>
</head>
<body>
<noscript>
<strong>We're sorry but shop doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -0,0 +1,42 @@
<template>
<div id="app">
<router-view />
<TabbarComponents v-if="showTabbar"></TabbarComponents>
</div>
</template>
<script>
import TabbarComponents from "@/components/Tabbar"
export default {
// 注意: 不要大量使用,会导致数据传递混乱
provide () {
return {
close: this.CloseTabbar,
open: this.OpenTabbar
}
},
data() {
return {
showTabbar: true
}
},
methods: {
CloseTabbar() {
this.showTabbar = false
},
OpenTabbar() {
this.showTabbar = true
}
},
components: {
TabbarComponents
}
}
</script>
<style lang="stylus">
.car .van-checkbox__label
width 100%
</style>

View File

@@ -0,0 +1,112 @@
import axios from 'axios'
import utils from '../utils'
import { Toast } from 'vant';
import rsa from '../utils/rsa';
class Axios {
constructor () {
axios.defaults.baseURL = utils.BaseApi()
this.RequestInterceptors()
this.ResponseInterceptors()
}
/**
* get接口的请求
* @param params
* {
* url: '请求地址',
* data: {
* 接口请求参数
* }
* }
* @returns {Promise<*>}
*/
async get (params = {}) {
return await axios.get(params.url, {
headers: {
data: params.data,
token: '2345323454435y'
}
})
}
/**
* post 接口的请求
* @param params
* {
* url: '请求地址',
* data: {
* 接口请求参数
* }
* }
* @param params
* @returns {Promise<*>}
*/
async post (params = {}) {
return await axios.post(params.url,{},{
headers: {
'data': rsa.PublicKeyEncryption(params.data),
'token': localStorage.getItem("token")
}
})
}
/**
* 添加请求拦截器
* @constructor
*/
RequestInterceptors() {
axios.interceptors.request.use(function (config) {
// ajax发送的时候显示加载进度
Toast.loading({
message: '加载中...',
forbidClick: true
});
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
}
/**
* 添加响应拦截器
* @constructor
*/
ResponseInterceptors() {
axios.interceptors.response.use(function (response) {
switch (response.data.status) {
case 200:
Toast.clear();
return rsa.PublicKeyDecryption(response.data.result);
break;
case 404:
Toast.fail(response.data.message);
break;
case 500:
// 当token失效的时候弹窗提醒用户在弹窗消失后清除本地旧的token
// 然后重定向到登录页面重新登录
Toast.fail({
message: response.data.message,
onClose: function () {
localStorage.removeItem("token")
location.href = "#/account"
}
});
break;
default:
break;
}
}, function (error) {
// 对响应错误做点什么
Toast.fail('wwwww'); // 给用户看
// 日志记录 稍后写
return Promise.reject(error);
});
}
}
export default new Axios();

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@@ -0,0 +1,3 @@
@import "tpl/color.styl"
@import "tpl/mixins.styl"
@import "tpl/clear.styl"

View File

@@ -0,0 +1,88 @@
//.account_title
// width 100%
// height 60px
// background #a4b0fc
// position relative
// margin-bottom 60px
// .status
// padding 0 23px
// height 40px
// background #fff
// text-align center
// line-height 40px
// color #a4b0fc
// position absolute
// bottom -20px
// transition all 0.9s
// font-size 16px
// z-index 9
// border-radius 2px
// box-shadow 1px 1px 5px #e1e1e1
.left
left 50px
.right
right 50px
.account_action
padding-top 80px
input
border none
border-bottom 1px solid #ebebeb
width 100%
font-size 18px
padding-bottom 5px
margin-bottom 25px
.van-button
width 100%
margin-top 10px
box-shadow: 0 0.12667rem 0.93333rem #e1e1e1;
&:before
border-color #fff
.van-button--default
color #fff
.tips
color #ababab
font-size 13px
.login
margin-top 60px
padding 0 20px
.color-item
width 35px
height 35px
border-radius 100%
box-shadow: 0 0.12667rem 0.93333rem #e1e1e1;
.van-grid
margin-top 30px
justify-content center
width 100%
bottom 20px
position fixed
.account
height 100%
position fixed
left 0
top 0
right 0
bottom 0
.backWhile
background #e0ecff
.account_welcome
width 80%
height 100%
margin 0 auto
display flex
flex-flow column
align-items center
justify-content center
p
font-size 13px
color #4b4b4b
margin-top 15px
span
color #9a99f6
img
width 95%
margin-left 45px
margin-bottom 20px

View File

@@ -0,0 +1,8 @@
.van-image {
width 32px;
}
.home
.home_banner
position: relative;
.type
margin-bottom 10px

View File

@@ -0,0 +1,77 @@
padding15(px = 15px)
padding px
border-bottom()
border-bottom 5px solid #f7f7f7
.info
.info_header
position relative
.header_action
display flex
justify-content space-between
padding 0 10px
box-sizing border-box
position fixed
left 0
width 100%
height 45px
top 0
z-index 9
align-items center
.info_message
padding15(15px)
border-bottom()
.title
font-size 21px
color #3c3c3c
margin-bottom 10px
.cont
color rgba(0,0,0,.54)
font-size 12.5px
line-height 18.75px
.price
margin-top 10px
color #ff6700
font-size 20px
.norms
padding 5px 15px
border-bottom()
display flex
justify-content space-between
height 40px
align-items center
font-size 13px
.quality
display flex
justify-content space-between
padding 0 10px
box-sizing border-box
height 40px
align-items center
border-bottom()
.left
line-height 15px
.item_1
float left
margin-right 10px
img
width 10px
height 10px
margin-right 5px
span
font-size 12px
color rgba(0,0,0,.54)
.van-icon
font-size 12px
.van-popup
img
width 10px
height 10px
margin-right 5px
p
border-bottom 0.02rem solid #d9d9d9
text-align center
font-size 16px
color rgba(0,0,0,.87)
padding 16px 0

View File

@@ -0,0 +1,39 @@
.header
width 100%
height 200px
background url("/img/me_back.png") no-repeat
background-position center center
background-size cover
position relative
.setting
position absolute
right 15px
top 20px
width 25px
height 25px
z-index 9
.user
display flex
align-items center
position absolute
bottom 40px
left 20px
img
width 55px
height 55px
p
margin-left 10px
font-size 18px
.type
img
width 35px
.setting
margin-top: 15px;
.van-cell
padding-top 15px
padding-bottom 15px
img
width 18px
height 20px
margin-right 10px

View File

@@ -0,0 +1,8 @@
.type, .content
height 100%
.type_list
position fixed
.lis
height: 100%;
overflow-y: scroll;

View File

@@ -0,0 +1,68 @@
html,body,#app
width 100%
height 95%
h1,h2,h3,h4,h5,h6,p,ul,li
margin 0
padding 0
list-style none
a
text-decoration none
img
width: 100%;
input
outline none
.content
margin-bottom: 50px;
.car .van-checkbox__icon
margin-left 10px
.account
#app
height 100%
.van-tab
span
font-size 18px
.list_item
text-align: center;
.item
margin-bottom 10px;
.title
font-size: 14px;
color #000
.info
color rgba(0,0,0,.54)
font-size 12px
margin-top 3.125px
.pice
color #ea625b
font-size 14px
margin-top: 5px;
.search_top
width: 100%;
display: flex
align-items center
justify-content space-between
background: #fff;
position: fixed;
z-index: 9;
left: 0;
top: 0;
.search_input
width 85%
img
width: 25px;
height: 16px;
margin 0 auto
.order
.van-key--gray
background #e0e0e0 !important

View File

@@ -0,0 +1,309 @@
// app
// app
$themeColor = red
$red50= #ffebee;
$red100= #ffcdd2;
$red200= #ef9a9a;
$red300= #e57373;
$red400= #ef5350;
$red500= #f44336;
$red600= #e53935;
$red700= #d32f2f;
$red800= #c62828;
$red900= #b71c1c;
$redA100= #ff8a80;
$redA200= #ff5252;
$redA400= #ff1744;
$redA700= #d50000;
$red= $red500;
$pink50= #fce4ec;
$pink100= #f8bbd0;
$pink200= #f48fb1;
$pink300= #f06292;
$pink400= #ec407a;
$pink500= #e91e63;
$pink600= #d81b60;
$pink700= #c2185b;
$pink800= #ad1457;
$pink900= #880e4f;
$pinkA100= #ff80ab;
$pinkA200= #ff4081;
$pinkA400= #f50057;
$pinkA700= #c51162;
$pink= $pink500;
$purple50= #f3e5f5;
$purple100= #e1bee7;
$purple200= #ce93d8;
$purple300= #ba68c8;
$purple400= #ab47bc;
$purple500= #9c27b0;
$purple600= #8e24aa;
$purple700= #7b1fa2;
$purple800= #6a1b9a;
$purple900= #4a148c;
$purpleA100= #ea80fc;
$purpleA200= #e040fb;
$purpleA400= #d500f9;
$purpleA700= #aa00ff;
$purple= $purple500;
$deepPurple50= #ede7f6;
$deepPurple100= #d1c4e9;
$deepPurple200= #b39ddb;
$deepPurple300= #9575cd;
$deepPurple400= #7e57c2;
$deepPurple500= #673ab7;
$deepPurple600= #5e35b1;
$deepPurple700= #512da8;
$deepPurple800= #4527a0;
$deepPurple900= #311b92;
$deepPurpleA100= #b388ff;
$deepPurpleA200= #7c4dff;
$deepPurpleA400= #651fff;
$deepPurpleA700= #6200ea;
$deepPurple= $deepPurple500;
$indigo50= #e8eaf6;
$indigo100= #c5cae9;
$indigo200= #9fa8da;
$indigo300= #7986cb;
$indigo400= #5c6bc0;
$indigo500= #3f51b5;
$indigo600= #3949ab;
$indigo700= #303f9f;
$indigo800= #283593;
$indigo900= #1a237e;
$indigoA100= #8c9eff;
$indigoA200= #536dfe;
$indigoA400= #3d5afe;
$indigoA700= #304ffe;
$indigo= $indigo500;
$blue50= #e3f2fd;
$blue100= #bbdefb;
$blue200= #90caf9;
$blue300= #64b5f6;
$blue400= #42a5f5;
$blue500= #2196f3;
$blue600= #1e88e5;
$blue700= #1976d2;
$blue800= #1565c0;
$blue900= #0d47a1;
$blueA100= #82b1ff;
$blueA200= #448aff;
$blueA400= #2979ff;
$blueA700= #2962ff;
$blue= $blue500;
$lightBlue50= #e1f5fe;
$lightBlue100= #b3e5fc;
$lightBlue200= #81d4fa;
$lightBlue300= #4fc3f7;
$lightBlue400= #29b6f6;
$lightBlue500= #03a9f4;
$lightBlue600= #039be5;
$lightBlue700= #0288d1;
$lightBlue800= #0277bd;
$lightBlue900= #01579b;
$lightBlueA100= #80d8ff;
$lightBlueA200= #40c4ff;
$lightBlueA400= #00b0ff;
$lightBlueA700= #0091ea;
$lightBlue= $lightBlue500;
$cyan50= #e0f7fa;
$cyan100= #b2ebf2;
$cyan200= #80deea;
$cyan300= #4dd0e1;
$cyan400= #26c6da;
$cyan500= #00bcd4;
$cyan600= #00acc1;
$cyan700= #0097a7;
$cyan800= #00838f;
$cyan900= #006064;
$cyanA100= #84ffff;
$cyanA200= #18ffff;
$cyanA400= #00e5ff;
$cyanA700= #00b8d4;
$cyan= $cyan500;
$teal50= #e0f2f1;
$teal100= #b2dfdb;
$teal200= #80cbc4;
$teal300= #4db6ac;
$teal400= #26a69a;
$teal500= #009688;
$teal600= #00897b;
$teal700= #00796b;
$teal800= #00695c;
$teal900= #004d40;
$tealA100= #a7ffeb;
$tealA200= #64ffda;
$tealA400= #1de9b6;
$tealA700= #00bfa5;
$teal= $teal500;
$green50= #e8f5e9;
$green100= #c8e6c9;
$green200= #a5d6a7;
$green300= #81c784;
$green400= #66bb6a;
$green500= #4caf50;
$green600= #43a047;
$green700= #388e3c;
$green800= #2e7d32;
$green900= #1b5e20;
$greenA100= #b9f6ca;
$greenA200= #69f0ae;
$greenA400= #00e676;
$greenA700= #00c853;
$green= $green500;
$lightGreen50= #f1f8e9;
$lightGreen100= #dcedc8;
$lightGreen200= #c5e1a5;
$lightGreen300= #aed581;
$lightGreen400= #9ccc65;
$lightGreen500= #8bc34a;
$lightGreen600= #7cb342;
$lightGreen700= #689f38;
$lightGreen800= #558b2f;
$lightGreen900= #33691e;
$lightGreenA100= #ccff90;
$lightGreenA200= #b2ff59;
$lightGreenA400= #76ff03;
$lightGreenA700= #64dd17;
$lightGreen= $lightGreen500;
$lime50= #f9fbe7;
$lime100= #f0f4c3;
$lime200= #e6ee9c;
$lime300= #dce775;
$lime400= #d4e157;
$lime500= #cddc39;
$lime600= #c0ca33;
$lime700= #afb42b;
$lime800= #9e9d24;
$lime900= #827717;
$limeA100= #f4ff81;
$limeA200= #eeff41;
$limeA400= #c6ff00;
$limeA700= #aeea00;
$lime= $lime500;
$yellow50= #fffde7;
$yellow100= #fff9c4;
$yellow200= #fff59d;
$yellow300= #fff176;
$yellow400= #ffee58;
$yellow500= #ffeb3b;
$yellow600= #fdd835;
$yellow700= #fbc02d;
$yellow800= #f9a825;
$yellow900= #f57f17;
$yellowA100= #ffff8d;
$yellowA200= #ffff00;
$yellowA400= #ffea00;
$yellowA700= #ffd600;
$yellow= $yellow500;
$amber50= #fff8e1;
$amber100= #ffecb3;
$amber200= #ffe082;
$amber300= #ffd54f;
$amber400= #ffca28;
$amber500= #ffc107;
$amber600= #ffb300;
$amber700= #ffa000;
$amber800= #ff8f00;
$amber900= #ff6f00;
$amberA100= #ffe57f;
$amberA200= #ffd740;
$amberA400= #ffc400;
$amberA700= #ffab00;
$amber= $amber500;
$orange50= #fff3e0;
$orange100= #ffe0b2;
$orange200= #ffcc80;
$orange300= #ffb74d;
$orange400= #ffa726;
$orange500= #ff9800;
$orange600= #fb8c00;
$orange700= #f57c00;
$orange800= #ef6c00;
$orange900= #e65100;
$orangeA100= #ffd180;
$orangeA200= #ffab40;
$orangeA400= #ff9100;
$orangeA700= #ff6d00;
$orange= $orange500;
$deepOrange50= #fbe9e7;
$deepOrange100= #ffccbc;
$deepOrange200= #ffab91;
$deepOrange300= #ff8a65;
$deepOrange400= #ff7043;
$deepOrange500= #ff5722;
$deepOrange600= #f4511e;
$deepOrange700= #e64a19;
$deepOrange800= #d84315;
$deepOrange900= #bf360c;
$deepOrangeA100= #ff9e80;
$deepOrangeA200= #ff6e40;
$deepOrangeA400= #ff3d00;
$deepOrangeA700= #dd2c00;
$deepOrange= $deepOrange500;
$brown50= #efebe9;
$brown100= #d7ccc8;
$brown200= #bcaaa4;
$brown300= #a1887f;
$brown400= #8d6e63;
$brown500= #795548;
$brown600= #6d4c41;
$brown700= #5d4037;
$brown800= #4e342e;
$brown900= #3e2723;
$brown= $brown500;
$blueGrey50= #eceff1;
$blueGrey100= #cfd8dc;
$blueGrey200= #b0bec5;
$blueGrey300= #90a4ae;
$blueGrey400= #78909c;
$blueGrey500= #607d8b;
$blueGrey600= #546e7a;
$blueGrey700= #455a64;
$blueGrey800= #37474f;
$blueGrey900= #263238;
$blueGrey= $blueGrey500;
$grey50= #fafafa;
$grey100= #f5f5f5;
$grey200= #eeeeee;
$grey300= #e0e0e0;
$grey400= #bdbdbd;
$grey500= #9e9e9e;
$grey600= #757575;
$grey700= #616161;
$grey800= #424242;
$grey900= #212121;
$grey= $grey500;
$black= #000000;
$white= #ffffff;
$transparent= rgba(0, 0, 0, 0);
$fullBlack= rgba(0, 0, 0, 1);
$darkBlack= rgba(0, 0, 0, 0.87);
$lightBlack= rgba(0, 0, 0, 0.54);
$minBlack= rgba(0, 0, 0, 0.26);
$faintBlack= rgba(0, 0, 0, 0.12);
$fullWhite= rgba(255, 255, 255, 1);
$darkWhite= rgba(255, 255, 255, 0.87);
$lightWhite= rgba(255, 255, 255, 0.54);

View File

@@ -0,0 +1,25 @@
// app
hairline(color = #eee)
&:before
content ''
position absolute
left 0
top 0
bottom auto
right auto
height 1px
width 100%
background-color color
display block
z-index 15
html.pixel-ratio-2 &
transform(scaleY(0.5))
html.pixel-ratio-3 &
transform(scaleY(0.33))
transform(t)
-webkit-transform t
transform t

View File

@@ -0,0 +1,40 @@
<template>
<van-nav-bar
:title="title"
:fixed="true"
:left-arrow="showLeft"
@click-left="onClickLeft">
<slot name="right-icon" slot="right"></slot>
</van-nav-bar>
</template>
<script>
export default {
props: {
// 导航栏的标题
title: {
type: String,
default: null
},
// 是否展示左侧返回键
showLeft: {
type: Boolean,
default: true
}
},
data() {
return {}
},
methods: {
onClickLeft() {
this.$router.back()
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,46 @@
<template>
<div class="order-card">
<div v-if="list.length == 0" class="no-order">
<van-icon size="40" color="#d1d1d1" name="balance-list-o" />
<p>没有订单</p>
</div>
<van-card
v-else
v-for="(item,index) in list"
:key="index"
:num="item.goods_num"
:price="item.goods_price"
:desc="item.wares_info"
:title="item.wares_title"
:thumb="item.wares_masterimg">
<div slot="footer">
<p>总计{{item.goods_totalprice}}</p>
</div>
</van-card>
</div>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: []
}
}
}
</script>
<style scoped lang="stylus">
.order-card
margin-top 10px
.no-order
text-align center
padding: 20px;
p
font-size 13px
color #d1d1d1
.van-card
background #fff
</style>

View File

@@ -0,0 +1,28 @@
<template>
<van-swipe class="home_swiper" :autoplay="3000" indicator-color="white">
<van-swipe-item v-for="(item,index) in list" :key="index">
<img :src="item.src || item"
alt="">
</van-swipe-item>
</van-swipe>
</template>
<script>
export default {
props: {
list: {
type: Array,
default: []
}
},
data() {
return {}
},
methods: {}
}
</script>
<style scoped lang="stylus">
.home_swiper
margin-top: 54px;
</style>

View File

@@ -0,0 +1,23 @@
<template>
<van-tabbar v-model="active" route>
<van-tabbar-item to="/" icon="wap-home-o">首页</van-tabbar-item>
<van-tabbar-item to="/type" icon="apps-o">分类</van-tabbar-item>
<van-tabbar-item to="/car" icon="shopping-cart-o">购物车</van-tabbar-item>
<van-tabbar-item to="/me" icon="friends-o">我的</van-tabbar-item>
</van-tabbar>
</template>
<script>
export default {
data() {
return {
active: 0
}
},
methods: {}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,32 @@
export default {
ajaxUrl: {
baseUrl: {
dev: 'http://127.0.0.1:9090',
prod: 'http://144.48.7.203:9090'
},
UrlList: {
buyOrder: '/order/buyOrder',
allOrder: '/order/allOrder',
submitCar: '/car/submitCar',
deteteCar: '/car/deleteCar',
updateCarNumber: '/car/updateCarNum',
getCarList: '/car/getCarList',
checkCar: '/car/checkCar',
addCar: '/car/addCar',
addLike: '/user/like',
search: '/home/search',
type: '/type/list',
list: '/home/activity',
index: '/home/index',
info: '/home/info',
add: '/user/add',
login: '/user/login',
}
},
rsa_public_key: `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC9eo8WIbWS5Yql06imlhrW0ZXh
faivPavdULvYLIxIKyUaOwMPFrPuHqqBNGnYOpiPHAKL+zxk2j4u+6jhB6VK1SOD
ccSLxIRxd0HmSDS+hBzYRf4vKc8BLlhMrYhnLmcxCc+PJIIa4DfCZnu8FfQlu/5L
ljjpYN9kHOpHAT+xpQIDAQAB
-----END PUBLIC KEY-----`
}

View File

@@ -0,0 +1,20 @@
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import 'amfe-flexible/index.js'
import Vant from 'vant'
import 'vant/lib/index.css'
import service from './service/imports'
Vue.use(Vant);
Vue.prototype.$http = new service()
Vue.config.productionTip = false
new Vue({
router,
render: h => h(App)
}).$mount('#app')

View File

@@ -0,0 +1,144 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'home',
component: getVuePath("Home"),
meta: {
title: '首页',
isUserLogin: false
}
},
{
path: '/list/:id',
name: 'list',
component: getVuePath("List"),
meta: {
title: '首页',
isUserLogin: false
}
},
{
path: '/search',
name: 'search',
component: getVuePath("Search"),
meta: {
title: '搜索',
isUserLogin: false
}
},
{
path: '/me',
name: 'me',
component: getVuePath("Me"),
meta: {
title: '我的',
isUserLogin: true
}
},
{
path: '/car',
name: 'car',
component: getVuePath("Car"),
meta: {
title: '购物车',
isUserLogin: true
}
},
{
path: '/type',
name: 'type',
component: getVuePath("Type"),
meta: {
title: '分类',
isUserLogin: false
}
},
{
path: '/info/:id',
name: 'info',
component: getVuePath("Info"),
meta: {
title: '详情',
isUserLogin: false
}
},
{
path: '/order',
name: 'order',
component: getVuePath("Order"),
meta: {
title: '订单',
isUserLogin: true
}
},
{
path: '/OrderStatus',
name: 'OrderStatus',
component: getVuePath("OrderStatus"),
meta: {
title: '订单状态',
isUserLogin: true
}
},
{
path: '/account',
name: 'account',
component: getVuePath("Account"),
meta: {
title: '登录 | 注册',
isUserLogin: false
},
beforeEnter: (to, from, next) => {
// 如果用户登录成功了.那么登录页面不应该被用户继续访问,所以使用
// 路由守卫 进行页面的访问拦截判断
if(localStorage.getItem("token") == null) {
next()
} else {
alert("您已登录过了,请勿重复登录")
router.push({
name: from.name
});
}
}
}
]
const router = new VueRouter({
routes
});
router.beforeEach((to, from, next) => {
// 设置标题
document.title = to.meta.title
if (to.meta.isUserLogin) {
// 未登录,重定向到登录页面
if (localStorage.getItem("token") == null) {
router.push({
name: 'account',
query: {
from: to.path
}
});
} else {
next()
}
} else {
next()
}
});
function getVuePath(fileName) {
return () => import(/* webpackChunkName: "[request]" */ `../views/${fileName}.vue`)
}
export default router

View File

@@ -0,0 +1,9 @@
import Axios from '../api'
import conf from '../config'
export default class BaseService {
constructor() {
this.api = Axios;
this.config = conf
}
}

View File

@@ -0,0 +1,45 @@
import BaseService from './BaseService'
export default class CarService extends BaseService {
async addCar(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.addCar,
data: data
})
}
async checkCar(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.checkCar,
data: data
})
}
async getCarList(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.getCarList,
data: data
})
}
async updateCarNumber(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.updateCarNumber,
data: data
})
}
async deteteCar(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.deteteCar,
data: data
})
}
async submitCar(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.submitCar,
data: data
})
}
}

View File

@@ -0,0 +1,35 @@
import BaseService from './BaseService'
export default class HomeService extends BaseService{
/**
* 获取首页数据
* @param data object
* @returns {Promise<*>}
*/
async getHomeData(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.index,
data: data
})
}
/**
* 获取详情页的数据
* @param {*} data
*/
async getInfoData(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.info,
data: data
})
}
async getListData(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.list,
data: data
})
}
}

View File

@@ -0,0 +1,18 @@
import BaseService from './BaseService'
export default class OrderService extends BaseService{
async allOrder(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.allOrder,
data: data
})
}
async buyOrder(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.buyOrder,
data: data
})
}
}

View File

@@ -0,0 +1,10 @@
import BaseService from './BaseService'
export default class SearchService extends BaseService{
async getSearchList(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.search,
data: data
})
}
}

View File

@@ -0,0 +1,10 @@
import BaseService from './BaseService'
export default class TypeService extends BaseService{
async getTypeList(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.type,
data: data
})
}
}

View File

@@ -0,0 +1,26 @@
import BaseService from './BaseService'
export default class UserService extends BaseService {
async UserAdd(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.add,
data: data
})
}
async UserLogin(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.login,
data: data
})
}
async addLike(data) {
return await this.api.post({
url: this.config.ajaxUrl.UrlList.addLike,
data: data
})
}
}

View File

@@ -0,0 +1,15 @@
import HomeService from './HomeService'
import UserService from './UserService'
import TypeService from './TypeService'
import SearchService from './SearchService'
import CarService from './CarService'
import OrderService from './OrderService'
export default class Imports {
homeService = new HomeService()
userService = new UserService()
typeService = new TypeService()
searchService = new SearchService()
carService = new CarService()
orderService = new OrderService()
}

View File

@@ -0,0 +1,18 @@
import config from "../config"
export default class Utils {
/**
* 根据当前所处的开发环境使用对应的ajax请求基地址
* @returns {string}
* @constructor
*/
static BaseApi () {
if(process.env.NODE_ENV === "development") {
return config.ajaxUrl.baseUrl.dev;
} else {
return config.ajaxUrl.baseUrl.prod;
}
}
}

View File

@@ -0,0 +1,20 @@
import NodeRsa from "node-rsa";
import config from "../config";
class RSA {
constructor () {
this.public_key = config.rsa_public_key
}
// 公钥加密
PublicKeyEncryption(text) {
return (new NodeRsa(this.public_key)).encrypt(JSON.stringify(text), 'base64')
}
// 公钥解密
PublicKeyDecryption(text) {
return JSON.parse((new NodeRsa(this.public_key)).decryptPublic(text, 'utf8'))
}
}
export default new RSA();

View File

@@ -0,0 +1,193 @@
<template>
<div :class="showPage ? 'account backWhile' : 'account' ">
<!--登录欢迎页面-->
<div class="account_welcome" v-if="showPage">
<img src="img/welcome_login.png" alt="">
<van-button
:round="true"
:style="{ background: currentTheme }"
@click="hiddenWelcome"
type="default">
</van-button>
<p>
还没有账号快来<span @click="nowAdd"> 注册</span>
</p>
</div>
<!--登录注册页面-->
<div v-else class="account_action">
<van-tabs
:line-height="7"
:line-width="30"
:border="false"
:color="textColor"
@change="changeAction"
:title-active-color="textColor"
v-model="AccountAction">
<van-tab title="登 录">
<!--登录页面-->
<div class="login">
<div class="username_input input">
<div class="tips">用户名</div>
<input v-model="UserInfo.name" :style="{ color: textColor}" type="text">
</div>
<div class="userpwd_input">
<div class="tips">密码</div>
<input v-model="UserInfo.pwd" :style="{ color: textColor}" type="password">
</div>
<van-button
:round="true"
@click="UserLogin"
:style="{ background: currentTheme }"
type="default"> </van-button>
</div>
</van-tab>
<van-tab title="注 册">
<!--注册页面-->
<div class="login">
<div class="username_input input">
<div class="tips">用户名</div>
<input v-model="UserInfo.name" :style="{ color: textColor}" type="text">
</div>
<div class="userpwd_input">
<div class="tips">手机号</div>
<input v-model="UserInfo.phone" :style="{ color: textColor}" type="text">
</div>
<div class="userpwd_input">
<div class="tips">密码</div>
<input v-model="UserInfo.pwd" :style="{ color: textColor}" type="password">
</div>
<van-button
:round="true"
:style="{ background: currentTheme }"
type="default" @click="addUser"> </van-button>
</div>
</van-tab>
</van-tabs>
<van-grid :border="false">
<van-grid-item
v-for="(item,index) in themeColor"
:key="index"
@click="changeTheme(item)">
<div class="color-item" :style="{ background: item.backgroundColor }"></div>
</van-grid-item>
</van-grid>
</div>
</div>
</template>
<script>
export default {
data() {
return {
UserInfo: {
name: "lb",
pwd: "1234567890",
phone: "15155145354"
},
showPage: true,
// 提示滑块移动号距离
left: 50,
// 默认显示第一个tabs
AccountAction: 0,
// 默认主题
currentTheme: 'linear-gradient(to right, #efe5f2 0%, #cd6cf2 100%)',
// 默认字体色
textColor: '#9a99f6',
// 默认标题
titleName: '登 录',
// 主题色
themeColor: [
{
textColor: '#9a99f6',
backgroundColor: 'linear-gradient(to right, #efe5f2 0%, #cd6cf2 100%)'
},
{
textColor: 'rgb(250, 108, 159)',
backgroundColor: 'linear-gradient(to right,#fa6c9f 0%,#ffe140 80%,#ffe140 100%)'
},
{
textColor: 'rgb(68, 234, 118)',
backgroundColor: 'linear-gradient(to right,#44ea76 0%,#39fad7 80%,#39fad7 100%)'
},
]
}
},
inject: ["close", "open"],
beforeRouteEnter(to, from, next) {
next(vm => vm.close())
},
beforeRouteLeave(to, from, next) {
this.open()
next()
},
methods: {
async UserLogin() {
if(this.UserInfo.name.length === 0
|| this.UserInfo.pwd.length === 0) {
this.$toast.fail('信息不完整,请检查');
} else {
console.log(this.$route.query.from)
var data = await this.$http.userService.UserLogin(this.UserInfo);
if(data !== undefined) {
this.$router.push({
path: '/'
});
localStorage.setItem("token", data.token)
}
}
},
// 注册用户
async addUser() {
if(this.UserInfo.name.length === 0
|| this.UserInfo.pwd.length === 0
|| this.UserInfo.phone.length === 0) {
this.$toast.fail('信息不完整,请检查');
} else {
var data = await this.$http.userService.UserAdd(this.UserInfo);
console.log(data)
this.$toast.success('注册成功请登录');
this.AccountAction = 0
}
},
hiddenWelcome() {
this.showPage = false
},
nowAdd() {
this.showPage = false
this.AccountAction = 1
},
changeTheme(item) {
this.textColor = item.textColor
this.currentTheme = item.backgroundColor
},
changeAction(index) {
if(index == 0) {
this.left = 50
this.titleName = "登 录"
} else {
this.left = 240
this.titleName = "注 册"
}
}
}
}
</script>
<style scoped lang="stylus">
@import "~!/account.styl"
</style>

View File

@@ -0,0 +1,203 @@
<template>
<div class="car">
<NavbarComponents title="购物车">
<span slot="right-icon" @click="EditCar">{{ showEdit ? '编辑' : '完成' }}</span>
</NavbarComponents>
<div class="content">
<van-checkbox-group v-if="carListData.length != 0" v-model="ChoiceCarList" ref="checkboxGroup">
<div class="car_item" v-for="(item,index) in carListData" :key="index">
<van-checkbox :name="item.car_id"></van-checkbox>
<van-card
:price="item.wares_nowprice"
:desc="item.wares_info.substring(0,10)+'..' "
:title="item.wares_title"
:thumb="item.wares_masterimg">
<p slot="num">x {{item.car_num}}</p>
<van-stepper slot="num"
@plus="updateCarNumber('plus',item.car_id,item.car_num)"
@minus="updateCarNumber('minus',item.car_id,item.car_num)"
v-model="item.car_num" />
</van-card>
</div>
</van-checkbox-group>
<div class="no-data" v-else>
<van-icon size="30" color="#d1d1d1" name="shopping-cart-o" />
<p>
购物车为空<router-link to="/"></router-link>
</p>
</div>
<van-submit-bar v-if="showEdit" :price="TotalMoney" button-text="买买买" @submit="submitOrder">
<p @click="checkAll">{{ isChoiceStatus ? '全选' : '取消' }}</p>
</van-submit-bar>
<van-submit-bar v-else button-text="删除" @submit="deleteShop">
<p @click="checkAll">{{ isChoiceStatus ? '全选' : '取消' }}</p>
</van-submit-bar>
</div>
</div>
</template>
<script>
import NavbarComponents from "@/components/Navbar";
export default {
data() {
return {
isChoiceStatus: true,
ChoiceCarList: [], // 购物车数据的id就是car_id
showEdit: true,
carListData: [],
submitOrderList: []
};
},
components: {
NavbarComponents
},
computed: {
TotalMoney:function () {
if(this.ChoiceCarList.length != 0) {
var price = 0, data = [];
this.carListData.forEach(val => {
if(this.ChoiceCarList.indexOf(val.car_id) != -1) {
data.push(val)
}
})
data.forEach(val => {
price += val.wares_nowprice * val.car_num
})
return price * 100
} else {
return 0
}
}
},
created() {
this.getCarList()
},
methods: {
// 提交购物车商品
async submitOrder() {
for(var i = this.carListData.length - 1; i >=0; i--) {
if(this.ChoiceCarList.indexOf(this.carListData[i].car_id) != -1) {
this.submitOrderList.push({
waresid: this.carListData[i].wares_id,
goodsnum: this.carListData[i].car_num,
goodsprice: this.carListData[i].wares_nowprice
})
}
}
let data = await this.$http.carService.submitCar({
carList: JSON.stringify(this.submitOrderList)
})
this.submitOrderList = []
this.deleteShop()
this.$router.push({ name: 'order'})
},
// 更新购物车需要购买的商品数量
async updateCarNumber(status, carid,nums) {
status == "plus" ? nums += 1 : nums -= 1
await this.$http.carService.updateCarNumber({
carid: carid,
quantity: nums
})
},
// 删除商品
async deleteShop() {
// ajax 删除后端数据库的数据
await this.$http.carService.deteteCar({
carid: JSON.stringify(this.ChoiceCarList)
})
// 从页面的数组中删除
for(var i = this.carListData.length - 1; i >=0; i--) {
if(this.ChoiceCarList.indexOf(this.carListData[i].car_id) != -1) {
var index = this.ChoiceCarList.indexOf(this.carListData[i].car_id)
this.ChoiceCarList.splice(index,1)
this.carListData.splice(i,1)
}
}
},
checkAll() {
if(this.isChoiceStatus) {
this.$refs.checkboxGroup.toggleAll(true);
this.isChoiceStatus = false
} else {
this.$refs.checkboxGroup.toggleAll();
this.isChoiceStatus = true
}
},
async getCarList() {
var carList = await this.$http.carService.getCarList({});
if (JSON.stringify(carList) == "{}") {
this.carListData = []
} else {
carList.forEach((val) => {
val.wares_masterimg = JSON.parse(val.wares_masterimg)[0]
val.checked = false
});
this.carListData = carList
}
},
EditCar() {
this.showEdit = !this.showEdit;
}
}
};
</script>
<style scoped lang="stylus">
.no-data
text-align center
padding-top 60px
p
font-size 13px
color #d1d1d1
margin-top 10px
a
color #ff7d7d
.content {
margin-top: 46px;
}
.van-checkbox {
margin: 10px 0;
}
.van-submit-bar {
bottom: 50px;
}
.van-card__num
p
float right
.van-stepper
clear both
margin-top 29px;
.van-submit-bar__bar
justify-content space-between
p
padding-left 20px
.car_item
display flex
.van-card
flex 1
background-color #fff
</style>

View File

@@ -0,0 +1,117 @@
<template>
<div class="home content">
<div class="home_banner">
<div class="search_top">
<img src="img/logo.png" alt="">
<van-search class="search_input"
@click="$router.push({ name: 'search' })"
show-action
:clearable="true"
placeholder="请输入搜索关键词"
shape="round"
v-model="value">
<div slot="action">搜索</div>
</van-search>
</div>
<SwiperComponents :list="swiperList"></SwiperComponents>
</div>
<van-grid class="type" clickable :column-num="4" :border="false">
<van-grid-item v-for="(item,index) in typeList"
:key="index"
:text="item.title"
:to="{ name: 'list', params: { id: item.id } }">
<van-image slot="icon" :src="item.src"/>
</van-grid-item>
</van-grid>
<van-row>
<van-col span="12">
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/32b5d24417b673008f386592c4d17046.jpg?thumb=1&w=358&h=508"
alt="">
</van-col>
<van-col span="12">
<van-row>
<van-col span="24">
<img
src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/1480d862e1f5a41e5adae8c030eef511.jpg?thumb=1&w=358&h=252"
alt="">
</van-col>
<van-col span="24">
<img
src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/1480d862e1f5a41e5adae8c030eef511.jpg?thumb=1&w=358&h=252"
alt="">
</van-col>
</van-row>
</van-col>
</van-row>
<van-row>
<van-col span="24">
<img src="https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/3ca39ff880dfbcbc0e45314782c39fff.jpg?thumb=1&w=720&h=280"
alt="">
</van-col>
</van-row>
<div class="list_item">
<van-row type="flex" justify="space-around" style="flex-wrap: wrap">
<van-col v-for="(i,index) in listData" class="item" span="11" :key=index>
<router-link :to="{ name: 'info', params: { id: i.wares_id } }">
<img :src="i | FirstImage" :alt="i.wares_title">
<h3 class="title">{{i.wares_title}}</h3>
<p class="info">{{ i.wares_info | LineText }}</p>
<p class="pice">1299</p>
</router-link>
</van-col>
</van-row>
</div>
</div>
</template>
<script>
import SwiperComponents from "@/components/Swiper"
export default {
data() {
return {
value: '',
listData: [],
typeList: [
{ id: 1, title: '限时白嫖', href: '/list', src: 'img/type_1.png' },
{ id: 2, title: '新品推荐', href: '/list', src: 'img/type_2.png' },
{ id: 3, title: '低价高配', href: '/list', src: 'img/type_3.png' },
{ id: 4, title: '超值特卖', href: '/list', src: 'img/type_4.png' }
],
swiperList: [
{ src: "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/f5008839c212fa55a475af26dca8e80f.jpg?thumb=1&w=720&h=360" },
{ src: "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/f5008839c212fa55a475af26dca8e80f.jpg?thumb=1&w=720&h=360" },
{ src: "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/f5008839c212fa55a475af26dca8e80f.jpg?thumb=1&w=720&h=360" },
{ src: "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/f5008839c212fa55a475af26dca8e80f.jpg?thumb=1&w=720&h=360" },
{ src: "https://cdn.cnbj1.fds.api.mi-img.com/mi-mall/f5008839c212fa55a475af26dca8e80f.jpg?thumb=1&w=720&h=360" }
]
}
},
filters: {
// 手机介绍太长,截短
LineText(text) {
return text.substring(0,10)+'..'
},
// 取出 wares_masterimg 主图第一张图片,作为缩略图
FirstImage(par) {
return JSON.parse(par.wares_masterimg)[0]
}
},
async created() {
// ajax封装基本案例
var data = await this.$http.homeService.getHomeData({});
this.listData = data
},
components: {
SwiperComponents
}
}
</script>
<style lang="stylus" scoped>
@import "~!/home.styl"
</style>

View File

@@ -0,0 +1,167 @@
<template>
<div class="info">
<div class="info_header">
<div class="header_action">
<van-icon size="25" name="arrow-left" @click="$router.back()" />
<van-icon size="25" name="shopping-cart-o" @click="$router.push({ name: 'car' })"/>
</div>
<SwiperComponents :list="InfoList.wares_masterimg | getArray"></SwiperComponents>
</div>
<div class="info_message">
<h2 class="title">{{InfoList.wares_title}}</h2>
<p class="cont">{{InfoList.wares_info}}</p>
<p class="price">
{{InfoList.wares_nowprice}}
</p>
</div>
<div class="norms" @click="isShow = !isShow">
<p class="status">已选</p>
<p class="conf">全网公开版碳纤黑6+128...</p>
<p class="right">
<span>x1</span>
<van-icon name="arrow" />
</p>
</div>
<div class="quality" @click="openQuality">
<div class="left">
<div class="item_1">
<img src="img/icon_1.png" alt />
<span>品质保障</span>
</div>
<div class="item_1">
<img src="img/icon_1.png" alt />
<span>顺丰发货</span>
</div>
<div class="item_1">
<img src="img/icon_1.png" alt />
<span>7天无理由退货</span>
</div>
</div>
<van-icon name="arrow" />
</div>
<van-popup v-model="showQuality" round closeable position="bottom" :style="{ height: '50%' }">
<p>服务说明</p>
<van-collapse :border="false" v-model="activeCollapse" accordion>
<van-collapse-item name="1">
<div slot="title">
<img src="img/icon_1.png" alt />
品质保障
</div>官方旗舰店品质保障提供最专业的服务
</van-collapse-item>
<van-collapse-item name="2">
<div slot="title">
<img src="img/icon_1.png" alt />
顺丰发货
</div>该商品顺丰发货顺丰无法到达的地区会安排其他转递其他快递
</van-collapse-item>
<van-collapse-item name="3">
<div slot="title">
<img src="img/icon_1.png" alt />
7天无理由退货
</div>自您的订单签收7个自然日之内在商品完好手机产品未激活的情况下可进行无理由退货
</van-collapse-item>
</van-collapse>
</van-popup>
<div class="info_img">
<img v-for="(item,index) in InfoList.wares_infoimg" :key="index" :src="item" alt />
</div>
<van-goods-action>
<van-goods-action-icon icon="star-o" text="收藏" @click="addLike" />
<van-goods-action-icon icon="cart-o" text="购物车" @click="$router.push({ name: 'car' })" />
<van-goods-action-button :disabled="closeAddShop" type="warning" text="加入购物车" @click="addCarShop" />
<van-goods-action-button type="danger" text="立即购买" @click />
</van-goods-action>
<!-- 商品规格的弹窗-->
<div class="sku"></div>
</div>
</template>
<script>
import SwiperComponents from "@/components/Swiper";
export default {
data() {
return {
closeAddShop: false,
id: this.$route.params.id,
showQuality: false,
InfoList: {},
active: 0,
isShow: false,
activeCollapse: ["1"]
};
},
inject: ["close", "open"],
beforeRouteEnter(to, from, next) {
next(vm => vm.close());
},
beforeRouteLeave(to, from, next) {
this.open();
next();
},
created() {
this.checkCarShop()
this.getInfoData();
},
methods: {
async checkCarShop() {
var checkCar = await this.$http.carService.checkCar({
waresid: this.id
});
this.closeAddShop = checkCar.isAddCar
},
async addCarShop() {
var car = await this.$http.carService.addCar({
waresid: this.id
});
this.closeAddShop = true
},
async addLike() {
var like = await this.$http.userService.addLike({
shopid: this.id
});
if (JSON.stringify(like) == "{}") {
this.$toast.success("收藏成功");
}
},
async getInfoData() {
var data = await this.$http.homeService.getInfoData({
id: this.id
});
console.log(data.wares_infoimg);
data.wares_infoimg = JSON.parse(data.wares_infoimg);
this.InfoList = data;
},
openQuality() {
this.showQuality = !this.showQuality;
}
},
filters: {
getArray(val) {
return val !== undefined ? JSON.parse(val) : [];
}
},
components: {
SwiperComponents
}
};
</script>
<style scoped lang="stylus">
@import '~!/info.styl';
.home_swiper {
margin-top: 0 !important;
}
</style>

View File

@@ -0,0 +1,80 @@
<template>
<div class="list">
<NavbarComponents :title="currentTitle"></NavbarComponents>
<div class="content">
<div class="list_item">
<van-row type="flex" style="flex-wrap: wrap">
<van-col v-for="(i,index) in listData" class="item" span="11" :key="index">
<router-link :to="{ name: 'info', params: { id: i.wares_id } }">
<img :src="i | FirstImage" :alt="i.wares_title" />
<h3 class="title">{{i.wares_title}}</h3>
<p class="info">{{ i.wares_info | LineText }}</p>
<p class="pice">{{ i.wares_nowprice}}</p>
</router-link>
</van-col>
</van-row>
</div>
</div>
</div>
</template>
<script>
import NavbarComponents from "@/components/Navbar";
export default {
data() {
return {
id: this.$route.params.id,
currentTitle: "",
listData: [],
typeList: [
{ id: 1, title: "限时白嫖" },
{ id: 2, title: "新品推荐" },
{ id: 3, title: "低价高配" },
{ id: 4, title: "超值特卖" }
]
};
},
inject: ["close", "open"],
beforeRouteEnter(to, from, next) {
next(vm => vm.close());
},
beforeRouteLeave(to, from, next) {
this.open();
next();
},
created() {
this.currentTitle = this.typeList[this.id - 1].title;
this.getListData();
},
methods: {
async getListData() {
var data = await this.$http.homeService.getListData({
id: this.id
});
console.log(data);
this.listData = data;
}
},
components: {
NavbarComponents
},
filters: {
// 手机介绍太长,截短
LineText(text) {
return text.substring(0, 10) + "..";
},
// 取出 wares_masterimg 主图第一张图片,作为缩略图
FirstImage(par) {
return JSON.parse(par.wares_masterimg)[0];
}
}
};
</script>
<style lang="stylus" scoped>
.van-row--flex
justify-content space-between
padding 12px
.content
margin-top 46px
</style>

View File

@@ -0,0 +1,57 @@
<template>
<div class="me">
<div class="header">
<img class="setting" src="img/me_settin_2.png" alt="">
<div class="user">
<img class="user_head" src="img/user_head.png" alt="">
<p>编码猿Code</p>
</div>
</div>
<van-grid class="type" clickable :column-num="5" :border="false" >
<router-link v-for="(item,index) in orderList" :key="index" :to="{ name: 'OrderStatus', query: { active: index } }">
<van-grid-item :text="item.title">
<img slot="icon" :src="item.img" />
</van-grid-item>
</router-link>
</van-grid>
<div class="setting">
<van-cell :clickable="true" :center="true" title="收货地址">
<img slot="icon" src="img/me_address.png" alt="">
</van-cell>
<van-cell :clickable="true" :center="true" title="我的收藏" icon="location-o" >
<img slot="icon" src="img/me_like.png" alt="">
</van-cell>
<van-cell :clickable="true" :center="true" title="我的设置" icon="location-o" >
<img slot="icon" src="img/me_settin_2.png" alt="">
</van-cell>
</div>
</div>
</template>
<script>
export default {
data() {
return {
orderList: [
{ title: '全部订单', img: 'img/me_1.png'},
{ title: '待付款', img: 'img/me_2.png'},
{ title: '待发货', img: 'img/me_3.png'},
{ title: '待收货', img: 'img/me_4.png'},
{ title: '退款/售后', img: 'img/me_5.png'},
]
}
},
methods: {}
}
</script>
<style scoped lang="stylus">
@import "~!/me"
.van-grid
justify-content space-around
</style>

View File

@@ -0,0 +1,342 @@
<template>
<div class="order">
<NavbarComponents title="订单结算"></NavbarComponents>
<div class="content">
<div class="wxpay-page" v-if="HiddedWxPage">
<div class="wxpay-page-dialog">
<div class="dialog-title">
<van-icon size="15" name="cross" @click="HiddedWxPage = false"/>
<span>请输入支付密码</span>
</div>
<div class="dialog-price">
<p class="price-title">付款给创想网络科技</p>
<p class="price-info">
<span class="info-1"></span>
<span class="info-2">{{TotalMoney / 100}}.00</span>
</p>
</div>
<div class="dialog-chooise">
<p>支付方式</p>
<div class="chooise-right">
<img src="img/wxPay/ye.png" alt="">
<span>零钱</span>
<van-icon size="15" name="arrow" />
</div>
</div>
<van-password-input
:value="PayPassword"
:focused="showKeyboard"
@focus="showKeyboard = true" />
</div>
<div class="wxpay-page-password">
<van-number-keyboard
:show="true"
@blur="show = false"
@input="onInput"
@delete="onDelete">
<template slot="delete">
<img class="delete" src="img/wxPay/jftc_18.jpg" alt="">
</template>
</van-number-keyboard>
</div>
</div>
<div class="order-page" v-else>
<!--地址选择-->
<div class="address">
<van-contact-card
:type="cardType"
:name="currentContact.name"
:tel="currentContact.tel"
add-text="请添加收货地址"
@click="showList = true"/>
<!--地址编辑添加弹窗-->
<van-popup closeable v-model="showList" :style="{ height : '100%' }" position="bottom">
<van-address-edit
:area-list="areaList"
show-delete
show-search-result
:search-result="searchResult"
:area-columns-placeholder="['请选择', '请选择', '请选择']"
@save="onSave"
@delete="onDelete"
/>
</van-popup>
</div>
<div class="order-list">
<!--代付款订单列表-->
<van-card
v-for="(item,index) in waitPayOrderList"
:num="item.goods_num"
:key="index"
:price="item.wares_nowprice"
:desc="item.wares_info"
:title="item.wares_title"
:thumb="item.wares_masterimg"/>
<van-cell-group>
<van-cell title="配送方式" value="顺丰配送货(免运费)" />
<van-cell title="发票类型" value="电子发票" />
<van-cell title="优惠券" value="无" />
</van-cell-group>
<van-cell-group title="支付方式">
<van-cell title="微信支付">
<template slot="icon">
<img src="img/pay_wx.png" alt="微信支付">
</template>
<template slot="right-icon">
<van-radio checked></van-radio>
</template>
</van-cell>
<van-cell title="支付宝支付">
<template slot="icon">
<img src="img/pay_zfb2.png" alt="支付宝支付">
</template>
<template slot="right-icon">
<van-radio disabled></van-radio>
</template>
</van-cell>
<van-cell title="花呗分期">
<template slot="icon">
<img src="img/pay_antinstalment.png" alt="花呗分期">
</template>
<template slot="right-icon">
<van-radio disabled></van-radio>
</template>
</van-cell>
<van-cell title="银联支付">
<template slot="icon">
<img src="img/pay_yl1.png" alt="银联支付">
</template>
<template slot="right-icon">
<van-radio disabled></van-radio>
</template>
</van-cell>
</van-cell-group>
</div>
<!--底部固定的付款按钮-->
<van-submit-bar
:price="TotalMoney"
button-text="去付款"
@submit="GoPlay"
/>
</div>
</div>
</div>
</template>
<script>
import NavbarComponents from "@/components/Navbar";
import areaList from "@/assets/js/area"
export default {
data() {
return {
areaList,
searchResult: [],
HiddedWxPage: false, // 控制微信支付页面是否显示
PayPassword: '', // 记录用户输入的密码
showKeyboard: true, // 控制密码输入框是否聚焦
waitPayOrderList: [], // 等待付款的订单数组
showList: false, // 是否展示地址编辑框
chosenContactId: null, // 记录当前是编辑还是添加的状态
list: []
}
},
created(){
this.getAllOrder()
},
methods: {
onSave(content) {
this.list.push(content)
this.showList = false
this.chosenContactId = content.id;
console.log("onSave content: ", content)
},
onDelete() {
Toast('delete');
},
GoPlay() {
this.HiddedWxPage = true
},
async onInput(key) {
this.PayPassword = (this.PayPassword + key).slice(0, 6);
// 输完密码,开始购买
if(this.PayPassword.length >= 6) {
console.log("购买成功");
var waitParams = [];
this.waitPayOrderList.forEach(val => {
waitParams.push(val.goods_id)
})
var data = await this.$http.orderService.buyOrder({
goodsid: JSON.stringify(waitParams)
})
this.$router.push({
name: 'OrderStatus'
})
} else {
console.log("正在输入密码");
}
},
onDelete() {
this.PayPassword = this.PayPassword.slice(0, this.PayPassword.length - 1);
},
async getAllOrder() {
let waitPayOrder = await this.$http.orderService.allOrder({
status: 0
});
if(waitPayOrder == undefined) {
this.$router.back()
} else {
waitPayOrder.forEach(val => {
val.wares_masterimg = JSON.parse(val.wares_masterimg)[0]
});
this.waitPayOrderList = waitPayOrder
}
}
},
computed: {
TotalMoney () {
var price = 0
this.waitPayOrderList.forEach(val=>{
price += val.goods_price * val.goods_num
})
return price * 100
},
cardType() {
return this.chosenContactId !== null ? 'edit' : 'add';
},
currentContact() {
const id = this.chosenContactId;
return id !== null ? this.list.filter(item => item.id === id)[0] : {};
}
},
inject: ["close", "open"],
beforeRouteEnter(to, from, next) {
next(vm => vm.close());
},
beforeRouteLeave(to, from, next) {
this.open();
next();
},
components: {
NavbarComponents
},
}
</script>
<style scoped lang="stylus">
.wxpay-page-dialog
width 330px
height 280px
position absolute
background #f8f8f8
left 50%
margin-left -165px
top 10%
padding: 0 10px;
box-sizing: border-box;
.dialog-title
display flex
align-items center
height 50px
position relative
.van-icon
position absolute
left 10px
color #aca6a8
span
font-size 14px
color #000
margin 0 auto
.dialog-price
margin-top 10px
text-align center
border-bottom: 1px solid #ececec;
padding-bottom: 15px;
.price-title
font-size 16px
margin-bottom 15px
color #000
.price-info
font-weight bolder
.info-1
vertical-align middle
font-size 17px
.dialog-chooise
display flex
justify-content space-between
height 45px
align-items center
padding 0 4px
p
font-size 14px
color #686169
.chooise-right
display: flex;
align-items: center;
img
width 20px
span
font-size 13px
margin-left 8px
margin-right 8px
.van-password-input
margin 5px 0 0 0
.wxpay-page
position fixed
width 100%
background #000000b3
z-index 9999
height 100%
top 0
left 0
right 0
bottom 0
.delete
width 40px
margin-top 15px
.content
margin-top 46px
.order-list
margin-top 20px
.van-card
background #fff
.van-cell
align-items center
img
width 30px
margin-right 10px
.van-submit-bar__bar
justify-content space-between
padding-left 20px
.van-submit-bar__text
text-align left
</style>

View File

@@ -0,0 +1,83 @@
<template>
<div class="orderstatus">
<NavbarComponents title="订单状态"></NavbarComponents>
<div class="content">
<van-tabs v-model="active" @click="changeTabs">
<van-tab title="全部订单">
<OrderCardComponents :list="OrderList"></OrderCardComponents>
</van-tab>
<van-tab title="待付款">
<OrderCardComponents :list="OrderList"></OrderCardComponents>
</van-tab>
<van-tab title="待发货">
<OrderCardComponents :list="OrderList"></OrderCardComponents>
</van-tab>
<van-tab title="待收货">
<OrderCardComponents :list="OrderList"></OrderCardComponents>
</van-tab>
<van-tab title="退款/售后">
<OrderCardComponents :list="OrderList"></OrderCardComponents>
</van-tab>
</van-tabs>
</div>
</div>
</template>
<script>
import NavbarComponents from "@/components/Navbar";
import OrderCardComponents from "@/components/OrderCard";
export default {
data() {
return {
OrderList: [],
active: this.$route.query.active == undefined ? 0 : Number(this.$route.query.active),
list: [
{ index: 0, key: -1 },
{ index: 1, key: 0 },
{ index: 2, key: 1 },
{ index: 3, key: 2 },
{ index: 4, key: 3 },
]
};
},
created() {
this.getOrderStatus(this.list[this.active].key)
},
methods: {
changeTabs(index, title) {
this.getOrderStatus(this.list[index].key)
},
async getOrderStatus(status) {
var data = await this.$http.orderService.allOrder({
status: status
});
console.log(data)
if (JSON.stringify(data) == "{}") {
this.OrderList = []
} else {
data.forEach(val => val.wares_masterimg = JSON.parse(val.wares_masterimg)[0])
this.OrderList = data
}
}
},
components: {
OrderCardComponents,
NavbarComponents
},
inject: ["close", "open"],
beforeRouteEnter(to, from, next) {
next(vm => vm.close());
},
beforeRouteLeave(to, from, next) {
this.open();
next();
},
};
</script>
<style lang="stylus" scoped>
.content
margin-top 46px
</style>

View File

@@ -0,0 +1,142 @@
<template>
<div class="search">
<div class="search_top">
<van-icon size="20" @click="$router.back()" name="arrow-left" />
<van-search
class="search_input"
show-action
@focus="InputFocus"
@blur="InputBlur"
:clearable="true"
placeholder="请输入搜索关键词"
shape="round"
v-model="SearchKeyword">
<div slot="action" @click="getSearch">搜索</div>
</van-search>
</div>
<div class="content">
<div class="search_tj" v-if="ShowHot">
<p>热门搜索</p>
<van-tag
plain
size="large"
v-for="(item,index) in tagList"
@click="HotClick(item)"
:key="index"
>{{item.text}}</van-tag>
</div>
<div class="list_item" v-else>
<van-row type="flex" style="flex-wrap: wrap">
<van-col v-for="(i,index) in searchList" class="item" span="11" :key="index">
<router-link :to="{ name: 'info', params: { id: i.wares_id } }">
<img :src="i | FirstImage" :alt="i.wares_title" />
<h3 class="title">{{i.wares_title}}</h3>
<p class="info">{{ i.wares_info | LineText }}</p>
<p class="pice">{{ i.wares_nowprice}}</p>
</router-link>
</van-col>
</van-row>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
ShowHot: true,
SearchKeyword: "",
searchList: [],
tagList: [
{ text: "小米" },
{ text: "华为" },
{ text: "16t" },
{ text: "11Pro" },
{ text: "锤子" },
{ text: "三星" }
]
};
},
watch: {
SearchKeyword (newVal, oldVal) {
if(newVal.length == 0) {
this.searchList = []
}
}
},
methods: {
InputBlur() {
if(this.searchList.length != 0) {
this.ShowHot = false
}
},
InputFocus() {
this.ShowHot = true
},
HotClick(data) {
this.SearchKeyword = "";
this.SearchKeyword = data.text;
this.getSearch();
},
async getSearch() {
var list = await this.$http.searchService.getSearchList({
keyword: this.SearchKeyword
});
this.ShowHot = false
this.searchList = list;
}
},
filters: {
// 手机介绍太长,截短
LineText(text) {
return text.substring(0, 10) + "..";
},
// 取出 wares_masterimg 主图第一张图片,作为缩略图
FirstImage(par) {
return JSON.parse(par.wares_masterimg)[0];
}
},
inject: ["close", "open"],
beforeRouteEnter(to, from, next) {
next(vm => vm.close());
},
beforeRouteLeave(to, from, next) {
this.open();
next();
}
};
</script>
<style lang="stylus" scoped>
.van-icon-arrow-left {
margin: 0 auto;
margin-left: 10px;
}
.search_top .search_input {
width: 93%;
}
.content {
margin-top: 46px;
}
.van-tag {
margin-right: 10px;
}
.search_tj {
padding: 10px;
padding-top: 26px;
p {
margin-bottom: 10px;
font-size: 18px;
}
}
</style>

View File

@@ -0,0 +1,101 @@
<template>
<div class="type">
<NavbarComponents title="分类" :show-left="false">
<van-icon slot="right-icon" @click="$router.push({ name: 'search' })" name="search"/>
</NavbarComponents>
<div class="content">
<van-tree-select
class="type_list"
height="85%"
@click-nav="changeNav"
:items="items"
:main-active-index.sync="activeIndex">
<template slot="content">
<div class="lis" v-for="(i,index) in items" v-show="activeIndex === index" :key="index">
<van-row type="flex" style="flex-wrap: wrap">
<van-col v-for="(it,ke) in i.content" span="11" :key="ke">
<router-link class="type_item" tag="div" :to="{ name: 'info', params: { id: it.wares_id } }">
<van-image :src="it.wares_masterimg"/>
<p>{{it.wares_title}}</p>
</router-link>
</van-col>
</van-row>
</div>
</template>
</van-tree-select>
</div>
</div>
</template>
<script>
import NavbarComponents from "@/components/Navbar"
export default {
data() {
return {
activeIndex: 0,
currentTypeName: '小米',
items: [
{ text: '小米', content: [] },
{ text: '魅族', content: [] },
{ text: '华为', content: [] },
{ text: 'iphone', content: [] },
{ text: '三星', content: [] },
{ text: '锤子', content: [] },
{ text: '诺基亚', content: [] },
]
}
},
created() {
this.getTypeList(0)
},
components: {
NavbarComponents
},
methods: {
async getTypeList(index) {
if (this.items[index].content.length == 0) {
var typeList = await this.$http.typeService.getTypeList({
typename: this.currentTypeName
});
this.items[index].content = typeList
}
},
onClickLeft() {
this.$router.back()
},
changeNav(index) {
this.currentTypeName = this.items[index].text
this.getTypeList(index)
}
}
}
</script>
<style lang="stylus" scoped>
@import "~!/type.styl"
.content {
margin-top 46px
}
.van-nav-bar .van-icon {
color: #a2a2a2;
}
.van-sidebar
width 20%
.van-sidebar,
.van-tree-select__content
flex none
.van-tree-select__content
width 80%
.type_item
text-align center
font-size 13px
color #000
margin-bottom 15px
.van-row--flex
justify-content space-between
padding 10px
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 512 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 735 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 496 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 KiB

View File

@@ -0,0 +1,54 @@
const path = require('path')
module.exports = {
publicPath: './',
lintOnSave: false,
productionSourceMap: false,
devServer: {
// proxy: {
// '/api': {
// target: 'https://api.jisuapi.com/weather',
// changeOrigin: true,
// ws: true,
// pathRewrite: {
// '^/api': ''
// }
// }
// },
port: 1314,
compress: true,
open: true
},
chainWebpack: config => {
// 去除 preload 和 prefetch减少页面请求次数
config.plugins.delete('preload')
config.plugins.delete('prefetch')
// 配置路径别名
config.resolve.alias
.set('@', resolve('src'))
.set('!', resolve('src/assets/styl/page'))
// 配置css的全局自动导入
const types = ['vue-modules', 'vue', 'normal-modules', 'normal']
types.forEach(type => addStyleResource(config.module.rule('stylus').oneOf(type)))
},
};
function addStyleResource (rule) {
rule.use('style-resource')
.loader('style-resources-loader')
.options({
patterns: [
path.resolve(__dirname, './src/assets/styl/imports.styl'),
],
})
}
function resolve (dir) {
return path.join(__dirname, dir)
}