This commit is contained in:
LittleBoy 2021-01-04 13:40:02 +08:00
parent caa654ec65
commit 94c90d729d
15 changed files with 501 additions and 111 deletions

View File

@ -5,9 +5,13 @@
<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">
<title>user-demo</title>
<title>在线商城</title>
</head>
<body>
<form action="http://localhost:18080" method="post" enctype="multipart/form-data">
<input type="file" name="pic">
<button type="submit">GO</button>
</form>
<noscript>
<strong>We're sorry but user-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>

View File

@ -7,6 +7,7 @@
<style lang="less">
#app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
font-size: 14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;

View File

@ -1,10 +1,10 @@
<template>
<div>
<div id="app-content" style="padding-bottom:50px;">
<!-- <keep-alive>-->
<keep-alive>
<!-- 缓存加载过的界面 -->
<router-view />
<!-- </keep-alive>-->
</keep-alive>
</div>
<van-tabbar v-model="active">
<van-tabbar-item name="home" replace to="/" icon="home-o">首页</van-tabbar-item>
@ -40,4 +40,4 @@ export default {
// }
}
}
</script>
</script>

View File

@ -13,7 +13,7 @@
<div class="p-price">¥ <strong>{{g.sell_price}}</strong></div>
<div class="p-ext">
<span class="d-num">
<span class="font-num" v-text="g.sell_count"></span>人购买
<span class="font-num">{{g.sell_count | nft}}</span>人购买
</span>
<!-- <span class="d-area">杭州</span> -->
</div>
@ -59,7 +59,7 @@ export default {
.list-item{
width: 50%;
float:left;
&:nth-child(2n){
.goods-item{
margin-right:0px;

View File

@ -0,0 +1,43 @@
<template>
<GoodsList :goodsList="dataList" />
</template>
<script>
import http from "../components/http";
import GoodsList from "./GoodsList";
export default {
name: "HotGoods",
components: {GoodsList},
props: {
size: {
default: 10
}
},
data() {
return {
pageSize: 10,
page:1,
dataList:[]
}
},
mounted() {
this.pageSize = this.size;
this.load()
},
methods: {
load(page = 1) {
http.shop.get("/goods?list=y&page=" + page)
.then(data => {
this.dataList = data.list;
})
.catch(() => {
this.loading = false;
});
}
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,58 @@
<template>
<van-overlay :show="show" @click="onclick">
<div class="wrapper">
<div class="text-center block">
<van-loading />
<div class="text">{{loadingText}}</div>
</div>
</div>
</van-overlay>
</template>
<style scoped>
.wrapper {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
}
.block{
color:#fff;
}
</style>
<script>
export default {
name: "PageLoading",
props:{
show:{
require:true,
type:Boolean
},
loadingText:{
type:String,default:'加载中...'
},
hideOnClick:{
type:Boolean,
default:false
}
},
data(){
return {
showLoading:false
}
},
mounted(){
this.showLoading = this.show;
},
methods:{
onclick(){
if(this.hideOnClick){
this.show = false;
}
}
}
}
</script>
<style scoped>
</style>

View File

@ -1,7 +1,7 @@
import qs from 'qs';
// import { async } from 'q';
const baseUri = "http://127.0.0.1:8080/api";
const baseUri = "http://127.0.0.1:8000";
const processResponse = (promise) => {
return new Promise((resolve, reject) => {
promise.then(ret => {
@ -17,18 +17,39 @@ const processResponse = (promise) => {
})
})
}
class Api {
constructor(baseUri) {
this.baseUri = baseUri;
}
$getUrl(url) {
return this.baseUri + url;
}
async get(url) {
buildToken(data) {
if(!data) data= {};
if (!data['token']) {
let token = localStorage.getItem('gg_user_token');
if (token) {
data['token'] = token;
}
}
return data;
}
async get(url, data = null) {
data = this.buildToken(data)
if (data) {
url += url.indexOf('?') == -1 ? '?' : '&'
url += qs.stringify(data);
}
const resp = await fetch(this.$getUrl(url));
return processResponse(resp.json());
}
async post(url, data) {
data = this.buildToken(data)
const resp = await fetch(this.$getUrl(url), {
body: qs.stringify(data),
method: 'post',
@ -39,8 +60,9 @@ class Api {
return processResponse(resp.json());
}
}
const http = new Api(baseUri);
export default {
http,
shop:new Api('https://fj-server.os.wm-app.xyz/shop/api')
};
shop: new Api(baseUri)
};

View File

@ -5,13 +5,28 @@ import router from './router'
import Vant from 'vant';
import 'vant/lib/index.css';
import './style.less';
import { Lazyload } from 'vant';
import {Lazyload} from 'vant';
Vue.config.productionTip = false
Vue.use(Vant);
Vue.use(Lazyload);
Vue.filter('nft', function (value) {
if (!value) return '';
value = parseInt(value);
if (value >= 10000) {
value = (value / 10000).toFixed(2).toString();
let di = value.lastIndexOf('.'),
f = value.substr(di + 1);
value = value.substr(0, di);
if (parseInt(f) != 0) {
value += '.' + f.replace(/0+$/g,'');
}
return value + '万';
}
return value;
// return value.toString().replace(/(\d{1,3})(?=(\d{3})+(?:$|\.))/g,'$1,');
})
new Vue({
router,
render: h => h(App)
router,
render: h => h(App)
}).$mount('#app')

View File

@ -30,8 +30,8 @@ const router = new Router({
},
{
path: '/my',
name: 'Orders',
component: () => import( /* webpackChunkName: "Orders" */ './views/Orders.vue')
name: 'UserIndex',
component: () => import( /* webpackChunkName: "UserIndex" */ './views/UserIndex.vue')
}
]
},
@ -63,4 +63,4 @@ router.beforeEach((to, from, next) => {
next();
});
export default router;
export default router;

View File

@ -1,3 +1,33 @@
body,p,input,text,a{
text-decoration: none;
color:#333;
}
.text-center{
text-align:center;
}
}
.text-left{
text-align:left;
}
.text-right{
text-align:right;
}
.content-v-center{
height: 100vh;
align-items: center;
display: flex;
}
.float-left{
float:left;
}
.float-right{
float: right;
}
.row{
&:after{
content:' ';
display: block;
clear: both;
}
}

View File

@ -1,44 +1,66 @@
<template>
<div class="page-cart">
<van-nav-bar
title="购物车"
:fixed="true"
/>
<div style="height: 50px"></div>
<van-checkbox-group v-model="checkedGroup" ref="checkboxGroup">
<van-card
:price="item.sell_price"
:desc="item.desc"
v-for="(item,index) in goodsList"
:key="index"
>
<template slot="title"> <!-- 自定义标题部分主要是为了添加删除商品按钮 -->
<span>{{item.title}}</span>
<span style="float:right;" @click="remove(item)"><van-icon name="delete"/></span>
</template>
<template slot="thumb"> <!-- 自定义左侧部分为了添加左侧checkbox -->
<van-checkbox :name="item.id" checked-color="#b90505" icon-size="12px"></van-checkbox>
<van-image :src="item.picture"></van-image>
</template>
<template slot="bottom"> <!-- 自定义底部为了实现商品数量功能 -->
<div class="num">
<van-button size="small" @click="less(item)" :disabled="item.count <=1">-</van-button>
<!-- 数量小于1时禁用按钮 -->
{{item.count}}
<van-button size="small" @click="more(item)">+</van-button>
</div>
</template>
</van-card>
</van-checkbox-group>
<div style="height: 50px;"></div>
<van-submit-bar class="my-cart" :price="totalPrice" button-text="提交订单" @submit="onSubmit" :disabled="checkedGroup.length == 0">
<van-checkbox v-model="isCheckAll">全选</van-checkbox>
</van-submit-bar>
<template v-if="token">
<van-nav-bar
title="购物车"
:fixed="true"
/>
<div style="height: 50px"></div>
<van-checkbox-group v-model="checkedGroup" ref="checkboxGroup">
<van-card class="cart-g-item"
v-for="(item,index) in goodsList"
:key="index"
>
<template slot="title"> <!-- 自定义标题部分主要是为了添加删除商品按钮 -->
<span>{{item.title}}</span>
</template>
<template slot="thumb"> <!-- 自定义左侧部分为了添加左侧checkbox -->
<div class="goods-image" style="display: flex">
<div class="check-box" style="display: flex;align-items: center;margin-right: 10px">
<van-checkbox :name="item.id"></van-checkbox>
</div>
<div class="g-img">
<van-image :src="item.picture"></van-image>
</div>
</div>
</template>
<template slot="bottom"> <!-- 自定义底部为了实现商品数量功能 -->
<div class="goods-bottom row">
<div class="van-card__price float-left">
<div>
<span class="van-card__price-currency">¥</span>
<span class="van-card__price-integer">{{ item.sell_price | int }}</span>
<span class="van-card__price-decimal">{{ item.sell_price | dec }}</span>
</div>
</div>
<div class="num float-right">
<van-button class="count-btn" size="small" @click="less(item)" :disabled="item.count <=1">-</van-button>
<!-- 数量小于1时禁用按钮 -->
<input class="count-box" type="text" v-model="item.count">
<van-button class="count-btn" size="small" @click="more(item)">+</van-button>
</div>
</div>
</template>
</van-card>
</van-checkbox-group>
<div style="height: 50px;"></div>
<van-submit-bar class="my-cart" :price="totalPrice * 100" button-text="提交订单" @submit="onSubmit"
:disabled="checkedGroup.length == 0">
<van-checkbox v-model="isCheckAll">全选</van-checkbox>
</van-submit-bar>
</template>
<div v-else>
<van-empty description="登录后可同步购物车中商品" style="padding-top:100px">
<van-button round type="danger" @click="$router.push('/login?from=cart')"
style="width: 160px">登录
</van-button>
</van-empty>
</div>
</div>
</template>
<script>
import {Dialog} from "vant";
import {Dialog,Notify} from "vant";
import http from "../components/http";
export default {
@ -49,57 +71,72 @@
token,
checkedGroup: [],
goodsList: [],
checkedAllGoods:false,
checkedAllGoods: false,
}
},
computed:{
totalPrice(){
return 0;
computed: {
totalPrice() {
let total = 0;
this.goodsList.forEach(g=>{
if(this.checkedGroup.indexOf(g.id) != -1){
total += g.sell_price * g.count;
}
})
return total;
},
isCheckAll:{
set(v){
isCheckAll: {
set(v) {
this.$refs.checkboxGroup.toggleAll(v);
this.checkedAllGoods = 0;
},
get(){
return (this.goodsList.length == 0 || this.checkedGroup.length != this.goodsList.length)?false:true;
get() {
return (this.goodsList.length == 0 || this.checkedGroup.length != this.goodsList.length) ? false : true;
}
}
},
mounted() {
if(!this.token){
Dialog.alert({
title: '提示',
message: '请先登录一下下哟',
}).then(() => {
this.$router.push('/login?from=' + this.$route.fullPath);
});
return;
}
this.loadData();
},
activated() {
if (this.token) {
this.loadData();
// Dialog.alert({
// title: '',
// message: '',
// }).then(() => {
// this.$router.push('/login?from=' + this.$route.fullPath);
// });
// return;
}
},
filters:{
int(v){
if(v.indexOf('.') == -1) return v;
return v.substr(0,v.indexOf('.'));
},
dec(v){
if(v.indexOf('.') == -1) return '00';
return v.substr(v.indexOf('.'));
}
},
methods: {
onSubmit(){
if(this.checkedGroup.length > 0){
onSubmit() {
if (this.checkedGroup.length > 0) {
}
},
checkAll(){
if(this.checkedGroup.length !== 0){ //
if(this.checkedGroup.length === this.goodsList.length){ //
checkAll() {
if (this.checkedGroup.length !== 0) { //
if (this.checkedGroup.length === this.goodsList.length) { //
this.$refs.checkboxGroup.toggleAll(false); //
}else{ //
} else { //
this.$refs.checkboxGroup.toggleAll(true); //
}
}else{ //
} else { //
this.$refs.checkboxGroup.toggleAll(true);
}
},
loadData(){
http.shop.get('/cart/query?token=' + this.token).then(gs=>{
loadData() {
http.shop.get('/cart/query').then(gs => {
this.goodsList = gs
}).catch(e=>{
}).catch(e => {
Dialog.alert({
title: '提示',
message: e.message,
@ -109,22 +146,63 @@
});
},
more(g) {
g.count ++
this.update(g,g.count + 1)
},
less(g) {
if(g.count > 1){
g.count --
if (g.count > 1) {
this.update(g,g.count- 1)
}
},
remove(g) {
},
update(g,count){
http.shop.post('/cart/update',{id:g.id,count}).then(ret=>{
g.count = count;
}).catch(e=>{
Notify({message:e.message,duration: 1000})
})
}
}
}
</script>
<style scoped>
.my-cart{
bottom:50px;
}
</style>
<style scoped lang="less">
.cart-g-item{
margin:10px;
padding:5px;
border-radius: 5px;
}
.my-cart {
bottom: 50px;
}
.goods-bottom{
line-height: 26px;
.van-card__price{
color:#f00;
}
.van-card__price-integer{
font-size: 20px;
letter-spacing: -1px;
}
}
.count-box{
display: inline-block;
border: solid 1px #eee;
outline: none;
width: 30px;
text-align: center;
height: 26px;
box-sizing: border-box;
}
.count-btn{
height: 26px;
display: inline-block;
border: none;
vertical-align: middle;
background: none;
font-weight:bold;
padding:0 10px;
margin:0 3px;
}
</style>

View File

@ -1,14 +1,16 @@
<template>
<div class="page-goods-list">
<van-nav-bar
:title="category"
:title="title"
:fixed="true"
:placeholder="true"
left-text="返回"
left-arrow
@click-left="$router.back()"
/>
<page-loading :show="loading" />
<div class="goods-list-wrapper">
<template v-if="dataList.length">
<div
v-for="g in dataList"
:key="g.id"
@ -25,45 +27,62 @@
<template #price>
<div class="g-info">
<div class="price"><span>{{g.sell_price}}</span></div>
<div class="sell-info"><span>{{g.sell_count}}</span>人已经付款购买</div>
<div class="sell-info"><span>{{g.sell_count | nft}}</span> 人已经付款购买</div>
</div>
</template>
</van-card>
</div>
</template>
<van-empty v-else image="search" description="哎呀搜索的商品不还没有上架呢" />
</div>
</div>
</template>
<script>
import http from "../components/http";
import PageLoading from "../components/PageLoading";
export default {
name: "GoodsList",
components: {PageLoading},
data() {
return {
category: "",
query:{
list:'y',
pageSize: 15,
page:1
},
title: "xx",
loading: false,
dataList: [],
total: 0,
pageSize: 15
};
},
mounted() {
this.category = this.$route.query.cate;
document.title = this.category;
this.loadData(1);
const query = this.$route.query;
if(query.cate){
this.query['category'] = query.cate;
this.title = query.cate;
}
if(query.price){
if(query.price == '9_9'){
this.title = '9块9优选';
this.query['price'] = '0_9.9';
}
}
document.title = this.title;
this.loadData();
},
methods: {
onPageChange(page) {
this.loadData(page);
this.query.page = page;
this.loadData();
},
showDetail(g) {
this.$router.push("/goods-detail?id=" + g.id);
},
loadData(page) {
loadData() {
this.loading = true;
http.shop
.get(
"/goods?list=y&page=" + page + "&category=" + this.category
)
.get('/goods',this.query)
.then(data => {
this.loading = false;
this.dataList = data.list;

View File

@ -11,6 +11,15 @@
.page-home{
background-color: #eee;
}
.hot-cate{
padding: 10px 0;
img{
width: 40px;
}
.item{
flex: 1;
}
}
</style>
<template>
@ -23,12 +32,21 @@
</van-swipe-item>
</van-swipe>
</div>
<div class="hot-cate"></div>
<div class="hot-cate text-center">
<div style="display: flex">
<router-link :to="c.to" class="item" v-for="c in hotCategory" :key="c.text">
<div class="image">
<img :src="c.img" alt="">
</div>
<div class="text">{{c.text}}</div>
</router-link>
</div>
</div>
<div class="hot-goods">
<div class="title" style="margin:10px 0;">
<img class="ll_fadeIn" style="width: calc(100% - 1rem); height: 100%; opacity: 1;" src="//img12.360buyimg.com/img/s750x70_jfs/t1/148857/1/16777/13220/5fc9f9d0E734c0ee5/88c99cdbe410e58a.png">
</div>
<GoodsList :goodsList="dataList" />
<HotGoods />
</div>
</div>
</template>
@ -38,13 +56,20 @@
import http from "../components/http";
import GoodsList from '../components/GoodsList'
import SearchGoodsBox from "../components/SearchGoodsBox";
import HotGoods from "../components/HotGoods";
const cate_img_url ='https://file.wx.wm-app.xyz/os/shop/';
export default {
name: "home",
components:{SearchGoodsBox, GoodsList},
components:{HotGoods, SearchGoodsBox, GoodsList},
data() {
return {
hotCategory:[
{img:cate_img_url + '3c.png.webp',text:'数码电器',to:'/goods-list?cate=手机'},
{img:cate_img_url + '9.9.png.webp',text:'9.9包邮',to:'/goods-list?price=9_9'},
{img:cate_img_url + 'cloth.png.webp',text:'服饰',to:'/goods-list?cate=服饰'},
{img:cate_img_url + 'fruit.png.webp',text:'生鲜',to:'/goods-list?cate=生鲜'},
{img:cate_img_url + 'fruit.png.webp',text:'生鲜',to:'/goods-list?cate=生鲜'},
],
swipes:[
{name:'24期免息',img:'//m.360buyimg.com/mobilecms/s700x280_jfs/t1/145540/4/18667/107221/5fd8c5a7Ed54a9545/14e408a6ee76c316.jpg!cr_1125x445_0_171!q70.jpg.dpg',url:'/goods-list?cate=显示器'},
{name:'茶油',img:'//m.360buyimg.com/mobilecms/s700x280_jfs/t1/149172/3/18184/263815/5fd5c4d5E1740ade6/a05ecfaaa05026a4.jpg!cr_1125x445_0_171!q70.jpg.dpg',url:'/goods-list?cate=茶油'},

View File

@ -13,7 +13,7 @@
</style>
<template>
<div class="page-login" style="background:#eee; height: 100vh;">
<div class="page-login" style="height: 100vh;">
<van-nav-bar title="登录"
left-text="返回"
left-arrow
@ -37,6 +37,14 @@
placeholder="密码"
:rules="[{ required: true, message: '请填写密码' }]"
/>
<van-row class="van-cell">
<van-col span="12">
<router-link to="/forget">忘记密码</router-link>
</van-col>
<van-col span="12" class="text-right">
<router-link to="/reg">立即免费注册</router-link>
</van-col>
</van-row>
<div style="margin: 16px;">
<van-button
round
@ -44,7 +52,7 @@
type="info"
native-type="submit"
>
提交
登录
</van-button>
</div>
</van-form>

87
src/views/UserIndex.vue Normal file
View File

@ -0,0 +1,87 @@
<template>
<div class="page-user-index">
<div class="user-profile">
<div class="info">
<van-image round src="https://img.yzcdn.cn/vant/cat.jpeg" />
<h3 class="name">
用户名
</h3>
</div>
</div>
<van-row class="user-links">
<van-col span="8">
<div><van-icon name="balance-pay" color="#7af" badge="9" /></div>
<span>代付款</span>
</van-col>
<van-col span="8">
<div><van-icon name="send-gift-o" color="#f00"/></div>
<span>待收货</span>
</van-col>
<van-col span="8">
<div><van-icon name="comment-o" color="#fa0"/></div>
<span>待评价</span>
</van-col>
</van-row>
<van-cell-group class="user-group">
<van-cell icon="edit" title="编辑资料" to="/user/profile" is-link />
<van-cell icon="chat-o" title="小智同学" to="/user/chat" is-link />
<van-cell icon="setting-o" title="系统设置" is-link />
<van-cell icon="warning-o" title="退出登录" to="/user/login" is-link />
</van-cell-group>
</div>
</template>
<script>
export default {
name: "UserIndex"
}
</script>
<style scoped lang="less">
.page-user-index{
background: #1989fa;
}
.user {
&-profile {
width: 100%;
display: block;
.info {
display: flex;
padding: 30px 20px;
align-items: center;
color:#fff;
.van-image{
width: 64px;
height: 64px;
}
.name {
font-size: 16px;
font-weight: normal;
margin-left: 10px;
}
.van-tag {
background: #fff;
color: #3296fa;
}
}
p{
margin: 0;
text-align: center;
}
}
&-group {
margin-bottom: 15px;
}
&-links {
padding: 15px 0;
text-align: center;
background-color: #fff;
border-top-left-radius: 10px;
border-top-right-radius:10px;
.van-icon {
font-size: 26px;
}
}
}
</style>