chore[litemall-vue]: 参考litemall-admin结构,重新调整litemall-vue的src结构
This commit is contained in:
@@ -23,7 +23,7 @@ litemall轻商城,是商城移动版本。
|
||||
|
||||
可以阅读3.1
|
||||
|
||||
## 3.2 litemall-vue
|
||||
## 5.2 litemall-vue
|
||||
|
||||
这里的代码基于[vant--mobile-mall](https://github.com/qianzhaoy/vant--mobile-mall)
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ litemall是一个简单的商场系统,基于现有的开源项目,重新实
|
||||
* 地址列表、地址添加、地址删除
|
||||
* 收藏、足迹、关于
|
||||
|
||||
### 1.2.1 轻商城功能
|
||||
### 1.2.2 轻商城功能
|
||||
|
||||
**目前还在开发中,不稳定**
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@
|
||||
"vant": "^1.4.4",
|
||||
"vee-validate": "^2.1.4",
|
||||
"vue": "^2.5.17",
|
||||
"js-cookie": "2.2.0",
|
||||
"vuex": "3.0.1",
|
||||
"vue-router": "^3.0.1",
|
||||
"vuelidation": "^1.1.0"
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import request from '@/core/utils/request'
|
||||
import request from '@/utils/request'
|
||||
|
||||
// export const GOODS_CATEGORY = '/category';
|
||||
export const GOODS_CATEGORY = '/wx/catalog/index';
|
||||
|
||||
@@ -1,18 +1,44 @@
|
||||
// 登录
|
||||
export const USER_LOGIN = '/wx/auth/login';
|
||||
export const USER_LOGOUT = '';
|
||||
|
||||
// 用户信息
|
||||
export const USER_PROFILE = '/user-profile';
|
||||
export const USER_MODIFY_PASSWORD = '';
|
||||
export const USER_CHANGE_MOBILE = '';
|
||||
|
||||
// 验证码
|
||||
export const USER_SENDCODE = '';
|
||||
|
||||
// 地址
|
||||
export const ADDRESS = '/address';
|
||||
export const ADDRESS_DEFAULT = '/address-default';
|
||||
|
||||
// 收藏
|
||||
export const GOODS_COLLECT_LIST = '/moreGoods';
|
||||
// 登录
|
||||
export const USER_LOGIN = '/wx/auth/login';
|
||||
export const USER_LOGOUT = '';
|
||||
|
||||
// 用户信息
|
||||
export const USER_PROFILE = '/user-profile';
|
||||
export const USER_MODIFY_PASSWORD = '';
|
||||
export const USER_CHANGE_MOBILE = '';
|
||||
|
||||
// 验证码
|
||||
export const USER_SENDCODE = '';
|
||||
|
||||
// 地址
|
||||
export const ADDRESS = '/address';
|
||||
export const ADDRESS_DEFAULT = '/address-default';
|
||||
|
||||
// 收藏
|
||||
export const GOODS_COLLECT_LIST = '/moreGoods';
|
||||
|
||||
import request from '@/utils/request'
|
||||
|
||||
export function loginByUsername(data) {
|
||||
return request({
|
||||
url: '/wx/auth/login',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function logout() {
|
||||
return request({
|
||||
url: '/auth/logout',
|
||||
method: 'post'
|
||||
})
|
||||
}
|
||||
|
||||
export function getUserInfo(token) {
|
||||
return request({
|
||||
url: '/auth/info',
|
||||
method: 'get',
|
||||
params: { token }
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB |
176
litemall-vue/src/vue/components/Tabbar/index.vue → litemall-vue/src/components/Tabbar/index.vue
Executable file → Normal file
176
litemall-vue/src/vue/components/Tabbar/index.vue → litemall-vue/src/components/Tabbar/index.vue
Executable file → Normal file
@@ -1,88 +1,88 @@
|
||||
<template>
|
||||
<van-tabbar v-model="active" style="z-index: 1999">
|
||||
<van-tabbar-item
|
||||
v-for="(tab, index) in tabbar"
|
||||
:icon="tab.icon"
|
||||
:to="tab.path"
|
||||
:dot="tab.dot"
|
||||
:info="tab.info"
|
||||
:key="index">
|
||||
{{tab.name}}
|
||||
</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { Tabbar, TabbarItem } from 'vant';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
active: 0,
|
||||
tabbar: [
|
||||
{
|
||||
name: '精选',
|
||||
path: '/',
|
||||
pathName: 'home',
|
||||
icon: 'compass-full',
|
||||
dot: false,
|
||||
info: ''
|
||||
},
|
||||
{
|
||||
name: '分类',
|
||||
path: '/items',
|
||||
pathName: 'class',
|
||||
icon: 'class-full',
|
||||
dot: false,
|
||||
info: ''
|
||||
},
|
||||
{
|
||||
name: '购物车',
|
||||
path: '/order',
|
||||
pathName: 'cart',
|
||||
icon: 'cart-full',
|
||||
dot: false,
|
||||
info: ''
|
||||
},
|
||||
{
|
||||
name: '我的',
|
||||
path: '/user',
|
||||
pathName: 'user',
|
||||
icon: 'wode',
|
||||
dot: false,
|
||||
info: ''
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
$route: 'changeActive'
|
||||
},
|
||||
|
||||
created() {
|
||||
const toName = this.$route.name;
|
||||
this.setActive(toName);
|
||||
},
|
||||
|
||||
methods: {
|
||||
changeActive({ name }) {
|
||||
this.setActive(name);
|
||||
},
|
||||
setActive(name) {
|
||||
this.tabbar.forEach((tab, i) => {
|
||||
if (tab.pathName == name) {
|
||||
this.active = i;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[Tabbar.name]: Tabbar,
|
||||
[TabbarItem.name]: TabbarItem
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<template>
|
||||
<van-tabbar v-model="active" style="z-index: 1999">
|
||||
<van-tabbar-item
|
||||
v-for="(tab, index) in tabbar"
|
||||
:icon="tab.icon"
|
||||
:to="tab.path"
|
||||
:dot="tab.dot"
|
||||
:info="tab.info"
|
||||
:key="index">
|
||||
{{tab.name}}
|
||||
</van-tabbar-item>
|
||||
</van-tabbar>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { Tabbar, TabbarItem } from 'vant';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
active: 0,
|
||||
tabbar: [
|
||||
{
|
||||
name: '精选',
|
||||
path: '/',
|
||||
pathName: 'home',
|
||||
icon: 'compass-full',
|
||||
dot: false,
|
||||
info: ''
|
||||
},
|
||||
{
|
||||
name: '分类',
|
||||
path: '/items',
|
||||
pathName: 'class',
|
||||
icon: 'class-full',
|
||||
dot: false,
|
||||
info: ''
|
||||
},
|
||||
{
|
||||
name: '购物车',
|
||||
path: '/order',
|
||||
pathName: 'cart',
|
||||
icon: 'cart-full',
|
||||
dot: false,
|
||||
info: ''
|
||||
},
|
||||
{
|
||||
name: '我的',
|
||||
path: '/user',
|
||||
pathName: 'user',
|
||||
icon: 'wode',
|
||||
dot: false,
|
||||
info: ''
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
watch: {
|
||||
$route: 'changeActive'
|
||||
},
|
||||
|
||||
created() {
|
||||
const toName = this.$route.name;
|
||||
this.setActive(toName);
|
||||
},
|
||||
|
||||
methods: {
|
||||
changeActive({ name }) {
|
||||
this.setActive(name);
|
||||
},
|
||||
setActive(name) {
|
||||
this.tabbar.forEach((tab, i) => {
|
||||
if (tab.pathName == name) {
|
||||
this.active = i;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[Tabbar.name]: Tabbar,
|
||||
[TabbarItem.name]: TabbarItem
|
||||
}
|
||||
};
|
||||
</script>
|
||||
226
litemall-vue/src/vue/components/_directive/scrollMore.js → litemall-vue/src/components/_directive/scrollMore.js
Executable file → Normal file
226
litemall-vue/src/vue/components/_directive/scrollMore.js → litemall-vue/src/components/_directive/scrollMore.js
Executable file → Normal file
@@ -1,113 +1,113 @@
|
||||
import { debounce } from 'lodash';
|
||||
import scroll from 'core/utils/scroll';
|
||||
|
||||
const CONTEXT = '$scrollArrow';
|
||||
const OFFSET = 30;
|
||||
|
||||
// 绑定事件
|
||||
function startBind(el) {
|
||||
const context = el[CONTEXT];
|
||||
|
||||
context.vm.$nextTick(() => {
|
||||
if (scroll.isAttached(el)) {
|
||||
doBindEvent.call(el[CONTEXT]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 绑定事件到元素上
|
||||
// 读取基本的控制变量
|
||||
function doBindEvent() {
|
||||
if (this.el[CONTEXT].binded) {
|
||||
return;
|
||||
}
|
||||
this.el[CONTEXT].binded = true;
|
||||
|
||||
this.scrollEventListener = debounce(handleScrollEvent.bind(this), 100);
|
||||
// this.scrollEventTarget = this.el;
|
||||
|
||||
// var disabledExpr = this.el.getAttribute('waterfall-disabled');
|
||||
// var disabled = false;
|
||||
// if (disabledExpr) {
|
||||
// this.vm.$watch(disabledExpr, (value) => {
|
||||
// this.disabled = value;
|
||||
// this.scrollEventListener();
|
||||
// });
|
||||
// disabled = Boolean(this.vm[disabledExpr]);
|
||||
// }
|
||||
// this.disabled = disabled;
|
||||
|
||||
const offset = this.el.getAttribute('scroll-offset');
|
||||
this.offset = Number(offset) || OFFSET;
|
||||
this.el.addEventListener('scroll', this.scrollEventListener);
|
||||
|
||||
// this.scrollEventListener();
|
||||
}
|
||||
|
||||
// 处理滚动函数
|
||||
function handleScrollEvent() {
|
||||
const element = this.el;
|
||||
// 已被禁止的滚动处理
|
||||
// if (this.disabled) return;
|
||||
|
||||
const targetScrollLeft = scroll.getScrollLeft(element);
|
||||
const targetVisibleWidth = scroll.getVisibleWidth(element);
|
||||
// 滚动元素可视区域下边沿到滚动元素元素最顶上 距离
|
||||
const targetRight = targetScrollLeft + targetVisibleWidth;
|
||||
// 如果无元素高度,考虑为元素隐藏,直接返回
|
||||
if (!targetVisibleWidth) return;
|
||||
|
||||
// 判断是否到了最右边
|
||||
const isRightOver = element.scrollWidth - targetRight < this.offset;
|
||||
|
||||
// 判断是否到了最左边
|
||||
const isLeftOver = targetScrollLeft < this.offset;
|
||||
|
||||
this.cb &&
|
||||
this.cb({
|
||||
target: element,
|
||||
isRightOver,
|
||||
isLeftOver
|
||||
});
|
||||
|
||||
// // 判断是否到了顶
|
||||
// let needLoadMoreToUpper = targetScrollTop < this.offset;
|
||||
// if (needLoadMoreToUpper) {
|
||||
// this.cb.upper && this.cb.upper({
|
||||
// target: scrollEventTarget,
|
||||
// top: targetScrollTop
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
// 确认何时绑事件监听函数
|
||||
function doCheckStartBind(el) {
|
||||
const context = el[CONTEXT];
|
||||
|
||||
if (context.vm._isMounted) {
|
||||
startBind(el);
|
||||
} else {
|
||||
context.vm.$on('hook:mounted', () => {
|
||||
startBind(el);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
bind(el, binding, vnode) {
|
||||
if (!el[CONTEXT]) {
|
||||
el[CONTEXT] = {
|
||||
el,
|
||||
vm: vnode.context,
|
||||
cb: {}
|
||||
};
|
||||
}
|
||||
el[CONTEXT].cb = binding.value;
|
||||
|
||||
doCheckStartBind(el);
|
||||
},
|
||||
update(el) {
|
||||
const context = el[CONTEXT];
|
||||
context.scrollEventListener && context.scrollEventListener();
|
||||
}
|
||||
};
|
||||
import { debounce } from 'lodash';
|
||||
import scroll from '@/utils/scroll';
|
||||
|
||||
const CONTEXT = '$scrollArrow';
|
||||
const OFFSET = 30;
|
||||
|
||||
// 绑定事件
|
||||
function startBind(el) {
|
||||
const context = el[CONTEXT];
|
||||
|
||||
context.vm.$nextTick(() => {
|
||||
if (scroll.isAttached(el)) {
|
||||
doBindEvent.call(el[CONTEXT]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 绑定事件到元素上
|
||||
// 读取基本的控制变量
|
||||
function doBindEvent() {
|
||||
if (this.el[CONTEXT].binded) {
|
||||
return;
|
||||
}
|
||||
this.el[CONTEXT].binded = true;
|
||||
|
||||
this.scrollEventListener = debounce(handleScrollEvent.bind(this), 100);
|
||||
// this.scrollEventTarget = this.el;
|
||||
|
||||
// var disabledExpr = this.el.getAttribute('waterfall-disabled');
|
||||
// var disabled = false;
|
||||
// if (disabledExpr) {
|
||||
// this.vm.$watch(disabledExpr, (value) => {
|
||||
// this.disabled = value;
|
||||
// this.scrollEventListener();
|
||||
// });
|
||||
// disabled = Boolean(this.vm[disabledExpr]);
|
||||
// }
|
||||
// this.disabled = disabled;
|
||||
|
||||
const offset = this.el.getAttribute('scroll-offset');
|
||||
this.offset = Number(offset) || OFFSET;
|
||||
this.el.addEventListener('scroll', this.scrollEventListener);
|
||||
|
||||
// this.scrollEventListener();
|
||||
}
|
||||
|
||||
// 处理滚动函数
|
||||
function handleScrollEvent() {
|
||||
const element = this.el;
|
||||
// 已被禁止的滚动处理
|
||||
// if (this.disabled) return;
|
||||
|
||||
const targetScrollLeft = scroll.getScrollLeft(element);
|
||||
const targetVisibleWidth = scroll.getVisibleWidth(element);
|
||||
// 滚动元素可视区域下边沿到滚动元素元素最顶上 距离
|
||||
const targetRight = targetScrollLeft + targetVisibleWidth;
|
||||
// 如果无元素高度,考虑为元素隐藏,直接返回
|
||||
if (!targetVisibleWidth) return;
|
||||
|
||||
// 判断是否到了最右边
|
||||
const isRightOver = element.scrollWidth - targetRight < this.offset;
|
||||
|
||||
// 判断是否到了最左边
|
||||
const isLeftOver = targetScrollLeft < this.offset;
|
||||
|
||||
this.cb &&
|
||||
this.cb({
|
||||
target: element,
|
||||
isRightOver,
|
||||
isLeftOver
|
||||
});
|
||||
|
||||
// // 判断是否到了顶
|
||||
// let needLoadMoreToUpper = targetScrollTop < this.offset;
|
||||
// if (needLoadMoreToUpper) {
|
||||
// this.cb.upper && this.cb.upper({
|
||||
// target: scrollEventTarget,
|
||||
// top: targetScrollTop
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
||||
// 确认何时绑事件监听函数
|
||||
function doCheckStartBind(el) {
|
||||
const context = el[CONTEXT];
|
||||
|
||||
if (context.vm._isMounted) {
|
||||
startBind(el);
|
||||
} else {
|
||||
context.vm.$on('hook:mounted', () => {
|
||||
startBind(el);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
bind(el, binding, vnode) {
|
||||
if (!el[CONTEXT]) {
|
||||
el[CONTEXT] = {
|
||||
el,
|
||||
vm: vnode.context,
|
||||
cb: {}
|
||||
};
|
||||
}
|
||||
el[CONTEXT].cb = binding.value;
|
||||
|
||||
doCheckStartBind(el);
|
||||
},
|
||||
update(el) {
|
||||
const context = el[CONTEXT];
|
||||
context.scrollEventListener && context.scrollEventListener();
|
||||
}
|
||||
};
|
||||
52
litemall-vue/src/vue/components/field-group/index.vue → litemall-vue/src/components/field-group/index.vue
Executable file → Normal file
52
litemall-vue/src/vue/components/field-group/index.vue → litemall-vue/src/components/field-group/index.vue
Executable file → Normal file
@@ -1,26 +1,26 @@
|
||||
<template>
|
||||
<div class="field_group">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-field-group'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.field_group {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
|
||||
> div {
|
||||
margin-bottom: 15px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="field_group">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-field-group'
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.field_group {
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
|
||||
> div {
|
||||
margin-bottom: 15px;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
208
litemall-vue/src/vue/components/field/index.vue → litemall-vue/src/components/field/index.vue
Executable file → Normal file
208
litemall-vue/src/vue/components/field/index.vue → litemall-vue/src/components/field/index.vue
Executable file → Normal file
@@ -1,104 +1,104 @@
|
||||
<template>
|
||||
<div class="md_field" :class="{md_field_hasIcon: !!icon, md_field_isError: isError}">
|
||||
<van-icon v-if="icon" :name="icon" class="md_feld_icon"/>
|
||||
<div class="md_field_control">
|
||||
<input
|
||||
:type="type"
|
||||
v-on="listeners"
|
||||
v-bind="$attrs"
|
||||
:value="value">
|
||||
</div>
|
||||
<div>
|
||||
<slot name="rightIcon">
|
||||
<van-icon :name="rightIcon" @click="rightClick" v-show="value" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-field',
|
||||
|
||||
props: {
|
||||
value: {},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
rightIcon: String,
|
||||
icon: String,
|
||||
isError: Boolean
|
||||
},
|
||||
computed: {
|
||||
listeners() {
|
||||
return {
|
||||
...this.$listeners,
|
||||
input: this.onInput
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onInput(event) {
|
||||
this.$emit('input', event.target.value);
|
||||
},
|
||||
rightClick(event) {
|
||||
this.$emit('right-click', event);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.md_field {
|
||||
position: relative;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 10px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
> div {
|
||||
display: table-cell;
|
||||
}
|
||||
> .md_field_control {
|
||||
padding-right: 10px;
|
||||
box-sizing: border-box;
|
||||
input {
|
||||
border: 0;
|
||||
line-height: 14px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.md_feld_icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 10px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.md_field_hasIcon {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.md_field_isError {
|
||||
color: $red;
|
||||
background-color: #fcf5f5;
|
||||
border: 1px solid $red;
|
||||
input {
|
||||
color: $red;
|
||||
background-color: #fcf5f5;
|
||||
}
|
||||
input:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0 1000px #fcf5f5 inset !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="md_field" :class="{md_field_hasIcon: !!icon, md_field_isError: isError}">
|
||||
<van-icon v-if="icon" :name="icon" class="md_feld_icon"/>
|
||||
<div class="md_field_control">
|
||||
<input
|
||||
:type="type"
|
||||
v-on="listeners"
|
||||
v-bind="$attrs"
|
||||
:value="value">
|
||||
</div>
|
||||
<div>
|
||||
<slot name="rightIcon">
|
||||
<van-icon :name="rightIcon" @click="rightClick" v-show="value" />
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'md-field',
|
||||
|
||||
props: {
|
||||
value: {},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
rightIcon: String,
|
||||
icon: String,
|
||||
isError: Boolean
|
||||
},
|
||||
computed: {
|
||||
listeners() {
|
||||
return {
|
||||
...this.$listeners,
|
||||
input: this.onInput
|
||||
};
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
onInput(event) {
|
||||
this.$emit('input', event.target.value);
|
||||
},
|
||||
rightClick(event) {
|
||||
this.$emit('right-click', event);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.md_field {
|
||||
position: relative;
|
||||
border: 1px solid $border-color;
|
||||
border-radius: 5px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
padding-left: 10px;
|
||||
display: table;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
> div {
|
||||
display: table-cell;
|
||||
}
|
||||
> .md_field_control {
|
||||
padding-right: 10px;
|
||||
box-sizing: border-box;
|
||||
input {
|
||||
border: 0;
|
||||
line-height: 14px;
|
||||
font-size: 14px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.md_feld_icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 10px;
|
||||
transform: translate(0, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.md_field_hasIcon {
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.md_field_isError {
|
||||
color: $red;
|
||||
background-color: #fcf5f5;
|
||||
border: 1px solid $red;
|
||||
input {
|
||||
color: $red;
|
||||
background-color: #fcf5f5;
|
||||
}
|
||||
input:-webkit-autofill {
|
||||
-webkit-box-shadow: 0 0 0 1000px #fcf5f5 inset !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -17,8 +17,8 @@
|
||||
<script>
|
||||
import { List } from 'vant';
|
||||
import { get } from 'lodash';
|
||||
import IsEmpty from '@/vue/components/is-empty';
|
||||
import loadMore from '@/vue/mixin/load-more';
|
||||
import IsEmpty from '@/components/is-empty';
|
||||
import loadMore from '@/mixin/load-more';
|
||||
|
||||
const DEFAULT_CONFIG = {
|
||||
params: {},
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="is_empty">
|
||||
<div>
|
||||
<img src="../../../assets/images/is_empty.png" alt="无商品" width="20%">
|
||||
<img src="../../assets/images/is_empty.png" alt="无商品" width="20%">
|
||||
</div>
|
||||
<div>
|
||||
<slot></slot>
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
|
||||
<script>
|
||||
import item_mix from '@/vue/mixin/item-card';
|
||||
import item_mix from '@/mixin/item-card';
|
||||
|
||||
export default {
|
||||
name: 'item-card-hori',
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
|
||||
<script>
|
||||
import item_mix from '@/vue/mixin/item-card';
|
||||
import item_mix from '@/mixin/item-card';
|
||||
|
||||
export default {
|
||||
name: 'item-card-vert',
|
||||
@@ -1,32 +0,0 @@
|
||||
// 使用这个会导致组件内部的 router 导航守卫无法使用, 慎用
|
||||
/**
|
||||
* @param { string } chunkPath views 文件夹下的页面路径
|
||||
* @return { function } 返回 promise<component> 的匿名函数
|
||||
*/
|
||||
import spinner from '@/vue/components/spinner';
|
||||
|
||||
export default chunkPath => {
|
||||
const AsyncHandler = () => ({
|
||||
component: new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(
|
||||
import(/* webpackChunkName: "[request]" */ `@/views/${chunkPath}`)
|
||||
);
|
||||
}, 1000);
|
||||
}),
|
||||
loading: spinner,
|
||||
error: {
|
||||
render(h) {
|
||||
return h('div', {}, ['异步组件加载失败']);
|
||||
}
|
||||
},
|
||||
timeout: 10000
|
||||
});
|
||||
return () =>
|
||||
Promise.resolve({
|
||||
functional: true,
|
||||
render(h, { data, children }) {
|
||||
return h(AsyncHandler, data, children);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -1,90 +0,0 @@
|
||||
// import axios from 'axios'
|
||||
// import { Message, MessageBox } from 'element-ui'
|
||||
// import store from '@/store'
|
||||
// import { getToken } from '@/utils/auth'
|
||||
|
||||
// // create an axios instance
|
||||
// const service = axios.create({
|
||||
// baseURL: process.env.BASE_API, // api 的 base_url
|
||||
// timeout: 5000 // request timeout
|
||||
// })
|
||||
|
||||
// // request interceptor
|
||||
// service.interceptors.request.use(
|
||||
// config => {
|
||||
// // Do something before request is sent
|
||||
// if (store.getters.token) {
|
||||
// // 让每个请求携带token-- ['X-Litemall-Admin-Token']为自定义key 请根据实际情况自行修改
|
||||
// config.headers['X-Litemall-Admin-Token'] = getToken()
|
||||
// }
|
||||
// return config
|
||||
// },
|
||||
// error => {
|
||||
// // Do something with request error
|
||||
// console.log(error) // for debug
|
||||
// Promise.reject(error)
|
||||
// }
|
||||
// )
|
||||
|
||||
// // response interceptor
|
||||
// service.interceptors.response.use(
|
||||
// response => {
|
||||
// const res = response.data
|
||||
|
||||
// if (res.errno === 501) {
|
||||
// MessageBox.alert('系统未登录,请重新登录', '错误', {
|
||||
// confirmButtonText: '确定',
|
||||
// type: 'error'
|
||||
// }).then(() => {
|
||||
// store.dispatch('FedLogOut').then(() => {
|
||||
// location.reload()
|
||||
// })
|
||||
// })
|
||||
// return Promise.reject('error')
|
||||
// } else if (res.errno === 502) {
|
||||
// MessageBox.alert('系统内部错误,请联系管理员维护', '错误', {
|
||||
// confirmButtonText: '确定',
|
||||
// type: 'error'
|
||||
// })
|
||||
// return Promise.reject('error')
|
||||
// } else if (res.errno === 503) {
|
||||
// MessageBox.alert('请求业务目前未支持', '警告', {
|
||||
// confirmButtonText: '确定',
|
||||
// type: 'error'
|
||||
// })
|
||||
// return Promise.reject('error')
|
||||
// } else if (res.errno === 504) {
|
||||
// MessageBox.alert('更新数据已经失效,请刷新页面重新操作', '警告', {
|
||||
// confirmButtonText: '确定',
|
||||
// type: 'error'
|
||||
// })
|
||||
// return Promise.reject('error')
|
||||
// } else if (res.errno === 505) {
|
||||
// MessageBox.alert('更新失败,请再尝试一次', '警告', {
|
||||
// confirmButtonText: '确定',
|
||||
// type: 'error'
|
||||
// })
|
||||
// return Promise.reject('error')
|
||||
// } else if (res.errno === 506) {
|
||||
// MessageBox.alert('没有操作权限,请联系管理员授权', '错误', {
|
||||
// confirmButtonText: '确定',
|
||||
// type: 'error'
|
||||
// })
|
||||
// return Promise.reject('error')
|
||||
// } else if (res.errno !== 0) {
|
||||
// // 非5xx的错误属于业务错误,留给具体页面处理
|
||||
// return Promise.reject(response)
|
||||
// } else {
|
||||
// return response
|
||||
// }
|
||||
// }, error => {
|
||||
// console.log('err' + error)// for debug
|
||||
// Message({
|
||||
// message: '登录连接超时(后台不能连接,请联系系统管理员)',
|
||||
// type: 'error',
|
||||
// duration: 5 * 1000
|
||||
// })
|
||||
// return Promise.reject(error)
|
||||
// })
|
||||
|
||||
// export default service
|
||||
28
litemall-vue/src/vue/filter/index.js → litemall-vue/src/filter/index.js
Executable file → Normal file
28
litemall-vue/src/vue/filter/index.js → litemall-vue/src/filter/index.js
Executable file → Normal file
@@ -1,14 +1,14 @@
|
||||
import dayjs from 'dayjs';
|
||||
import { isNumber } from 'lodash';
|
||||
export const dateFormat = (value, format = 'YYYY-MM-DD') =>
|
||||
value ? dayjs(value * 1000).format(format) : '';
|
||||
|
||||
export const yuan = value =>
|
||||
isNumber(value) ? `¥${(value / 100).toFixed(2)}` : value;
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.filter('yuan', yuan);
|
||||
Vue.filter('dateFormat', dateFormat);
|
||||
}
|
||||
};
|
||||
import dayjs from 'dayjs';
|
||||
import { isNumber } from 'lodash';
|
||||
export const dateFormat = (value, format = 'YYYY-MM-DD') =>
|
||||
value ? dayjs(value * 1000).format(format) : '';
|
||||
|
||||
export const yuan = value =>
|
||||
isNumber(value) ? `¥${(value / 100).toFixed(2)}` : value;
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.filter('yuan', yuan);
|
||||
Vue.filter('dateFormat', dateFormat);
|
||||
}
|
||||
};
|
||||
@@ -1,15 +1,16 @@
|
||||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
import router from './vue/router';
|
||||
import router from './router';
|
||||
import store from './store'
|
||||
import './assets/scss/global.scss';
|
||||
import '@/assets/scss/iconfont/iconfont.css';
|
||||
|
||||
import VeeValidate, { Validator } from 'vee-validate';
|
||||
import VueCountdown from '@/vue/plugins/vue-countdown';
|
||||
import VueCountdown from '@/plugins/vue-countdown';
|
||||
import zhCN from 'vee-validate/dist/locale/zh_CN';
|
||||
|
||||
import axios from '@/vue/plugins/axios';
|
||||
import filters from '@/vue/filter';
|
||||
import axios from '@/plugins/axios';
|
||||
import filters from '@/filter';
|
||||
|
||||
Vue.use(VueCountdown);
|
||||
Vue.use(axios);
|
||||
@@ -41,5 +42,6 @@ Vue.config.productionTip = false;
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App)
|
||||
}).$mount('#app');
|
||||
|
||||
44
litemall-vue/src/vue/mixin/item-card.js → litemall-vue/src/mixin/item-card.js
Executable file → Normal file
44
litemall-vue/src/vue/mixin/item-card.js → litemall-vue/src/mixin/item-card.js
Executable file → Normal file
@@ -1,22 +1,22 @@
|
||||
export default {
|
||||
props: {
|
||||
goods: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
goodsStatusToMe() {
|
||||
const is_buy = this.goods.is_buy;
|
||||
const is_collect = this.goods.is_collect;
|
||||
return is_buy ? '我购买过' : is_collect ? '我收藏过' : '';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OnClick() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
export default {
|
||||
props: {
|
||||
goods: {
|
||||
type: Object,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
goodsStatusToMe() {
|
||||
const is_buy = this.goods.is_buy;
|
||||
const is_collect = this.goods.is_collect;
|
||||
return is_buy ? '我购买过' : is_collect ? '我收藏过' : '';
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
OnClick() {
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
};
|
||||
132
litemall-vue/src/vue/mixin/load-more.js → litemall-vue/src/mixin/load-more.js
Executable file → Normal file
132
litemall-vue/src/vue/mixin/load-more.js → litemall-vue/src/mixin/load-more.js
Executable file → Normal file
@@ -1,66 +1,66 @@
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pages: {
|
||||
perPage: 8,
|
||||
currPage: 1,
|
||||
pageCount: 1
|
||||
},
|
||||
loading: false,
|
||||
finished: false,
|
||||
isEmpty: false
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async resetInit() {
|
||||
this.resetData();
|
||||
const page = await this.initData();
|
||||
this.$nextTick(() => {
|
||||
this.setPages(page);
|
||||
});
|
||||
},
|
||||
isFinished() {
|
||||
this.finished = true;
|
||||
this.loading = false;
|
||||
},
|
||||
async loadMore() {
|
||||
console.log('loadmore');
|
||||
const {
|
||||
pages: { pageCount, currPage }
|
||||
} = this;
|
||||
const finish = pageCount < currPage;
|
||||
if (finish) {
|
||||
this.isFinished();
|
||||
} else {
|
||||
this.setPages(await this.initData(true));
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
nextPage(pageCount = 1) {
|
||||
this.pages.currPage += 1;
|
||||
this.pages.pageCount = pageCount;
|
||||
this.loading = false;
|
||||
},
|
||||
setPages(page = {}) {
|
||||
this.isEmpty = page.totalCount === 0;
|
||||
if (page.totalCount <= this.pages.perPage) {
|
||||
// 不满一页
|
||||
this.isFinished();
|
||||
} else {
|
||||
// 下一页
|
||||
this.nextPage(page.pageCount);
|
||||
}
|
||||
},
|
||||
resetData() {
|
||||
this.pages = {
|
||||
perPage: 8,
|
||||
currPage: 1,
|
||||
pageCount: 1
|
||||
};
|
||||
this.loading = true;
|
||||
this.finished = false;
|
||||
this.isEmpty = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
pages: {
|
||||
perPage: 8,
|
||||
currPage: 1,
|
||||
pageCount: 1
|
||||
},
|
||||
loading: false,
|
||||
finished: false,
|
||||
isEmpty: false
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async resetInit() {
|
||||
this.resetData();
|
||||
const page = await this.initData();
|
||||
this.$nextTick(() => {
|
||||
this.setPages(page);
|
||||
});
|
||||
},
|
||||
isFinished() {
|
||||
this.finished = true;
|
||||
this.loading = false;
|
||||
},
|
||||
async loadMore() {
|
||||
console.log('loadmore');
|
||||
const {
|
||||
pages: { pageCount, currPage }
|
||||
} = this;
|
||||
const finish = pageCount < currPage;
|
||||
if (finish) {
|
||||
this.isFinished();
|
||||
} else {
|
||||
this.setPages(await this.initData(true));
|
||||
}
|
||||
this.loading = false;
|
||||
},
|
||||
nextPage(pageCount = 1) {
|
||||
this.pages.currPage += 1;
|
||||
this.pages.pageCount = pageCount;
|
||||
this.loading = false;
|
||||
},
|
||||
setPages(page = {}) {
|
||||
this.isEmpty = page.totalCount === 0;
|
||||
if (page.totalCount <= this.pages.perPage) {
|
||||
// 不满一页
|
||||
this.isFinished();
|
||||
} else {
|
||||
// 下一页
|
||||
this.nextPage(page.pageCount);
|
||||
}
|
||||
},
|
||||
resetData() {
|
||||
this.pages = {
|
||||
perPage: 8,
|
||||
currPage: 1,
|
||||
pageCount: 1
|
||||
};
|
||||
this.loading = true;
|
||||
this.finished = false;
|
||||
this.isEmpty = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
184
litemall-vue/src/vue/plugins/axios.js → litemall-vue/src/plugins/axios.js
Executable file → Normal file
184
litemall-vue/src/vue/plugins/axios.js → litemall-vue/src/plugins/axios.js
Executable file → Normal file
@@ -1,92 +1,92 @@
|
||||
import axios from 'axios';
|
||||
import _ from 'lodash';
|
||||
import qs from 'qs';
|
||||
import { Dialog, Toast } from 'vant';
|
||||
import Vue from 'vue';
|
||||
Vue.use(Toast);
|
||||
const instance = axios.create({
|
||||
timeout: 5000,
|
||||
baseURL: ''
|
||||
});
|
||||
|
||||
instance.interceptors.request.use(
|
||||
config => {
|
||||
if (!config.headers['X-Litemall-Token']) {
|
||||
config.headers['X-Litemall-Token'] = `${window.localStorage.getItem(
|
||||
'Authorization'
|
||||
) || ''}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
err => Promise.reject(err)
|
||||
);
|
||||
|
||||
instance.interceptors.response.use(
|
||||
res => {
|
||||
let litemall = _.has(res.data, 'errno') && res.data.errno !== 0;
|
||||
let oldmall = _.has(res.data, 'success') && !res.data.success;
|
||||
if (litemall || oldmall) {
|
||||
switch (res.data.code || res.data.errno) {
|
||||
case 422: {
|
||||
const flag = Array.isArray(res.data.data) && res.data.data.length;
|
||||
Dialog.alert({
|
||||
message: flag ? res.data.data[0].message : res.data.message
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 401:
|
||||
break;
|
||||
case 404:
|
||||
break;
|
||||
case 740: {
|
||||
Toast.fail('优惠券已经领取过');
|
||||
break;
|
||||
}
|
||||
case 501: {
|
||||
Toast.fail('请登录');
|
||||
setTimeout(() => {
|
||||
window.location = '#/login/'
|
||||
}, 1500)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Toast.fail(res.data.errmsg)
|
||||
}
|
||||
return Promise.reject(res);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
error => {
|
||||
Dialog.alert({
|
||||
title: '警告',
|
||||
message: error.message
|
||||
});
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
const post = (url, data, config = {}) => instance.post(url, data, config);
|
||||
|
||||
const put = (url, data, config = {}) => instance.put(url, data, config);
|
||||
|
||||
const get = (url, params, config = {}) =>
|
||||
instance.get(url, {
|
||||
params,
|
||||
...config
|
||||
});
|
||||
|
||||
const deleteMethod = (url, config = {}) =>
|
||||
instance({
|
||||
url,
|
||||
method: 'delete',
|
||||
...config
|
||||
});
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.prototype.$reqGet = get;
|
||||
Vue.prototype.$reqPost = post;
|
||||
Vue.prototype.$reqPut = put;
|
||||
Vue.prototype.$reqDel = deleteMethod;
|
||||
}
|
||||
};
|
||||
import axios from 'axios';
|
||||
import _ from 'lodash';
|
||||
import qs from 'qs';
|
||||
import { Dialog, Toast } from 'vant';
|
||||
import Vue from 'vue';
|
||||
Vue.use(Toast);
|
||||
const instance = axios.create({
|
||||
timeout: 5000,
|
||||
baseURL: ''
|
||||
});
|
||||
|
||||
instance.interceptors.request.use(
|
||||
config => {
|
||||
if (!config.headers['X-Litemall-Token']) {
|
||||
config.headers['X-Litemall-Token'] = `${window.localStorage.getItem(
|
||||
'Authorization'
|
||||
) || ''}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
err => Promise.reject(err)
|
||||
);
|
||||
|
||||
instance.interceptors.response.use(
|
||||
res => {
|
||||
let litemall = _.has(res.data, 'errno') && res.data.errno !== 0;
|
||||
let oldmall = _.has(res.data, 'success') && !res.data.success;
|
||||
if (litemall || oldmall) {
|
||||
switch (res.data.code || res.data.errno) {
|
||||
case 422: {
|
||||
const flag = Array.isArray(res.data.data) && res.data.data.length;
|
||||
Dialog.alert({
|
||||
message: flag ? res.data.data[0].message : res.data.message
|
||||
});
|
||||
break;
|
||||
}
|
||||
case 401:
|
||||
break;
|
||||
case 404:
|
||||
break;
|
||||
case 740: {
|
||||
Toast.fail('优惠券已经领取过');
|
||||
break;
|
||||
}
|
||||
case 501: {
|
||||
Toast.fail('请登录');
|
||||
setTimeout(() => {
|
||||
window.location = '#/login/'
|
||||
}, 1500)
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Toast.fail(res.data.errmsg)
|
||||
}
|
||||
return Promise.reject(res);
|
||||
}
|
||||
return res;
|
||||
},
|
||||
error => {
|
||||
Dialog.alert({
|
||||
title: '警告',
|
||||
message: error.message
|
||||
});
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
const post = (url, data, config = {}) => instance.post(url, data, config);
|
||||
|
||||
const put = (url, data, config = {}) => instance.put(url, data, config);
|
||||
|
||||
const get = (url, params, config = {}) =>
|
||||
instance.get(url, {
|
||||
params,
|
||||
...config
|
||||
});
|
||||
|
||||
const deleteMethod = (url, config = {}) =>
|
||||
instance({
|
||||
url,
|
||||
method: 'delete',
|
||||
...config
|
||||
});
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.prototype.$reqGet = get;
|
||||
Vue.prototype.$reqPost = post;
|
||||
Vue.prototype.$reqPut = put;
|
||||
Vue.prototype.$reqDel = deleteMethod;
|
||||
}
|
||||
};
|
||||
14
litemall-vue/src/vue/plugins/vue-countdown.js → litemall-vue/src/plugins/vue-countdown.js
Executable file → Normal file
14
litemall-vue/src/vue/plugins/vue-countdown.js → litemall-vue/src/plugins/vue-countdown.js
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
import VueCountdown from '@xkeshi/vue-countdown';
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.component('countdown', VueCountdown);
|
||||
}
|
||||
};
|
||||
import VueCountdown from '@xkeshi/vue-countdown';
|
||||
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.component('countdown', VueCountdown);
|
||||
}
|
||||
};
|
||||
44
litemall-vue/src/vue/router/home.js → litemall-vue/src/router/home.js
Executable file → Normal file
44
litemall-vue/src/vue/router/home.js → litemall-vue/src/router/home.js
Executable file → Normal file
@@ -1,23 +1,21 @@
|
||||
const Tabbar = () =>
|
||||
import(/* webpackChunkName: "Tabbar" */ '@/vue/components/Tabbar/');
|
||||
import asyncLoader from 'core/async-loader';
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
components: {
|
||||
default: asyncLoader('home/tabbar-home'),
|
||||
tabbar: Tabbar
|
||||
},
|
||||
meta: {
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: {
|
||||
name: 'home'
|
||||
}
|
||||
}
|
||||
];
|
||||
const Tabbar = () => import('@/components/Tabbar/');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
components: {
|
||||
default: () => import('@/views/home/tabbar-home'),
|
||||
tabbar: Tabbar
|
||||
},
|
||||
meta: {
|
||||
keepAlive: true
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: {
|
||||
name: 'home'
|
||||
}
|
||||
}
|
||||
];
|
||||
62
litemall-vue/src/vue/router/index.js → litemall-vue/src/router/index.js
Executable file → Normal file
62
litemall-vue/src/vue/router/index.js → litemall-vue/src/router/index.js
Executable file → Normal file
@@ -1,31 +1,31 @@
|
||||
import Vue from 'vue';
|
||||
import Router from 'vue-router';
|
||||
import { getLocalStorage } from '@/core/utils/local-storage';
|
||||
|
||||
import home from './home';
|
||||
import items from './items';
|
||||
import user from './user';
|
||||
import order from './order';
|
||||
import login from './login';
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
const RouterModel = new Router({
|
||||
routes: [...home, ...items, ...user, ...order, ...login]
|
||||
});
|
||||
|
||||
RouterModel.beforeEach((to, from, next) => {
|
||||
const { Authorization, user_id } = getLocalStorage(
|
||||
'Authorization',
|
||||
'user_id'
|
||||
);
|
||||
if (!Authorization && !user_id) {
|
||||
if (to.meta.login) {
|
||||
next({ name: 'login', query: { redirect: to.name } });
|
||||
return;
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
export default RouterModel;
|
||||
import Vue from 'vue';
|
||||
import Router from 'vue-router';
|
||||
import { getLocalStorage } from '@/utils/local-storage';
|
||||
|
||||
import home from './home';
|
||||
import items from './items';
|
||||
import user from './user';
|
||||
import order from './order';
|
||||
import login from './login';
|
||||
|
||||
Vue.use(Router);
|
||||
|
||||
const RouterModel = new Router({
|
||||
routes: [...home, ...items, ...user, ...order, ...login]
|
||||
});
|
||||
|
||||
RouterModel.beforeEach((to, from, next) => {
|
||||
const { Authorization, user_id } = getLocalStorage(
|
||||
'Authorization',
|
||||
'user_id'
|
||||
);
|
||||
if (!Authorization && !user_id) {
|
||||
if (to.meta.login) {
|
||||
next({ name: 'login', query: { redirect: to.name } });
|
||||
return;
|
||||
}
|
||||
}
|
||||
next();
|
||||
});
|
||||
|
||||
export default RouterModel;
|
||||
96
litemall-vue/src/vue/router/items.js → litemall-vue/src/router/items.js
Executable file → Normal file
96
litemall-vue/src/vue/router/items.js → litemall-vue/src/router/items.js
Executable file → Normal file
@@ -1,49 +1,47 @@
|
||||
import asyncLoader from 'core/async-loader';
|
||||
|
||||
const Tabbar = () =>
|
||||
import(/* webpackChunkName: "Tabbar" */ '@/vue/components/Tabbar/');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/items',
|
||||
name: 'class',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
components: {
|
||||
default: asyncLoader('items/tabbar-class'),
|
||||
tabbar: Tabbar
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/items/search',
|
||||
name: 'search',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
component: asyncLoader('items/search')
|
||||
},
|
||||
{
|
||||
path: '/items/search/result',
|
||||
name: 'search-result',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
component: asyncLoader('items/search-result'),
|
||||
props: route => route.query
|
||||
},
|
||||
{
|
||||
path: '/items/detail/:itemId',
|
||||
name: 'detail',
|
||||
props: true,
|
||||
component: asyncLoader('items/detail')
|
||||
},
|
||||
{
|
||||
path: '/items/list',
|
||||
name: 'list',
|
||||
component: asyncLoader('items/list'),
|
||||
props: route => ({
|
||||
itemClass: +route.query.itemClass
|
||||
})
|
||||
}
|
||||
];
|
||||
const Tabbar = () =>
|
||||
import(/* webpackChunkName: "Tabbar" */ '@/components/Tabbar/');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/items',
|
||||
name: 'class',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
components: {
|
||||
default: () => import('@/views/items/tabbar-class'),
|
||||
tabbar: Tabbar
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/items/search',
|
||||
name: 'search',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
component: () => import('@/views/items/search')
|
||||
},
|
||||
{
|
||||
path: '/items/search/result',
|
||||
name: 'search-result',
|
||||
meta: {
|
||||
keepAlive: true
|
||||
},
|
||||
component: () => import('@/views/items/search-result'),
|
||||
props: route => route.query
|
||||
},
|
||||
{
|
||||
path: '/items/detail/:itemId',
|
||||
name: 'detail',
|
||||
props: true,
|
||||
component: () => import('@/views/items/detail')
|
||||
},
|
||||
{
|
||||
path: '/items/list',
|
||||
name: 'list',
|
||||
component: () => import('@/views/items/list'),
|
||||
props: route => ({
|
||||
itemClass: +route.query.itemClass
|
||||
})
|
||||
}
|
||||
];
|
||||
39
litemall-vue/src/router/login.js
Normal file
39
litemall-vue/src/router/login.js
Normal file
@@ -0,0 +1,39 @@
|
||||
export default [
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: () => import('@/views/login/login')
|
||||
},
|
||||
{
|
||||
path: '/login/registerGetCode',
|
||||
name: 'registerGetCode',
|
||||
component: () => import('@/views/login/register-getCode')
|
||||
},
|
||||
{
|
||||
path: '/login/registerSubmit',
|
||||
name: 'registerSubmit',
|
||||
component: () => import('@/views/login/register-submit')
|
||||
},
|
||||
{
|
||||
path: '/login/registerStatus/:status',
|
||||
name: 'registerStatus',
|
||||
props: true,
|
||||
component: () => import('@/views/login/register-status')
|
||||
},
|
||||
{
|
||||
path: '/login/forget',
|
||||
name: 'forget',
|
||||
component: () => import('@/views/login/forget')
|
||||
},
|
||||
{
|
||||
path: '/login/forget/reset',
|
||||
name: 'forgetReset',
|
||||
component: () => import('@/views/login/forget-reset')
|
||||
},
|
||||
{
|
||||
path: '/login/forget/reset/:status',
|
||||
name: 'forgetStatus',
|
||||
props: true,
|
||||
component: () => import('@/views/login/forget-status')
|
||||
}
|
||||
];
|
||||
41
litemall-vue/src/router/order.js
Normal file
41
litemall-vue/src/router/order.js
Normal file
@@ -0,0 +1,41 @@
|
||||
const Tabbar = () => import('@/components/Tabbar/');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/order',
|
||||
name: 'cart',
|
||||
meta: {
|
||||
login: true
|
||||
},
|
||||
components: {
|
||||
default: () => import('@/views/order/tabbar-cart'),
|
||||
tabbar: Tabbar
|
||||
}
|
||||
},
|
||||
{
|
||||
path: '/order/placeOrderEntity',
|
||||
name: 'placeOrderEntity',
|
||||
component: () => import('@/views/order/place-order-entity')
|
||||
},
|
||||
{
|
||||
path: '/order/orderDetail',
|
||||
name: 'orderDetail',
|
||||
component: () => import('@/views/order/orderDetail')
|
||||
},
|
||||
{
|
||||
path: '/order/placeOrderVirtual',
|
||||
name: 'placeOrderVirtual',
|
||||
component: () => import('@/views/order/place-order-virtual')
|
||||
},
|
||||
{
|
||||
path: '/order/payment',
|
||||
name: 'payment',
|
||||
component: () => import('@/views/order/payment')
|
||||
},
|
||||
{
|
||||
path: '/order/payment/:status',
|
||||
name: 'paymentStatus',
|
||||
component: () => import('@/views/order/payment-status'),
|
||||
props: true
|
||||
}
|
||||
];
|
||||
37
litemall-vue/src/vue/router/user.js → litemall-vue/src/router/user.js
Executable file → Normal file
37
litemall-vue/src/vue/router/user.js → litemall-vue/src/router/user.js
Executable file → Normal file
@@ -1,28 +1,21 @@
|
||||
import asyncLoader from 'core/async-loader';
|
||||
const tab_user = () => import('@/views/user/tabbar-user');
|
||||
const UserCollect = () => import('@/views/user/module-collect');
|
||||
const UserInvitation = () => import('@/views/user/module-invitation');
|
||||
const UserAddress = () => import('@/views/user/module-address');
|
||||
const UserAddressEdit = () => import('@/views/user/module-address-edit');
|
||||
const UserServer = () => import('@/views/user/module-server');
|
||||
|
||||
const tab_user = asyncLoader('user/tabbar-user');
|
||||
const UserCollect = asyncLoader('user/module-collect');
|
||||
const UserInvitation = asyncLoader('user/module-invitation');
|
||||
const UserAddress = asyncLoader('user/module-address');
|
||||
const UserAddressEdit = asyncLoader('user/module-address-edit');
|
||||
const UserServer = asyncLoader('user/module-server');
|
||||
const UserInformation = () => import('@/views/user/user-information-set');
|
||||
const UserInfo_SetBg = () => import('@/views/user/user-information-set/set-bg');
|
||||
const UserInfo_SetMobile = () => import('@/views/user/user-information-set/set-mobile');
|
||||
const UserInfo_SetNickname = () => import('@/views/user/user-information-set/set-nickname');
|
||||
const UserInfo_SetPassword = () => import('@/views/user/user-information-set/set-password');
|
||||
|
||||
const UserInformation = asyncLoader('user/user-information-set');
|
||||
const UserInfo_SetBg = asyncLoader('user/user-information-set/set-bg');
|
||||
const UserInfo_SetMobile = asyncLoader('user/user-information-set/set-mobile');
|
||||
const UserInfo_SetNickname = asyncLoader(
|
||||
'user/user-information-set/set-nickname'
|
||||
);
|
||||
const UserInfo_SetPassword = asyncLoader(
|
||||
'user/user-information-set/set-password'
|
||||
);
|
||||
const UserOrderEntityList = () => import('@/views/user/order-entity-list');
|
||||
const UserOrderEleList = () => import('@/views/user/order-ele-list');
|
||||
const UserRefundList = () => import('@/views/user/refund-list');
|
||||
|
||||
const UserOrderEntityList = asyncLoader('user/order-entity-list');
|
||||
const UserOrderEleList = asyncLoader('user/order-ele-list');
|
||||
const UserRefundList = asyncLoader('user/refund-list');
|
||||
|
||||
const Tabbar = () =>
|
||||
import(/* webpackChunkName: "Tabbar" */ '@/vue/components/Tabbar/');
|
||||
const Tabbar = () => import('@/components/Tabbar/');
|
||||
|
||||
export default [
|
||||
{
|
||||
16
litemall-vue/src/store/getters.js
Normal file
16
litemall-vue/src/store/getters.js
Normal file
@@ -0,0 +1,16 @@
|
||||
const getters = {
|
||||
sidebar: state => state.app.sidebar,
|
||||
language: state => state.app.language,
|
||||
size: state => state.app.size,
|
||||
device: state => state.app.device,
|
||||
|
||||
token: state => state.user.token,
|
||||
avatar: state => state.user.avatar,
|
||||
name: state => state.user.name,
|
||||
introduction: state => state.user.introduction,
|
||||
status: state => state.user.status,
|
||||
roles: state => state.user.roles,
|
||||
perms: state => state.user.perms,
|
||||
setting: state => state.user.setting
|
||||
}
|
||||
export default getters
|
||||
17
litemall-vue/src/store/index.js
Normal file
17
litemall-vue/src/store/index.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import app from './modules/app'
|
||||
import user from './modules/user'
|
||||
import getters from './getters'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const store = new Vuex.Store({
|
||||
modules: {
|
||||
app,
|
||||
user
|
||||
},
|
||||
getters
|
||||
})
|
||||
|
||||
export default store
|
||||
59
litemall-vue/src/store/modules/app.js
Normal file
59
litemall-vue/src/store/modules/app.js
Normal file
@@ -0,0 +1,59 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const app = {
|
||||
state: {
|
||||
sidebar: {
|
||||
opened: !+Cookies.get('sidebarStatus'),
|
||||
withoutAnimation: false
|
||||
},
|
||||
device: 'desktop',
|
||||
language: Cookies.get('language') || 'en',
|
||||
size: Cookies.get('size') || 'medium'
|
||||
},
|
||||
mutations: {
|
||||
TOGGLE_SIDEBAR: state => {
|
||||
if (state.sidebar.opened) {
|
||||
Cookies.set('sidebarStatus', 1)
|
||||
} else {
|
||||
Cookies.set('sidebarStatus', 0)
|
||||
}
|
||||
state.sidebar.opened = !state.sidebar.opened
|
||||
state.sidebar.withoutAnimation = false
|
||||
},
|
||||
CLOSE_SIDEBAR: (state, withoutAnimation) => {
|
||||
Cookies.set('sidebarStatus', 1)
|
||||
state.sidebar.opened = false
|
||||
state.sidebar.withoutAnimation = withoutAnimation
|
||||
},
|
||||
TOGGLE_DEVICE: (state, device) => {
|
||||
state.device = device
|
||||
},
|
||||
SET_LANGUAGE: (state, language) => {
|
||||
state.language = language
|
||||
Cookies.set('language', language)
|
||||
},
|
||||
SET_SIZE: (state, size) => {
|
||||
state.size = size
|
||||
Cookies.set('size', size)
|
||||
}
|
||||
},
|
||||
actions: {
|
||||
toggleSideBar({ commit }) {
|
||||
commit('TOGGLE_SIDEBAR')
|
||||
},
|
||||
closeSideBar({ commit }, { withoutAnimation }) {
|
||||
commit('CLOSE_SIDEBAR', withoutAnimation)
|
||||
},
|
||||
toggleDevice({ commit }, device) {
|
||||
commit('TOGGLE_DEVICE', device)
|
||||
},
|
||||
setLanguage({ commit }, language) {
|
||||
commit('SET_LANGUAGE', language)
|
||||
},
|
||||
setSize({ commit }, size) {
|
||||
commit('SET_SIZE', size)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default app
|
||||
147
litemall-vue/src/store/modules/user.js
Normal file
147
litemall-vue/src/store/modules/user.js
Normal file
@@ -0,0 +1,147 @@
|
||||
import { loginByUsername, logout, getUserInfo } from '@/api/user'
|
||||
import { getToken, setToken, removeToken } from '@/utils/auth'
|
||||
|
||||
const user = {
|
||||
state: {
|
||||
user: '',
|
||||
status: '',
|
||||
code: '',
|
||||
token: getToken(),
|
||||
name: '',
|
||||
avatar: '',
|
||||
introduction: '',
|
||||
roles: [],
|
||||
perms: [],
|
||||
setting: {
|
||||
articlePlatform: []
|
||||
}
|
||||
},
|
||||
|
||||
mutations: {
|
||||
SET_CODE: (state, code) => {
|
||||
state.code = code
|
||||
},
|
||||
SET_TOKEN: (state, token) => {
|
||||
state.token = token
|
||||
},
|
||||
SET_INTRODUCTION: (state, introduction) => {
|
||||
state.introduction = introduction
|
||||
},
|
||||
SET_SETTING: (state, setting) => {
|
||||
state.setting = setting
|
||||
},
|
||||
SET_STATUS: (state, status) => {
|
||||
state.status = status
|
||||
},
|
||||
SET_NAME: (state, name) => {
|
||||
state.name = name
|
||||
},
|
||||
SET_AVATAR: (state, avatar) => {
|
||||
state.avatar = avatar
|
||||
},
|
||||
SET_ROLES: (state, roles) => {
|
||||
state.roles = roles
|
||||
},
|
||||
SET_PERMS: (state, perms) => {
|
||||
state.perms = perms
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
// 用户名登录
|
||||
LoginByUsername({ commit }, userInfo) {
|
||||
const username = userInfo.username.trim()
|
||||
return new Promise((resolve, reject) => {
|
||||
loginByUsername(username, userInfo.password).then(response => {
|
||||
const token = response.data.data
|
||||
commit('SET_TOKEN', token)
|
||||
setToken(token)
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 获取用户信息
|
||||
GetUserInfo({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
getUserInfo(state.token).then(response => {
|
||||
const data = response.data.data
|
||||
|
||||
if (data.perms && data.perms.length > 0) { // 验证返回的perms是否是一个非空数组
|
||||
commit('SET_PERMS', data.perms)
|
||||
} else {
|
||||
reject('getInfo: perms must be a non-null array !')
|
||||
}
|
||||
|
||||
commit('SET_ROLES', data.roles)
|
||||
commit('SET_NAME', data.name)
|
||||
commit('SET_AVATAR', data.avatar)
|
||||
commit('SET_INTRODUCTION', data.introduction)
|
||||
resolve(response)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 第三方验证登录
|
||||
// LoginByThirdparty({ commit, state }, code) {
|
||||
// return new Promise((resolve, reject) => {
|
||||
// commit('SET_CODE', code)
|
||||
// loginByThirdparty(state.status, state.email, state.code).then(response => {
|
||||
// commit('SET_TOKEN', response.data.token)
|
||||
// setToken(response.data.token)
|
||||
// resolve()
|
||||
// }).catch(error => {
|
||||
// reject(error)
|
||||
// })
|
||||
// })
|
||||
// },
|
||||
|
||||
// 登出
|
||||
LogOut({ commit, state }) {
|
||||
return new Promise((resolve, reject) => {
|
||||
logout(state.token).then(() => {
|
||||
commit('SET_TOKEN', '')
|
||||
commit('SET_ROLES', [])
|
||||
commit('SET_PERMS', [])
|
||||
removeToken()
|
||||
resolve()
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
// 前端 登出
|
||||
FedLogOut({ commit }) {
|
||||
return new Promise(resolve => {
|
||||
commit('SET_TOKEN', '')
|
||||
removeToken()
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
|
||||
// 动态修改权限
|
||||
ChangeRoles({ commit, dispatch }, role) {
|
||||
return new Promise(resolve => {
|
||||
commit('SET_TOKEN', role)
|
||||
setToken(role)
|
||||
getUserInfo(role).then(response => {
|
||||
const data = response.data
|
||||
commit('SET_ROLES', data.roles)
|
||||
commit('SET_PERMS', data.perms)
|
||||
commit('SET_NAME', data.name)
|
||||
commit('SET_AVATAR', data.avatar)
|
||||
commit('SET_INTRODUCTION', data.introduction)
|
||||
dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default user
|
||||
15
litemall-vue/src/utils/auth.js
Normal file
15
litemall-vue/src/utils/auth.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import Cookies from 'js-cookie'
|
||||
|
||||
const TokenKey = 'X-Litemall-Admin-Token'
|
||||
|
||||
export function getToken() {
|
||||
return Cookies.get(TokenKey)
|
||||
}
|
||||
|
||||
export function setToken(token) {
|
||||
return Cookies.set(TokenKey, token)
|
||||
}
|
||||
|
||||
export function removeToken() {
|
||||
return Cookies.remove(TokenKey)
|
||||
}
|
||||
52
litemall-vue/src/utils/request.js
Normal file
52
litemall-vue/src/utils/request.js
Normal file
@@ -0,0 +1,52 @@
|
||||
import axios from 'axios'
|
||||
import { Dialog, Toast } from 'vant';
|
||||
|
||||
// create an axios instance
|
||||
const service = axios.create({
|
||||
baseURL: process.env.BASE_API, // api 的 base_url
|
||||
timeout: 5000 // request timeout
|
||||
})
|
||||
|
||||
// request interceptor
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
if (!config.headers['X-Litemall-Token']) {
|
||||
config.headers['X-Litemall-Token'] = `${window.localStorage.getItem(
|
||||
'Authorization'
|
||||
) || ''}`;
|
||||
}
|
||||
return config;
|
||||
},
|
||||
err => Promise.reject(err)
|
||||
)
|
||||
|
||||
// response interceptor
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
const res = response.data
|
||||
|
||||
if (res.errno === 501) {
|
||||
Toast.fail('请登录');
|
||||
setTimeout(() => {
|
||||
window.location = '#/login/'
|
||||
}, 1500)
|
||||
return Promise.reject('error')
|
||||
} else if (res.errno === 502) {
|
||||
Toast.alert('网站内部错误,请联系网站维护人员')
|
||||
return Promise.reject('error')
|
||||
} else if (res.errno !== 0) {
|
||||
// 非5xx的错误属于业务错误,留给具体页面处理
|
||||
return Promise.reject(response)
|
||||
} else {
|
||||
return response
|
||||
}
|
||||
}, error => {
|
||||
console.log('err' + error)// for debug
|
||||
Dialog.alert({
|
||||
title: '警告',
|
||||
message: '登录连接超时'
|
||||
});
|
||||
return Promise.reject(error)
|
||||
})
|
||||
|
||||
export default service
|
||||
62
litemall-vue/src/core/utils/scroll.js → litemall-vue/src/utils/scroll.js
Executable file → Normal file
62
litemall-vue/src/core/utils/scroll.js → litemall-vue/src/utils/scroll.js
Executable file → Normal file
@@ -1,31 +1,31 @@
|
||||
export default {
|
||||
isAttached(element) {
|
||||
let currentNode = element.parentNode;
|
||||
while (currentNode) {
|
||||
if (currentNode.tagName === 'HTML') {
|
||||
return true;
|
||||
}
|
||||
if (currentNode.nodeType === 11) {
|
||||
return false;
|
||||
}
|
||||
currentNode = currentNode.parentNode;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
getScrollLeft(element) {
|
||||
return 'scrollLeft' in element ? element.scrollLeft : element.pageXOffset;
|
||||
},
|
||||
|
||||
getVisibleHeight(element) {
|
||||
return element === window
|
||||
? element.innerHeight
|
||||
: element.getBoundingClientRect().height;
|
||||
},
|
||||
|
||||
getVisibleWidth(element) {
|
||||
return element === window
|
||||
? element.innerWidth
|
||||
: element.getBoundingClientRect().width;
|
||||
}
|
||||
};
|
||||
export default {
|
||||
isAttached(element) {
|
||||
let currentNode = element.parentNode;
|
||||
while (currentNode) {
|
||||
if (currentNode.tagName === 'HTML') {
|
||||
return true;
|
||||
}
|
||||
if (currentNode.nodeType === 11) {
|
||||
return false;
|
||||
}
|
||||
currentNode = currentNode.parentNode;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
getScrollLeft(element) {
|
||||
return 'scrollLeft' in element ? element.scrollLeft : element.pageXOffset;
|
||||
},
|
||||
|
||||
getVisibleHeight(element) {
|
||||
return element === window
|
||||
? element.innerHeight
|
||||
: element.getBoundingClientRect().height;
|
||||
},
|
||||
|
||||
getVisibleWidth(element) {
|
||||
return element === window
|
||||
? element.innerWidth
|
||||
: element.getBoundingClientRect().width;
|
||||
}
|
||||
};
|
||||
24
litemall-vue/src/core/regexp/index.js → litemall-vue/src/utils/validate.js
Executable file → Normal file
24
litemall-vue/src/core/regexp/index.js → litemall-vue/src/utils/validate.js
Executable file → Normal file
@@ -1,12 +1,12 @@
|
||||
export const idCard = /^[1-9]{1}[0-9]{14}$|^[1-9]{1}[0-9]{16}([0-9]|[xX])$/;
|
||||
|
||||
export const mobileReg = /^1[0-9]{10}$/;
|
||||
|
||||
export const address = val => {
|
||||
const value = val.trim();
|
||||
return value.length >= 5 && value.length <= 100;
|
||||
};
|
||||
|
||||
export const userName = /^[a-zA-Z0-9_\u4e00-\u9fa5]{3,20}$/;
|
||||
|
||||
export const emailReg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
|
||||
export const idCard = /^[1-9]{1}[0-9]{14}$|^[1-9]{1}[0-9]{16}([0-9]|[xX])$/;
|
||||
|
||||
export const mobileReg = /^1[0-9]{10}$/;
|
||||
|
||||
export const address = val => {
|
||||
const value = val.trim();
|
||||
return value.length >= 5 && value.length <= 100;
|
||||
};
|
||||
|
||||
export const userName = /^[a-zA-Z0-9_\u4e00-\u9fa5]{3,20}$/;
|
||||
|
||||
export const emailReg = /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -63,11 +63,11 @@
|
||||
<script>
|
||||
import { GOODS_SEARCH } from '@/api/goods';
|
||||
|
||||
import ItemGroup from '@/vue/components/item-group';
|
||||
import ItemCardHori from '@/vue/components/item-card-hori/';
|
||||
import ItemGroup from '@/components/item-group';
|
||||
import ItemCardHori from '@/components/item-card-hori/';
|
||||
import { Search, Tab, Tabs, Popup } from 'vant';
|
||||
// import { throttle } from 'lodash';
|
||||
import InfinityScroll from '@/vue/components/infinity-scroll';
|
||||
import InfinityScroll from '@/components/infinity-scroll';
|
||||
|
||||
export default {
|
||||
name: 'Item-list',
|
||||
|
||||
@@ -32,14 +32,14 @@
|
||||
<script>
|
||||
import { GOODS_SEARCH } from '@/api/goods';
|
||||
|
||||
import ItemGroup from '@/vue/components/item-group/';
|
||||
import IsEmpty from '@/vue/components/is-empty/';
|
||||
import ItemCardHori from '@/vue/components/item-card-hori/';
|
||||
import ItemGroup from '@/components/item-group/';
|
||||
import IsEmpty from '@/components/is-empty/';
|
||||
import ItemCardHori from '@/components/item-card-hori/';
|
||||
import { Search, List } from 'vant';
|
||||
import _ from 'lodash';
|
||||
|
||||
import loadMore from '@/vue/mixin/list-load-more';
|
||||
import scrollFixed from '@/vue/mixin/scroll-fixed';
|
||||
import loadMore from '@/mixin/list-load-more';
|
||||
import scrollFixed from '@/mixin/scroll-fixed';
|
||||
|
||||
export default {
|
||||
name: 'Item-list',
|
||||
|
||||
@@ -1,112 +1,112 @@
|
||||
<template>
|
||||
<div class="tab_class">
|
||||
<div class="tal_class_searchBox">
|
||||
<van-search placeholder="点击前往搜索"/>
|
||||
<div class="tal_class_searchMask" @click="$router.push({ name: 'search' })"></div>
|
||||
</div>
|
||||
<class-tree
|
||||
ref="classTree"
|
||||
class="height-fix42"
|
||||
@nav-click="changeCatalog"
|
||||
@class-click="toItemList"
|
||||
@all-click="toItemList"
|
||||
:list="list"
|
||||
></class-tree>
|
||||
|
||||
<is-empty v-if="isEmpty">抱歉,店主还未上架商品</is-empty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GOODS_CATEGORY, GOODS_CHANNGE_CATEGORY } from '@/api/goods';
|
||||
|
||||
import getLocationParam from 'core/utils/location-param';
|
||||
import { Search } from 'vant';
|
||||
import classTree from './tabbar-class-tree';
|
||||
import IsEmpty from '@/vue/components/is-empty';
|
||||
import _ from 'lodash';
|
||||
import { async } from 'q';
|
||||
|
||||
function getIndex(arr, keyWord) {
|
||||
let index = 0;
|
||||
_.each(arr, (v, k) => {
|
||||
if (v.id === keyWord) {
|
||||
index = k;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return index;
|
||||
}
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
subCategory: [],
|
||||
isEmpty: false
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
|
||||
methods: {
|
||||
initData() {
|
||||
const shop_id = getLocationParam('shop_id');
|
||||
this.$reqGet(`${GOODS_CATEGORY}`).then(res => {
|
||||
this.list = res.data.data.categoryList;
|
||||
this.$refs.classTree.changeList(res.data.data);
|
||||
this.subCategory = res.data.data.currentSubCategory;
|
||||
if (this.subCategory.length === 0) this.isEmpty = true;
|
||||
});
|
||||
},
|
||||
removeNoChild(data) {
|
||||
return data.filter(item => item.children && item.children.length);
|
||||
},
|
||||
changeCatalog(id) {
|
||||
this.$reqGet(`${GOODS_CHANNGE_CATEGORY}${id}`).then(res => {
|
||||
let index = getIndex(this.list, res.data.data.currentCategory.id);
|
||||
this.$refs.classTree.changeList(res.data.data);
|
||||
this.subCategory = res.data.data.currentSubCategory;
|
||||
if (this.subCategory.length === 0) this.isEmpty = true;
|
||||
});
|
||||
},
|
||||
toItemList(id) {
|
||||
this.$router.push({
|
||||
name: 'list',
|
||||
query: { keyword: '', itemClass: id }
|
||||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
[Search.name]: Search,
|
||||
[classTree.name]: classTree,
|
||||
[IsEmpty.name]: IsEmpty
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.tab_class {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.height-fix {
|
||||
padding-bottom: 42px;
|
||||
}
|
||||
|
||||
.tal_class_searchBox {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tal_class_searchMask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="tab_class">
|
||||
<div class="tal_class_searchBox">
|
||||
<van-search placeholder="点击前往搜索"/>
|
||||
<div class="tal_class_searchMask" @click="$router.push({ name: 'search' })"></div>
|
||||
</div>
|
||||
<class-tree
|
||||
ref="classTree"
|
||||
class="height-fix42"
|
||||
@nav-click="changeCatalog"
|
||||
@class-click="toItemList"
|
||||
@all-click="toItemList"
|
||||
:list="list"
|
||||
></class-tree>
|
||||
|
||||
<is-empty v-if="isEmpty">抱歉,店主还未上架商品</is-empty>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { GOODS_CATEGORY, GOODS_CHANNGE_CATEGORY } from '@/api/goods';
|
||||
|
||||
import getLocationParam from '@/utils/location-param';
|
||||
import { Search } from 'vant';
|
||||
import classTree from './tabbar-class-tree';
|
||||
import IsEmpty from '@/components/is-empty';
|
||||
import _ from 'lodash';
|
||||
import { async } from 'q';
|
||||
|
||||
function getIndex(arr, keyWord) {
|
||||
let index = 0;
|
||||
_.each(arr, (v, k) => {
|
||||
if (v.id === keyWord) {
|
||||
index = k;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return index;
|
||||
}
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
subCategory: [],
|
||||
isEmpty: false
|
||||
};
|
||||
},
|
||||
|
||||
created() {
|
||||
this.initData();
|
||||
},
|
||||
|
||||
methods: {
|
||||
initData() {
|
||||
const shop_id = getLocationParam('shop_id');
|
||||
this.$reqGet(`${GOODS_CATEGORY}`).then(res => {
|
||||
this.list = res.data.data.categoryList;
|
||||
this.$refs.classTree.changeList(res.data.data);
|
||||
this.subCategory = res.data.data.currentSubCategory;
|
||||
if (this.subCategory.length === 0) this.isEmpty = true;
|
||||
});
|
||||
},
|
||||
removeNoChild(data) {
|
||||
return data.filter(item => item.children && item.children.length);
|
||||
},
|
||||
changeCatalog(id) {
|
||||
this.$reqGet(`${GOODS_CHANNGE_CATEGORY}${id}`).then(res => {
|
||||
let index = getIndex(this.list, res.data.data.currentCategory.id);
|
||||
this.$refs.classTree.changeList(res.data.data);
|
||||
this.subCategory = res.data.data.currentSubCategory;
|
||||
if (this.subCategory.length === 0) this.isEmpty = true;
|
||||
});
|
||||
},
|
||||
toItemList(id) {
|
||||
this.$router.push({
|
||||
name: 'list',
|
||||
query: { keyword: '', itemClass: id }
|
||||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
[Search.name]: Search,
|
||||
[classTree.name]: classTree,
|
||||
[IsEmpty.name]: IsEmpty
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped>
|
||||
.tab_class {
|
||||
overflow: hidden;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.height-fix {
|
||||
padding-bottom: 42px;
|
||||
}
|
||||
|
||||
.tal_class_searchBox {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.tal_class_searchMask {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 9;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
<template>
|
||||
<md-field-group class="foget_view">
|
||||
<md-field
|
||||
v-model="password"
|
||||
icon="lock"
|
||||
:is-error="isErrow"
|
||||
placeholder="请输入新密码"/>
|
||||
|
||||
<md-field
|
||||
v-model="passwordRepeat"
|
||||
type="password"
|
||||
icon="lock"
|
||||
:is-error="isErrow"
|
||||
placeholder="请再次输入密码" />
|
||||
<div class="red" v-show="isErrow">两次密码输入不一致</div>
|
||||
|
||||
<div class="foget_submit">
|
||||
<van-button size="large" type="danger" @click="submitCode">重置</van-button>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/vue/components/field/';
|
||||
import fieldGroup from '@/vue/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isErrow: true,
|
||||
password: '',
|
||||
passwordRepeat: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitCode() {}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.foget_view {
|
||||
background-color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
div.foget_submit {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<md-field-group class="foget_view">
|
||||
<md-field
|
||||
v-model="password"
|
||||
icon="lock"
|
||||
:is-error="isErrow"
|
||||
placeholder="请输入新密码"/>
|
||||
|
||||
<md-field
|
||||
v-model="passwordRepeat"
|
||||
type="password"
|
||||
icon="lock"
|
||||
:is-error="isErrow"
|
||||
placeholder="请再次输入密码" />
|
||||
<div class="red" v-show="isErrow">两次密码输入不一致</div>
|
||||
|
||||
<div class="foget_submit">
|
||||
<van-button size="large" type="danger" @click="submitCode">重置</van-button>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/components/field/';
|
||||
import fieldGroup from '@/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isErrow: true,
|
||||
password: '',
|
||||
passwordRepeat: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitCode() {}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.foget_view {
|
||||
background-color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
div.foget_submit {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,80 +1,80 @@
|
||||
<template>
|
||||
<md-field-group class="foget_view">
|
||||
<md-field
|
||||
v-model="mobile"
|
||||
icon="mobile"
|
||||
placeholder="请输入手机号"/>
|
||||
|
||||
<md-field
|
||||
v-model="code"
|
||||
icon="lock"
|
||||
placeholder="请输入短信验证码"
|
||||
>
|
||||
<div slot="rightIcon" @click="getCode" class="getCode red">
|
||||
<countdown v-if="counting" :time="60000" @countdownend="countdownend">
|
||||
<template slot-scope="props">{{ +props.seconds || 60 }}秒后获取</template>
|
||||
</countdown>
|
||||
<span v-else>获取验证码</span>
|
||||
</div>
|
||||
</md-field >
|
||||
|
||||
<div class="foget_submit">
|
||||
<van-button size="large" type="danger" @click="submitCode">下一步</van-button>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/vue/components/field/';
|
||||
import fieldGroup from '@/vue/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
counting: false,
|
||||
mobile: '',
|
||||
code: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitCode() {
|
||||
this.$router.push({ name: 'forgetReset' });
|
||||
},
|
||||
getCode() {
|
||||
this.counting = true;
|
||||
},
|
||||
countdownend() {
|
||||
this.counting = false;
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../assets/scss/mixin';
|
||||
|
||||
div.foget_view {
|
||||
background-color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
div.foget_submit {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.getCode {
|
||||
@include one-border(left);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.time_down {
|
||||
color: $red;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<md-field-group class="foget_view">
|
||||
<md-field
|
||||
v-model="mobile"
|
||||
icon="mobile"
|
||||
placeholder="请输入手机号"/>
|
||||
|
||||
<md-field
|
||||
v-model="code"
|
||||
icon="lock"
|
||||
placeholder="请输入短信验证码"
|
||||
>
|
||||
<div slot="rightIcon" @click="getCode" class="getCode red">
|
||||
<countdown v-if="counting" :time="60000" @countdownend="countdownend">
|
||||
<template slot-scope="props">{{ +props.seconds || 60 }}秒后获取</template>
|
||||
</countdown>
|
||||
<span v-else>获取验证码</span>
|
||||
</div>
|
||||
</md-field >
|
||||
|
||||
<div class="foget_submit">
|
||||
<van-button size="large" type="danger" @click="submitCode">下一步</van-button>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/components/field/';
|
||||
import fieldGroup from '@/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
counting: false,
|
||||
mobile: '',
|
||||
code: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitCode() {
|
||||
this.$router.push({ name: 'forgetReset' });
|
||||
},
|
||||
getCode() {
|
||||
this.counting = true;
|
||||
},
|
||||
countdownend() {
|
||||
this.counting = false;
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../assets/scss/mixin';
|
||||
|
||||
div.foget_view {
|
||||
background-color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
div.foget_submit {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.getCode {
|
||||
@include one-border(left);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.time_down {
|
||||
color: $red;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -50,12 +50,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/vue/components/field/';
|
||||
import fieldGroup from '@/vue/components/field-group/';
|
||||
import field from '@/components/field/';
|
||||
import fieldGroup from '@/components/field-group/';
|
||||
|
||||
import { USER_LOGIN, USER_PROFILE } from '@/api/user';
|
||||
import { setLocalStorage } from 'core/utils/local-storage';
|
||||
import { emailReg, mobileReg } from '@/core/regexp';
|
||||
import { loginByUsername, USER_LOGIN, USER_PROFILE } from '@/api/user';
|
||||
import { setLocalStorage } from '@/utils/local-storage';
|
||||
import { emailReg, mobileReg } from '@/utils/validate';
|
||||
|
||||
import { Toast } from 'vant';
|
||||
|
||||
@@ -93,6 +93,7 @@ export default {
|
||||
|
||||
async login() {
|
||||
let loginData = this.getLoginData();
|
||||
loginByUsername(loginData)
|
||||
let { data } = await this.$reqPost(USER_LOGIN, loginData);
|
||||
this.userInfo = data.data.userInfo;
|
||||
console.log(this.userInfo);
|
||||
@@ -139,9 +140,9 @@ export default {
|
||||
|
||||
getLoginData() {
|
||||
const password = this.password;
|
||||
const username = this.getUserType(this.account);
|
||||
const account = this.getUserType(this.account);
|
||||
return {
|
||||
username: this.account,
|
||||
[account]: this.account,
|
||||
password: password
|
||||
};
|
||||
},
|
||||
|
||||
@@ -1,59 +1,59 @@
|
||||
<template>
|
||||
<md-field-group class="register_view">
|
||||
<div>我们将发送验证码到您的手机</div>
|
||||
<md-field
|
||||
v-model="mobile"
|
||||
icon="mobile"
|
||||
placeholder="请输入手机号"/>
|
||||
|
||||
<div class="register_submit">
|
||||
<van-button size="large" type="danger" @click="submitCode">下一步</van-button>
|
||||
</div>
|
||||
|
||||
<div class="register_footer">
|
||||
已有账号?
|
||||
<router-link to="/login" class="red">登录</router-link>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/vue/components/field/';
|
||||
import fieldGroup from '@/vue/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
mobile: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitCode() {
|
||||
this.$router.push({ name: 'registerSubmit' });
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.register_view {
|
||||
background-color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
div.register_submit {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.register_footer {
|
||||
text-align: right;
|
||||
color: $font-color-gray;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<md-field-group class="register_view">
|
||||
<div>我们将发送验证码到您的手机</div>
|
||||
<md-field
|
||||
v-model="mobile"
|
||||
icon="mobile"
|
||||
placeholder="请输入手机号"/>
|
||||
|
||||
<div class="register_submit">
|
||||
<van-button size="large" type="danger" @click="submitCode">下一步</van-button>
|
||||
</div>
|
||||
|
||||
<div class="register_footer">
|
||||
已有账号?
|
||||
<router-link to="/login" class="red">登录</router-link>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/components/field/';
|
||||
import fieldGroup from '@/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
mobile: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
submitCode() {
|
||||
this.$router.push({ name: 'registerSubmit' });
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
div.register_view {
|
||||
background-color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
div.register_submit {
|
||||
padding-top: 30px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.register_footer {
|
||||
text-align: right;
|
||||
color: $font-color-gray;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,78 +1,78 @@
|
||||
<template>
|
||||
<md-field-group class="register_submit">
|
||||
<md-field v-model="code" icon="mobile" placeholder="请输入验证码">
|
||||
<div slot="rightIcon" @click="getCode" class="getCode red">
|
||||
<countdown v-if="counting" :time="60000" @countdownend="countdownend">
|
||||
<template slot-scope="props">{{ +props.seconds || 60 }}秒后获取</template>
|
||||
</countdown>
|
||||
<span v-else>获取验证码</span>
|
||||
</div>
|
||||
</md-field>
|
||||
<md-field v-model="password" icon="lock" placeholder="请输入密码"/>
|
||||
<md-field v-model="repeatPassword" icon="lock" placeholder="请再次确认密码"/>
|
||||
|
||||
<div class="register_submit_btn">
|
||||
<van-button type="danger" size="large" @click="registerSubmit">确定</van-button>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/vue/components/field/';
|
||||
import fieldGroup from '@/vue/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
counting: true,
|
||||
code: '',
|
||||
password: '',
|
||||
repeatPassword: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
registerSubmit() {
|
||||
this.$router.push({
|
||||
name: 'registerStatus',
|
||||
params: { status: 'success' }
|
||||
});
|
||||
},
|
||||
|
||||
getCode() {
|
||||
this.counting = true;
|
||||
},
|
||||
countdownend() {
|
||||
this.counting = false;
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../assets/scss/mixin';
|
||||
|
||||
.register_submit {
|
||||
padding-top: 40px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.register_submit_btn {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.getCode {
|
||||
@include one-border(left);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.time_down {
|
||||
color: $red;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<md-field-group class="register_submit">
|
||||
<md-field v-model="code" icon="mobile" placeholder="请输入验证码">
|
||||
<div slot="rightIcon" @click="getCode" class="getCode red">
|
||||
<countdown v-if="counting" :time="60000" @countdownend="countdownend">
|
||||
<template slot-scope="props">{{ +props.seconds || 60 }}秒后获取</template>
|
||||
</countdown>
|
||||
<span v-else>获取验证码</span>
|
||||
</div>
|
||||
</md-field>
|
||||
<md-field v-model="password" icon="lock" placeholder="请输入密码"/>
|
||||
<md-field v-model="repeatPassword" icon="lock" placeholder="请再次确认密码"/>
|
||||
|
||||
<div class="register_submit_btn">
|
||||
<van-button type="danger" size="large" @click="registerSubmit">确定</van-button>
|
||||
</div>
|
||||
</md-field-group>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import field from '@/components/field/';
|
||||
import fieldGroup from '@/components/field-group/';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
counting: true,
|
||||
code: '',
|
||||
password: '',
|
||||
repeatPassword: ''
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
registerSubmit() {
|
||||
this.$router.push({
|
||||
name: 'registerStatus',
|
||||
params: { status: 'success' }
|
||||
});
|
||||
},
|
||||
|
||||
getCode() {
|
||||
this.counting = true;
|
||||
},
|
||||
countdownend() {
|
||||
this.counting = false;
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[field.name]: field,
|
||||
[fieldGroup.name]: fieldGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../../assets/scss/mixin';
|
||||
|
||||
.register_submit {
|
||||
padding-top: 40px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.register_submit_btn {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.getCode {
|
||||
@include one-border(left);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.time_down {
|
||||
color: $red;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,311 +1,311 @@
|
||||
<template>
|
||||
<div class="tab-cart">
|
||||
<div class="editor_head" v-show="goods.length">
|
||||
<van-icon :name="isEditor ? 'success' : 'editor'"/>
|
||||
<span @click="isEditor = !isEditor">{{isEditor ? '完成' : '编辑'}}</span>
|
||||
</div>
|
||||
<van-checkbox-group @change="toggle" class="card-goods" v-model="checkedGoods">
|
||||
<div v-for="(item, i) in goods" :key="i" class="card-goods__item">
|
||||
<van-checkbox :key="item.id" :name="item.id" v-model="item.checked"></van-checkbox>
|
||||
|
||||
<van-card desc="暂无描述" :num="item.number" :thumb="item.picUrl">
|
||||
<div class="van-card__row" slot="title">
|
||||
<div class="van-card__title">
|
||||
<!-- <van-tag plain type="danger">海淘</van-tag> -->
|
||||
{{item.goodsName}}
|
||||
</div>
|
||||
<div class="van-card__price">{{item.price * 100 | yuan}}</div>
|
||||
</div>
|
||||
<div slot="footer" v-if="isEditor">
|
||||
<van-stepper v-model="item.number" @change="stepperEvent(item,arguments)" disableInput/>
|
||||
</div>
|
||||
<div slot="footer" v-else>添加日期 {{item.addTime}}</div>
|
||||
</van-card>
|
||||
|
||||
<div class="cart_delete" v-if="isEditor" @click="deleteCart(i)">删除</div>
|
||||
</div>
|
||||
</van-checkbox-group>
|
||||
|
||||
<div class="clear_invalid" v-if="goods.length" @click="clearInvalid">
|
||||
<van-icon name="lajitong"/>清除失效商品
|
||||
</div>
|
||||
|
||||
<is-empty v-if="!goods.length">您的购物车空空如也~</is-empty>
|
||||
|
||||
<van-submit-bar
|
||||
style="bottom: 50px"
|
||||
:price="totalPrice"
|
||||
:disabled="!checkedGoods.length"
|
||||
:buttonText="submitBarText"
|
||||
:loading="isSubmit"
|
||||
label="总计"
|
||||
@submit="cartSubmit"
|
||||
>
|
||||
<van-checkbox v-model="allCheckedStatus" @change="setCheckAll" style="padding: 0 10px;">全选</van-checkbox>
|
||||
</van-submit-bar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Checkbox, CheckboxGroup, Card, SubmitBar, Stepper, Tag } from 'vant';
|
||||
|
||||
import isEmpty from '@/vue/components/is-empty/';
|
||||
import _ from 'lodash';
|
||||
import { debug } from 'util';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isEditor: false,
|
||||
checkedAll: false,
|
||||
isSubmit: false,
|
||||
checkedGoods: [],
|
||||
AllGoods: [],
|
||||
allCheckedStatus: false,
|
||||
goods: [],
|
||||
count: 0
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.checkedAll = false;
|
||||
this.isEditor = false;
|
||||
this.isSubmit = false;
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
computed: {
|
||||
submitBarText() {
|
||||
const count = this.count;
|
||||
return this.isEditor ? '删除' : `结算${count ? `(${count})` : ''}`;
|
||||
},
|
||||
totalPrice() {
|
||||
return this.goods.reduce(
|
||||
(total, item) =>
|
||||
total +
|
||||
(this.checkedGoods.indexOf(item.id) !== -1
|
||||
? item.price * item.number * 100
|
||||
: 0),
|
||||
0
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async stepperEvent(item, arg) {
|
||||
let number = arg[0];
|
||||
await this.$reqPost('/wx/cart/update', {
|
||||
number: number,
|
||||
goodsId: item.goodsId,
|
||||
id: item.id,
|
||||
productId: item.productId
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
let { data } = await this.$reqGet('/wx/cart/index');
|
||||
this.goods = data.data.cartList;
|
||||
this.AllGoods = this.getAllList();
|
||||
this.checkedGoods = this.getCheckedList(this.goods);
|
||||
this.count = this.checkedGoods.length;
|
||||
},
|
||||
getAllList() {
|
||||
let result = [];
|
||||
_.each(this.goods, v => {
|
||||
result.push(v.id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
getCheckedList(goods) {
|
||||
let result = [];
|
||||
_.each(goods, v => {
|
||||
if (v.checked) {
|
||||
result.push(v.id);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
async cartSubmit(data) {
|
||||
let productIds = [];
|
||||
let checkedGoods = this.checkedGoods;
|
||||
_.each(checkedGoods, id => {
|
||||
productIds.push(
|
||||
_.find(this.goods, vv => {
|
||||
return id === vv.id;
|
||||
}).productId
|
||||
);
|
||||
});
|
||||
console.log(this.goods);
|
||||
if (this.isEditor) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
message: '确定删除所选商品吗?',
|
||||
cancelButtonText: '再想想'
|
||||
})
|
||||
.then(() => {
|
||||
this.deleteNext(productIds);
|
||||
});
|
||||
} else {
|
||||
// for (check in checkedGoods){
|
||||
// await this.doCheck(productIds);
|
||||
// }
|
||||
let { data } = await this.$reqGet(
|
||||
'/wx/cart/checkout?cartId=0&addressId=0&couponId=0&grouponRulesId=0'
|
||||
);
|
||||
this.isSubmit = true;
|
||||
this.$router.push({ name: 'placeOrderEntity' });
|
||||
}
|
||||
},
|
||||
async doCheck(productIds, isChecked) {
|
||||
// let good = _.find(this.goods, vv => {
|
||||
// return id === vv.id;
|
||||
// })
|
||||
// let productId = good.productId;
|
||||
|
||||
let { data } = await this.$reqPost('/wx/cart/checked', {
|
||||
productIds: productIds,
|
||||
isChecked: isChecked
|
||||
});
|
||||
// if (this.checkedGoods.length == this.AllGoods.length) {
|
||||
// this.allCheckedStatus = true;
|
||||
// }
|
||||
},
|
||||
formatPrice(price) {
|
||||
return (price / 100).toFixed(2);
|
||||
},
|
||||
setCheckAll(val) {
|
||||
if (this.checkedGoods.length === this.AllGoods.length) {
|
||||
this.checkedGoods = [];
|
||||
} else {
|
||||
this.checkedGoods = this.AllGoods;
|
||||
}
|
||||
},
|
||||
deleteCart(o) {
|
||||
let productId = this.goods[o].productId;
|
||||
this.$dialog
|
||||
.confirm({ message: '确定删除所选商品吗', cancelButtonText: '再想想' })
|
||||
.then(() => {
|
||||
// const goodsId = this.goods.splice(i, 1)[0].id;
|
||||
this.$nextTick(() => {
|
||||
this.deleteNext(productId);
|
||||
});
|
||||
});
|
||||
},
|
||||
toggle(index) {
|
||||
let addProductIds = [];
|
||||
_.each(index, v => {
|
||||
let productId = _.find(this.goods, result => {
|
||||
return result.id === v;
|
||||
}).productId;
|
||||
addProductIds.push(productId);
|
||||
});
|
||||
|
||||
let delProductIds = [];
|
||||
_.each(_.difference(this.AllGoods, index), v => {
|
||||
let productId = _.find(this.goods, result => {
|
||||
return result.id === v;
|
||||
}).productId;
|
||||
delProductIds.push(productId);
|
||||
});
|
||||
//没选中的不掉接口
|
||||
if (delProductIds.length > 0) {
|
||||
this.doCheck(delProductIds, 0);
|
||||
}
|
||||
if (addProductIds.length > 0) {
|
||||
this.doCheck(addProductIds, 1);
|
||||
}
|
||||
},
|
||||
async deleteNext(o) {
|
||||
let productIds = [];
|
||||
if (o instanceof Array) {
|
||||
productIds = o;
|
||||
} else {
|
||||
productIds.push(o);
|
||||
}
|
||||
let { data } = await this.$reqPost('/wx/cart/delete', {
|
||||
productIds: productIds
|
||||
});
|
||||
|
||||
this.count = this.count - productIds.length;
|
||||
this.goods = data.data.cartList;
|
||||
|
||||
// this.isEditor = !!this.goods.length;
|
||||
// this.checkedGoods.forEach((goods, i) => {
|
||||
// if (goods.id == goodsId) {
|
||||
// this.checkedGoods.splice(i, 1);
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
},
|
||||
clearInvalid() {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
message: '确定清除所有失效商品吗?',
|
||||
cancelButtonText: '再想想'
|
||||
})
|
||||
.then(() => {
|
||||
this.goods = this.goods.filter(goods => goods.checked);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[Card.name]: Card,
|
||||
[Tag.name]: Tag,
|
||||
[Stepper.name]: Stepper,
|
||||
[isEmpty.name]: isEmpty,
|
||||
[Checkbox.name]: Checkbox,
|
||||
[SubmitBar.name]: SubmitBar,
|
||||
[CheckboxGroup.name]: CheckboxGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../assets/scss/mixin';
|
||||
|
||||
.tab-cart {
|
||||
padding-bottom: 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.editor_head {
|
||||
@include one-border;
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
font-size: $font-size-normal;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.card-goods {
|
||||
background-color: $bg-color;
|
||||
.card-goods__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.cart_delete {
|
||||
line-height: 100px;
|
||||
padding: 0 10px;
|
||||
color: #fff;
|
||||
background-color: $red;
|
||||
}
|
||||
.card-goods__footer {
|
||||
font-size: $font-size-normal;
|
||||
color: $font-color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
.clear_invalid {
|
||||
width: 120px;
|
||||
color: $font-color-gray;
|
||||
border: 1px solid $font-color-gray;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding: 5px 3px;
|
||||
margin-top: 20px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="tab-cart">
|
||||
<div class="editor_head" v-show="goods.length">
|
||||
<van-icon :name="isEditor ? 'success' : 'editor'"/>
|
||||
<span @click="isEditor = !isEditor">{{isEditor ? '完成' : '编辑'}}</span>
|
||||
</div>
|
||||
<van-checkbox-group @change="toggle" class="card-goods" v-model="checkedGoods">
|
||||
<div v-for="(item, i) in goods" :key="i" class="card-goods__item">
|
||||
<van-checkbox :key="item.id" :name="item.id" v-model="item.checked"></van-checkbox>
|
||||
|
||||
<van-card desc="暂无描述" :num="item.number" :thumb="item.picUrl">
|
||||
<div class="van-card__row" slot="title">
|
||||
<div class="van-card__title">
|
||||
<!-- <van-tag plain type="danger">海淘</van-tag> -->
|
||||
{{item.goodsName}}
|
||||
</div>
|
||||
<div class="van-card__price">{{item.price * 100 | yuan}}</div>
|
||||
</div>
|
||||
<div slot="footer" v-if="isEditor">
|
||||
<van-stepper v-model="item.number" @change="stepperEvent(item,arguments)" disableInput/>
|
||||
</div>
|
||||
<div slot="footer" v-else>添加日期 {{item.addTime}}</div>
|
||||
</van-card>
|
||||
|
||||
<div class="cart_delete" v-if="isEditor" @click="deleteCart(i)">删除</div>
|
||||
</div>
|
||||
</van-checkbox-group>
|
||||
|
||||
<div class="clear_invalid" v-if="goods.length" @click="clearInvalid">
|
||||
<van-icon name="lajitong"/>清除失效商品
|
||||
</div>
|
||||
|
||||
<is-empty v-if="!goods.length">您的购物车空空如也~</is-empty>
|
||||
|
||||
<van-submit-bar
|
||||
style="bottom: 50px"
|
||||
:price="totalPrice"
|
||||
:disabled="!checkedGoods.length"
|
||||
:buttonText="submitBarText"
|
||||
:loading="isSubmit"
|
||||
label="总计"
|
||||
@submit="cartSubmit"
|
||||
>
|
||||
<van-checkbox v-model="allCheckedStatus" @change="setCheckAll" style="padding: 0 10px;">全选</van-checkbox>
|
||||
</van-submit-bar>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Checkbox, CheckboxGroup, Card, SubmitBar, Stepper, Tag } from 'vant';
|
||||
|
||||
import isEmpty from '@/components/is-empty/';
|
||||
import _ from 'lodash';
|
||||
import { debug } from 'util';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isEditor: false,
|
||||
checkedAll: false,
|
||||
isSubmit: false,
|
||||
checkedGoods: [],
|
||||
AllGoods: [],
|
||||
allCheckedStatus: false,
|
||||
goods: [],
|
||||
count: 0
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.checkedAll = false;
|
||||
this.isEditor = false;
|
||||
this.isSubmit = false;
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
computed: {
|
||||
submitBarText() {
|
||||
const count = this.count;
|
||||
return this.isEditor ? '删除' : `结算${count ? `(${count})` : ''}`;
|
||||
},
|
||||
totalPrice() {
|
||||
return this.goods.reduce(
|
||||
(total, item) =>
|
||||
total +
|
||||
(this.checkedGoods.indexOf(item.id) !== -1
|
||||
? item.price * item.number * 100
|
||||
: 0),
|
||||
0
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
async stepperEvent(item, arg) {
|
||||
let number = arg[0];
|
||||
await this.$reqPost('/wx/cart/update', {
|
||||
number: number,
|
||||
goodsId: item.goodsId,
|
||||
id: item.id,
|
||||
productId: item.productId
|
||||
});
|
||||
},
|
||||
async init() {
|
||||
let { data } = await this.$reqGet('/wx/cart/index');
|
||||
this.goods = data.data.cartList;
|
||||
this.AllGoods = this.getAllList();
|
||||
this.checkedGoods = this.getCheckedList(this.goods);
|
||||
this.count = this.checkedGoods.length;
|
||||
},
|
||||
getAllList() {
|
||||
let result = [];
|
||||
_.each(this.goods, v => {
|
||||
result.push(v.id);
|
||||
});
|
||||
return result;
|
||||
},
|
||||
getCheckedList(goods) {
|
||||
let result = [];
|
||||
_.each(goods, v => {
|
||||
if (v.checked) {
|
||||
result.push(v.id);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
},
|
||||
async cartSubmit(data) {
|
||||
let productIds = [];
|
||||
let checkedGoods = this.checkedGoods;
|
||||
_.each(checkedGoods, id => {
|
||||
productIds.push(
|
||||
_.find(this.goods, vv => {
|
||||
return id === vv.id;
|
||||
}).productId
|
||||
);
|
||||
});
|
||||
console.log(this.goods);
|
||||
if (this.isEditor) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
message: '确定删除所选商品吗?',
|
||||
cancelButtonText: '再想想'
|
||||
})
|
||||
.then(() => {
|
||||
this.deleteNext(productIds);
|
||||
});
|
||||
} else {
|
||||
// for (check in checkedGoods){
|
||||
// await this.doCheck(productIds);
|
||||
// }
|
||||
let { data } = await this.$reqGet(
|
||||
'/wx/cart/checkout?cartId=0&addressId=0&couponId=0&grouponRulesId=0'
|
||||
);
|
||||
this.isSubmit = true;
|
||||
this.$router.push({ name: 'placeOrderEntity' });
|
||||
}
|
||||
},
|
||||
async doCheck(productIds, isChecked) {
|
||||
// let good = _.find(this.goods, vv => {
|
||||
// return id === vv.id;
|
||||
// })
|
||||
// let productId = good.productId;
|
||||
|
||||
let { data } = await this.$reqPost('/wx/cart/checked', {
|
||||
productIds: productIds,
|
||||
isChecked: isChecked
|
||||
});
|
||||
// if (this.checkedGoods.length == this.AllGoods.length) {
|
||||
// this.allCheckedStatus = true;
|
||||
// }
|
||||
},
|
||||
formatPrice(price) {
|
||||
return (price / 100).toFixed(2);
|
||||
},
|
||||
setCheckAll(val) {
|
||||
if (this.checkedGoods.length === this.AllGoods.length) {
|
||||
this.checkedGoods = [];
|
||||
} else {
|
||||
this.checkedGoods = this.AllGoods;
|
||||
}
|
||||
},
|
||||
deleteCart(o) {
|
||||
let productId = this.goods[o].productId;
|
||||
this.$dialog
|
||||
.confirm({ message: '确定删除所选商品吗', cancelButtonText: '再想想' })
|
||||
.then(() => {
|
||||
// const goodsId = this.goods.splice(i, 1)[0].id;
|
||||
this.$nextTick(() => {
|
||||
this.deleteNext(productId);
|
||||
});
|
||||
});
|
||||
},
|
||||
toggle(index) {
|
||||
let addProductIds = [];
|
||||
_.each(index, v => {
|
||||
let productId = _.find(this.goods, result => {
|
||||
return result.id === v;
|
||||
}).productId;
|
||||
addProductIds.push(productId);
|
||||
});
|
||||
|
||||
let delProductIds = [];
|
||||
_.each(_.difference(this.AllGoods, index), v => {
|
||||
let productId = _.find(this.goods, result => {
|
||||
return result.id === v;
|
||||
}).productId;
|
||||
delProductIds.push(productId);
|
||||
});
|
||||
//没选中的不掉接口
|
||||
if (delProductIds.length > 0) {
|
||||
this.doCheck(delProductIds, 0);
|
||||
}
|
||||
if (addProductIds.length > 0) {
|
||||
this.doCheck(addProductIds, 1);
|
||||
}
|
||||
},
|
||||
async deleteNext(o) {
|
||||
let productIds = [];
|
||||
if (o instanceof Array) {
|
||||
productIds = o;
|
||||
} else {
|
||||
productIds.push(o);
|
||||
}
|
||||
let { data } = await this.$reqPost('/wx/cart/delete', {
|
||||
productIds: productIds
|
||||
});
|
||||
|
||||
this.count = this.count - productIds.length;
|
||||
this.goods = data.data.cartList;
|
||||
|
||||
// this.isEditor = !!this.goods.length;
|
||||
// this.checkedGoods.forEach((goods, i) => {
|
||||
// if (goods.id == goodsId) {
|
||||
// this.checkedGoods.splice(i, 1);
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
},
|
||||
clearInvalid() {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
message: '确定清除所有失效商品吗?',
|
||||
cancelButtonText: '再想想'
|
||||
})
|
||||
.then(() => {
|
||||
this.goods = this.goods.filter(goods => goods.checked);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[Card.name]: Card,
|
||||
[Tag.name]: Tag,
|
||||
[Stepper.name]: Stepper,
|
||||
[isEmpty.name]: isEmpty,
|
||||
[Checkbox.name]: Checkbox,
|
||||
[SubmitBar.name]: SubmitBar,
|
||||
[CheckboxGroup.name]: CheckboxGroup
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../assets/scss/mixin';
|
||||
|
||||
.tab-cart {
|
||||
padding-bottom: 50px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.editor_head {
|
||||
@include one-border;
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
font-size: $font-size-normal;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.card-goods {
|
||||
background-color: $bg-color;
|
||||
.card-goods__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.cart_delete {
|
||||
line-height: 100px;
|
||||
padding: 0 10px;
|
||||
color: #fff;
|
||||
background-color: $red;
|
||||
}
|
||||
.card-goods__footer {
|
||||
font-size: $font-size-normal;
|
||||
color: $font-color-gray;
|
||||
}
|
||||
}
|
||||
|
||||
.clear_invalid {
|
||||
width: 120px;
|
||||
color: $font-color-gray;
|
||||
border: 1px solid $font-color-gray;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
padding: 5px 3px;
|
||||
margin-top: 20px;
|
||||
border-radius: 3px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,13 +40,13 @@
|
||||
<script>
|
||||
import { GOODS_COLLECT_LIST } from '@/api/user';
|
||||
|
||||
import ItemGroup from '@/vue/components/item-group/';
|
||||
import ItemCardHori from '@/vue/components/item-card-hori/';
|
||||
import IsEmpty from '@/vue/components/is-empty/';
|
||||
import ItemGroup from '@/components/item-group/';
|
||||
import ItemCardHori from '@/components/item-card-hori/';
|
||||
import IsEmpty from '@/components/is-empty/';
|
||||
import { Search, List } from 'vant';
|
||||
|
||||
import loadMore from '@/vue/mixin/list-load-more';
|
||||
import scrollFixed from '@/vue/mixin/scroll-fixed';
|
||||
import loadMore from '@/mixin/list-load-more';
|
||||
import scrollFixed from '@/mixin/scroll-fixed';
|
||||
|
||||
export default {
|
||||
mixins: [loadMore, scrollFixed],
|
||||
|
||||
@@ -1,198 +1,198 @@
|
||||
<template>
|
||||
<div class="order_list no-pad-bottom over-hide">
|
||||
<van-tabs v-model="activeIndex" :swipe-threshold="5" @click="handleTabClick">
|
||||
<van-tab v-for="(tab, tabIndex) in tabsItem" :title="tab.name" :key="tab.type">
|
||||
<InfinityScroll
|
||||
class="full-page scroll-wrap height-fix42"
|
||||
:beforeRequest="beforeRequest"
|
||||
:apiUrl="listApi"
|
||||
@onLoad="onLoad(tabIndex, $event)"
|
||||
>
|
||||
<van-panel
|
||||
v-for="(el, i) in tab.items"
|
||||
class="order_list--panel"
|
||||
:key="el.id"
|
||||
:title="'订单编号: ' + el.id"
|
||||
:status="getStatusText(el.status)"
|
||||
>
|
||||
<div>
|
||||
<van-card
|
||||
v-for="(goods, i) in el.serviceItems"
|
||||
class="order_list--van-card"
|
||||
:key="i"
|
||||
:title="goods.item_name"
|
||||
:desc="goods.sku_props_str"
|
||||
:num="10000"
|
||||
:price="(goods.price / 100).toFixed(2)"
|
||||
:thumb="goods.pic_url"
|
||||
/>
|
||||
<div class="order_list--total">合计: {{el.total_fee | yuan}}(含运费{{el.post_fee | yuan}})</div>
|
||||
</div>
|
||||
<component
|
||||
slot="footer"
|
||||
:is="'status' + el.status"
|
||||
@delete-order="delOrder(i)"
|
||||
@pay="toPay(el.id)"
|
||||
@cancel="cancelOrder(i)"
|
||||
/>
|
||||
</van-panel>
|
||||
</InfinityScroll>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ELE_COUPON_LIST } from '@/api/order';
|
||||
|
||||
import { Tab, Tabs, Panel, Card, List } from 'vant';
|
||||
import status10 from './handle-status-10';
|
||||
import status40 from './handle-status-40';
|
||||
import status60 from './handle-status-60';
|
||||
import status70 from './handle-status-70';
|
||||
import status100 from './handle-status-100';
|
||||
import status110 from './handle-status-110';
|
||||
import status120 from './handle-status-120';
|
||||
import _ from 'lodash';
|
||||
|
||||
import InfinityScroll from '@/vue/components/infinity-scroll';
|
||||
|
||||
const STATUS_TEXT = {
|
||||
10: '待付款',
|
||||
40: '已完成',
|
||||
60: '已关闭',
|
||||
70: '已关闭',
|
||||
100: '未使用',
|
||||
110: '已使用',
|
||||
120: '已退款'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'order-list',
|
||||
|
||||
props: {
|
||||
active: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
const activeIndex = this.active;
|
||||
return {
|
||||
listApi: ELE_COUPON_LIST,
|
||||
shop_id: 1,
|
||||
activeIndex,
|
||||
tabsItem: [
|
||||
{
|
||||
name: '全部',
|
||||
status: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
status: 10,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待使用',
|
||||
status: 100,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '已使用',
|
||||
status: 110,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '退款成功',
|
||||
status: 120,
|
||||
items: []
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onLoad(i, items) {
|
||||
new Array(10).fill(1).forEach(() => {
|
||||
items.push(_.cloneDeep(_.last(items)));
|
||||
});
|
||||
this.tabsItem[i].items.push(...items);
|
||||
},
|
||||
beforeRequest() {
|
||||
const i = this.activeIndex;
|
||||
const status = this.tabsItem[i].status;
|
||||
const { shop_id } = this;
|
||||
return {
|
||||
params: {
|
||||
status,
|
||||
shop_id
|
||||
}
|
||||
};
|
||||
},
|
||||
delOrder(i) {
|
||||
this.$dialog.confirm({ message: '确定删除订单?' }).then(() => {
|
||||
this.items.splice(i, 1);
|
||||
this.$toast('已删除');
|
||||
});
|
||||
},
|
||||
async cancelOrder(i) {
|
||||
this.$dialog
|
||||
.confirm({ message: '确定要取消该订单吗?' })
|
||||
.then(() => {
|
||||
this.items.splice(i, 1);
|
||||
this.$toast('已取消该订单');
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
toPay(id) {
|
||||
this.$router.push({ name: 'payment', params: { order_id: id } });
|
||||
},
|
||||
handleTabClick(index) {
|
||||
this.$router.replace({
|
||||
name: 'user-order-ele-list',
|
||||
params: { status: index }
|
||||
});
|
||||
},
|
||||
getStatusText(status) {
|
||||
return STATUS_TEXT[status] || '';
|
||||
}
|
||||
},
|
||||
components: {
|
||||
[Tab.name]: Tab,
|
||||
[Tabs.name]: Tabs,
|
||||
[Panel.name]: Panel,
|
||||
[Card.name]: Card,
|
||||
[List.name]: List,
|
||||
InfinityScroll,
|
||||
status10,
|
||||
status40,
|
||||
status60,
|
||||
status70,
|
||||
status100,
|
||||
status110,
|
||||
status120
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_list {
|
||||
&--footer_btn {
|
||||
text-align: right;
|
||||
}
|
||||
&--panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--van-card {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&--total {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="order_list no-pad-bottom over-hide">
|
||||
<van-tabs v-model="activeIndex" :swipe-threshold="5" @click="handleTabClick">
|
||||
<van-tab v-for="(tab, tabIndex) in tabsItem" :title="tab.name" :key="tab.type">
|
||||
<InfinityScroll
|
||||
class="full-page scroll-wrap height-fix42"
|
||||
:beforeRequest="beforeRequest"
|
||||
:apiUrl="listApi"
|
||||
@onLoad="onLoad(tabIndex, $event)"
|
||||
>
|
||||
<van-panel
|
||||
v-for="(el, i) in tab.items"
|
||||
class="order_list--panel"
|
||||
:key="el.id"
|
||||
:title="'订单编号: ' + el.id"
|
||||
:status="getStatusText(el.status)"
|
||||
>
|
||||
<div>
|
||||
<van-card
|
||||
v-for="(goods, i) in el.serviceItems"
|
||||
class="order_list--van-card"
|
||||
:key="i"
|
||||
:title="goods.item_name"
|
||||
:desc="goods.sku_props_str"
|
||||
:num="10000"
|
||||
:price="(goods.price / 100).toFixed(2)"
|
||||
:thumb="goods.pic_url"
|
||||
/>
|
||||
<div class="order_list--total">合计: {{el.total_fee | yuan}}(含运费{{el.post_fee | yuan}})</div>
|
||||
</div>
|
||||
<component
|
||||
slot="footer"
|
||||
:is="'status' + el.status"
|
||||
@delete-order="delOrder(i)"
|
||||
@pay="toPay(el.id)"
|
||||
@cancel="cancelOrder(i)"
|
||||
/>
|
||||
</van-panel>
|
||||
</InfinityScroll>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ELE_COUPON_LIST } from '@/api/order';
|
||||
|
||||
import { Tab, Tabs, Panel, Card, List } from 'vant';
|
||||
import status10 from './handle-status-10';
|
||||
import status40 from './handle-status-40';
|
||||
import status60 from './handle-status-60';
|
||||
import status70 from './handle-status-70';
|
||||
import status100 from './handle-status-100';
|
||||
import status110 from './handle-status-110';
|
||||
import status120 from './handle-status-120';
|
||||
import _ from 'lodash';
|
||||
|
||||
import InfinityScroll from '@/components/infinity-scroll';
|
||||
|
||||
const STATUS_TEXT = {
|
||||
10: '待付款',
|
||||
40: '已完成',
|
||||
60: '已关闭',
|
||||
70: '已关闭',
|
||||
100: '未使用',
|
||||
110: '已使用',
|
||||
120: '已退款'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'order-list',
|
||||
|
||||
props: {
|
||||
active: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
const activeIndex = this.active;
|
||||
return {
|
||||
listApi: ELE_COUPON_LIST,
|
||||
shop_id: 1,
|
||||
activeIndex,
|
||||
tabsItem: [
|
||||
{
|
||||
name: '全部',
|
||||
status: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
status: 10,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待使用',
|
||||
status: 100,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '已使用',
|
||||
status: 110,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '退款成功',
|
||||
status: 120,
|
||||
items: []
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onLoad(i, items) {
|
||||
new Array(10).fill(1).forEach(() => {
|
||||
items.push(_.cloneDeep(_.last(items)));
|
||||
});
|
||||
this.tabsItem[i].items.push(...items);
|
||||
},
|
||||
beforeRequest() {
|
||||
const i = this.activeIndex;
|
||||
const status = this.tabsItem[i].status;
|
||||
const { shop_id } = this;
|
||||
return {
|
||||
params: {
|
||||
status,
|
||||
shop_id
|
||||
}
|
||||
};
|
||||
},
|
||||
delOrder(i) {
|
||||
this.$dialog.confirm({ message: '确定删除订单?' }).then(() => {
|
||||
this.items.splice(i, 1);
|
||||
this.$toast('已删除');
|
||||
});
|
||||
},
|
||||
async cancelOrder(i) {
|
||||
this.$dialog
|
||||
.confirm({ message: '确定要取消该订单吗?' })
|
||||
.then(() => {
|
||||
this.items.splice(i, 1);
|
||||
this.$toast('已取消该订单');
|
||||
})
|
||||
.catch(() => {});
|
||||
},
|
||||
toPay(id) {
|
||||
this.$router.push({ name: 'payment', params: { order_id: id } });
|
||||
},
|
||||
handleTabClick(index) {
|
||||
this.$router.replace({
|
||||
name: 'user-order-ele-list',
|
||||
params: { status: index }
|
||||
});
|
||||
},
|
||||
getStatusText(status) {
|
||||
return STATUS_TEXT[status] || '';
|
||||
}
|
||||
},
|
||||
components: {
|
||||
[Tab.name]: Tab,
|
||||
[Tabs.name]: Tabs,
|
||||
[Panel.name]: Panel,
|
||||
[Card.name]: Card,
|
||||
[List.name]: List,
|
||||
InfinityScroll,
|
||||
status10,
|
||||
status40,
|
||||
status60,
|
||||
status70,
|
||||
status100,
|
||||
status110,
|
||||
status120
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_list {
|
||||
&--footer_btn {
|
||||
text-align: right;
|
||||
}
|
||||
&--panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--van-card {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&--total {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,243 +1,243 @@
|
||||
<template>
|
||||
<div class="order_list over-hide">
|
||||
<van-tabs v-model="activeIndex" :swipe-threshold="5" @click="handleTabClick">
|
||||
<van-tab
|
||||
v-for="(tab, tabIndex) in tabsItem"
|
||||
:title="tab.name"
|
||||
@click="changeTab"
|
||||
:key="tab.type"
|
||||
>
|
||||
<InfinityScroll
|
||||
class="full-page scroll-wrap height-fix42"
|
||||
:beforeRequest="beforeRequest"
|
||||
:apiUrl="listApi"
|
||||
@onLoad="onLoad(tabIndex, $event)"
|
||||
>
|
||||
<van-panel
|
||||
v-for="(el, i) in orderArr"
|
||||
class="order_list--panel"
|
||||
:key="i"
|
||||
:title="'订单编号: ' + el.orderSn"
|
||||
:status="el.orderStatusText"
|
||||
>
|
||||
<div>
|
||||
<van-card
|
||||
v-for="(goods, goodsI) in el.goodsList"
|
||||
class="order_list--van-card"
|
||||
:key="goodsI"
|
||||
:title="goods.goodsName"
|
||||
:desc="goods.goodsName"
|
||||
:num="goods.number"
|
||||
:thumb="goods.picUrl"
|
||||
@click.native="toOrderDetail(el.id)"
|
||||
/>
|
||||
<div
|
||||
class="order_list--total"
|
||||
>合计: {{el.actualPrice * 100 | yuan}}(含运费{{el.post_fee | yuan}})</div>
|
||||
</div>
|
||||
<component
|
||||
slot="footer"
|
||||
:is="'status' + el.status"
|
||||
:reminder="el.is_can_reminder"
|
||||
@handle="actionHandle($event, i)"
|
||||
/>
|
||||
</van-panel>
|
||||
</InfinityScroll>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ORDER_LIST } from '@/api/order';
|
||||
|
||||
import { Tab, Tabs, Panel, Card, List } from 'vant';
|
||||
import status10 from './handle-status-10';
|
||||
import status20 from './handle-status-20';
|
||||
import status25 from './handle-status-25';
|
||||
import status30 from './handle-status-30';
|
||||
import status40 from './handle-status-40';
|
||||
import status50 from './handle-status-50';
|
||||
import status60 from './handle-status-60';
|
||||
import status70 from './handle-status-70';
|
||||
|
||||
import InfinityScroll from '@/vue/components/infinity-scroll';
|
||||
|
||||
const STATUS_TEXT = {
|
||||
10: '待付款',
|
||||
20: '待发货',
|
||||
25: '部分发货',
|
||||
30: '待收货',
|
||||
40: '已完成',
|
||||
50: '退款成功',
|
||||
60: '交易关闭',
|
||||
70: '交易关闭'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'order-list',
|
||||
|
||||
props: {
|
||||
active: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
const activeIndex = this.active;
|
||||
return {
|
||||
listApi: ORDER_LIST,
|
||||
shop_id: 1,
|
||||
activeIndex,
|
||||
tabsItem: [
|
||||
{
|
||||
name: '全部',
|
||||
status: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
status: 10,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
status: 20,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
status: 30,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '已完成',
|
||||
status: 40,
|
||||
items: []
|
||||
}
|
||||
],
|
||||
orderArr: []
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async init(i) {
|
||||
let { data } = await this.$reqGet(
|
||||
`/wx/order/list?showType=${i || this.active || '0'}`
|
||||
);
|
||||
this.orderArr = data.data.data;
|
||||
},
|
||||
onLoad(i, items) {
|
||||
this.tabsItem[i].items.push(...items);
|
||||
},
|
||||
beforeRequest() {
|
||||
const i = this.activeIndex;
|
||||
const status = this.tabsItem[i].status;
|
||||
const { shop_id } = this;
|
||||
return {
|
||||
params: {
|
||||
status,
|
||||
shop_id
|
||||
}
|
||||
};
|
||||
},
|
||||
async delOrder(i) {
|
||||
await this.$dialog.confirm({ message: '确定要删除该订单吗?' });
|
||||
this.items.splice(i, 1);
|
||||
this.$toast('已删除该订单');
|
||||
},
|
||||
async cancelOrder(i) {
|
||||
await this.$dialog.confirm({ message: '确定要取消该订单吗?' });
|
||||
if (this.activeIndex == 0) {
|
||||
this.items[i].status = 60;
|
||||
} else {
|
||||
this.items.splice(i, 1);
|
||||
}
|
||||
this.$toast('已取消该订单');
|
||||
},
|
||||
async receiptOrder(i) {
|
||||
await this.$dialog.confirm({
|
||||
message: '请确认收到货物, 确认收货后无法撤销!'
|
||||
});
|
||||
this.items[i].status = 40;
|
||||
this.$toast('已确认收货');
|
||||
},
|
||||
reminderOrder(i) {
|
||||
this.items[i].is_can_reminder = false;
|
||||
this.$toast('已提醒卖家发货, 请耐心等待哦~');
|
||||
},
|
||||
toPay(i) {
|
||||
const id = this.items[i].id;
|
||||
this.$router.push({ name: 'payment', params: { order_id: id } });
|
||||
},
|
||||
handleTabClick(index) {
|
||||
console.log(6666666);
|
||||
// console.log(index);
|
||||
// await this.init(i);
|
||||
this.$router.replace({
|
||||
name: 'user-order-list',
|
||||
params: { active: index }
|
||||
});
|
||||
},
|
||||
getStatusText(status) {
|
||||
return STATUS_TEXT[status] || '';
|
||||
},
|
||||
toOrderDetail(id) {
|
||||
this.$router.push({
|
||||
name: `orderDetail`,
|
||||
query: { cartId: 0, orderId: id }
|
||||
});
|
||||
},
|
||||
actionHandle(handle, i) {
|
||||
this[handle] && this[handle](i);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
active(val) {
|
||||
this.init(val);
|
||||
val && !this.address_list.length && this.getAddress();
|
||||
}
|
||||
},
|
||||
components: {
|
||||
InfinityScroll,
|
||||
[Tab.name]: Tab,
|
||||
[Tabs.name]: Tabs,
|
||||
[Panel.name]: Panel,
|
||||
[Card.name]: Card,
|
||||
[List.name]: List,
|
||||
status10,
|
||||
status20,
|
||||
status25,
|
||||
status30,
|
||||
status40,
|
||||
status50,
|
||||
status60,
|
||||
status70
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_list {
|
||||
padding-bottom: 0;
|
||||
overflow-y: hidden;
|
||||
&--footer_btn {
|
||||
text-align: right;
|
||||
}
|
||||
&--panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--van-card {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&--total {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="order_list over-hide">
|
||||
<van-tabs v-model="activeIndex" :swipe-threshold="5" @click="handleTabClick">
|
||||
<van-tab
|
||||
v-for="(tab, tabIndex) in tabsItem"
|
||||
:title="tab.name"
|
||||
@click="changeTab"
|
||||
:key="tab.type"
|
||||
>
|
||||
<InfinityScroll
|
||||
class="full-page scroll-wrap height-fix42"
|
||||
:beforeRequest="beforeRequest"
|
||||
:apiUrl="listApi"
|
||||
@onLoad="onLoad(tabIndex, $event)"
|
||||
>
|
||||
<van-panel
|
||||
v-for="(el, i) in orderArr"
|
||||
class="order_list--panel"
|
||||
:key="i"
|
||||
:title="'订单编号: ' + el.orderSn"
|
||||
:status="el.orderStatusText"
|
||||
>
|
||||
<div>
|
||||
<van-card
|
||||
v-for="(goods, goodsI) in el.goodsList"
|
||||
class="order_list--van-card"
|
||||
:key="goodsI"
|
||||
:title="goods.goodsName"
|
||||
:desc="goods.goodsName"
|
||||
:num="goods.number"
|
||||
:thumb="goods.picUrl"
|
||||
@click.native="toOrderDetail(el.id)"
|
||||
/>
|
||||
<div
|
||||
class="order_list--total"
|
||||
>合计: {{el.actualPrice * 100 | yuan}}(含运费{{el.post_fee | yuan}})</div>
|
||||
</div>
|
||||
<component
|
||||
slot="footer"
|
||||
:is="'status' + el.status"
|
||||
:reminder="el.is_can_reminder"
|
||||
@handle="actionHandle($event, i)"
|
||||
/>
|
||||
</van-panel>
|
||||
</InfinityScroll>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ORDER_LIST } from '@/api/order';
|
||||
|
||||
import { Tab, Tabs, Panel, Card, List } from 'vant';
|
||||
import status10 from './handle-status-10';
|
||||
import status20 from './handle-status-20';
|
||||
import status25 from './handle-status-25';
|
||||
import status30 from './handle-status-30';
|
||||
import status40 from './handle-status-40';
|
||||
import status50 from './handle-status-50';
|
||||
import status60 from './handle-status-60';
|
||||
import status70 from './handle-status-70';
|
||||
|
||||
import InfinityScroll from '@/components/infinity-scroll';
|
||||
|
||||
const STATUS_TEXT = {
|
||||
10: '待付款',
|
||||
20: '待发货',
|
||||
25: '部分发货',
|
||||
30: '待收货',
|
||||
40: '已完成',
|
||||
50: '退款成功',
|
||||
60: '交易关闭',
|
||||
70: '交易关闭'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'order-list',
|
||||
|
||||
props: {
|
||||
active: {
|
||||
type: [String, Number],
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.init();
|
||||
},
|
||||
data() {
|
||||
const activeIndex = this.active;
|
||||
return {
|
||||
listApi: ORDER_LIST,
|
||||
shop_id: 1,
|
||||
activeIndex,
|
||||
tabsItem: [
|
||||
{
|
||||
name: '全部',
|
||||
status: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待付款',
|
||||
status: 10,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待发货',
|
||||
status: 20,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '待收货',
|
||||
status: 30,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '已完成',
|
||||
status: 40,
|
||||
items: []
|
||||
}
|
||||
],
|
||||
orderArr: []
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
async init(i) {
|
||||
let { data } = await this.$reqGet(
|
||||
`/wx/order/list?showType=${i || this.active || '0'}`
|
||||
);
|
||||
this.orderArr = data.data.data;
|
||||
},
|
||||
onLoad(i, items) {
|
||||
this.tabsItem[i].items.push(...items);
|
||||
},
|
||||
beforeRequest() {
|
||||
const i = this.activeIndex;
|
||||
const status = this.tabsItem[i].status;
|
||||
const { shop_id } = this;
|
||||
return {
|
||||
params: {
|
||||
status,
|
||||
shop_id
|
||||
}
|
||||
};
|
||||
},
|
||||
async delOrder(i) {
|
||||
await this.$dialog.confirm({ message: '确定要删除该订单吗?' });
|
||||
this.items.splice(i, 1);
|
||||
this.$toast('已删除该订单');
|
||||
},
|
||||
async cancelOrder(i) {
|
||||
await this.$dialog.confirm({ message: '确定要取消该订单吗?' });
|
||||
if (this.activeIndex == 0) {
|
||||
this.items[i].status = 60;
|
||||
} else {
|
||||
this.items.splice(i, 1);
|
||||
}
|
||||
this.$toast('已取消该订单');
|
||||
},
|
||||
async receiptOrder(i) {
|
||||
await this.$dialog.confirm({
|
||||
message: '请确认收到货物, 确认收货后无法撤销!'
|
||||
});
|
||||
this.items[i].status = 40;
|
||||
this.$toast('已确认收货');
|
||||
},
|
||||
reminderOrder(i) {
|
||||
this.items[i].is_can_reminder = false;
|
||||
this.$toast('已提醒卖家发货, 请耐心等待哦~');
|
||||
},
|
||||
toPay(i) {
|
||||
const id = this.items[i].id;
|
||||
this.$router.push({ name: 'payment', params: { order_id: id } });
|
||||
},
|
||||
handleTabClick(index) {
|
||||
console.log(6666666);
|
||||
// console.log(index);
|
||||
// await this.init(i);
|
||||
this.$router.replace({
|
||||
name: 'user-order-list',
|
||||
params: { active: index }
|
||||
});
|
||||
},
|
||||
getStatusText(status) {
|
||||
return STATUS_TEXT[status] || '';
|
||||
},
|
||||
toOrderDetail(id) {
|
||||
this.$router.push({
|
||||
name: `orderDetail`,
|
||||
query: { cartId: 0, orderId: id }
|
||||
});
|
||||
},
|
||||
actionHandle(handle, i) {
|
||||
this[handle] && this[handle](i);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
active(val) {
|
||||
this.init(val);
|
||||
val && !this.address_list.length && this.getAddress();
|
||||
}
|
||||
},
|
||||
components: {
|
||||
InfinityScroll,
|
||||
[Tab.name]: Tab,
|
||||
[Tabs.name]: Tabs,
|
||||
[Panel.name]: Panel,
|
||||
[Card.name]: Card,
|
||||
[List.name]: List,
|
||||
status10,
|
||||
status20,
|
||||
status25,
|
||||
status30,
|
||||
status40,
|
||||
status50,
|
||||
status60,
|
||||
status70
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_list {
|
||||
padding-bottom: 0;
|
||||
overflow-y: hidden;
|
||||
&--footer_btn {
|
||||
text-align: right;
|
||||
}
|
||||
&--panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--van-card {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&--total {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,156 +1,156 @@
|
||||
<template>
|
||||
<div class="order_list">
|
||||
<van-tabs sticky :active="activeIndex" :swipe-threshold="5" @click="handleTabClick">
|
||||
<van-tab v-for="(tab, tabIndex) in tabsItem" :title="tab.name" :key="tab.type">
|
||||
<InfinityScroll
|
||||
class="full-page scroll-wrap"
|
||||
:beforeRequest="beforeRequest"
|
||||
:apiUrl="listApi"
|
||||
@onLoad="onLoad(tabIndex, $event)"
|
||||
>
|
||||
<van-panel
|
||||
v-for="(el, i) in tab.items"
|
||||
class="order_list--panel"
|
||||
:key="i"
|
||||
:title="'订单编号: ' + el.id"
|
||||
:status="getStatusText(el.status)"
|
||||
>
|
||||
<div>
|
||||
<van-card
|
||||
class="order_list--van-card"
|
||||
:key="i"
|
||||
:title="el.orderItem.item_name"
|
||||
:desc="el.orderItem.sku_props_str"
|
||||
:num="10000"
|
||||
:price="(el.orderItem.price / 100).toFixed(2)"
|
||||
:thumb="el.orderItem.pic_url"
|
||||
/>
|
||||
<div
|
||||
class="order_list--total"
|
||||
>合计: {{el.refund_fee | yuan}}(含运费{{el.refund_post_fee | yuan}})</div>
|
||||
</div>
|
||||
<div slot="footer" style="text-align: right;">
|
||||
<van-button
|
||||
size="small"
|
||||
@click="refund_handle(i)"
|
||||
>{{ el.status == 10 ? "撤销申请" : "查看详情"}}</van-button>
|
||||
</div>
|
||||
</van-panel>
|
||||
</InfinityScroll>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { REFUND_LIST } from '@/api/order';
|
||||
|
||||
import { Tab, Tabs, Panel, Card, List } from 'vant';
|
||||
import InfinityScroll from '@/vue/components/infinity-scroll';
|
||||
|
||||
const STATUS_TEXT = {
|
||||
10: '退款中',
|
||||
50: '退款关闭',
|
||||
60: '退款成功'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'order-list',
|
||||
|
||||
data() {
|
||||
return {
|
||||
listApi: REFUND_LIST,
|
||||
shop_id: 1,
|
||||
activeIndex: 0,
|
||||
items: [],
|
||||
tabsItem: [
|
||||
{
|
||||
name: '全部',
|
||||
status: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '退款中',
|
||||
status: 10,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '退款成功',
|
||||
status: 60,
|
||||
items: []
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onLoad(i, items) {
|
||||
this.tabsItem[i].items.push(...items);
|
||||
},
|
||||
beforeRequest() {
|
||||
const i = this.activeIndex;
|
||||
const status = this.tabsItem[i].status;
|
||||
const { shop_id } = this;
|
||||
return {
|
||||
params: {
|
||||
status,
|
||||
shop_id
|
||||
}
|
||||
};
|
||||
},
|
||||
refund_handle(i) {
|
||||
const item = this.items[i];
|
||||
if (item.status == 10) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
message: '撤销后将不能再次发起申请,确定要撤销该申请吗?'
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast('已撤销该退款申请');
|
||||
this.items[i].status = 50;
|
||||
});
|
||||
} else {
|
||||
// 跳转退款详情
|
||||
}
|
||||
},
|
||||
handleTabClick(index) {
|
||||
if (this.activeIndex != index) {
|
||||
this.activeIndex = index;
|
||||
}
|
||||
},
|
||||
getStatusText(status) {
|
||||
return STATUS_TEXT[status] || '';
|
||||
}
|
||||
},
|
||||
components: {
|
||||
[Tab.name]: Tab,
|
||||
[Tabs.name]: Tabs,
|
||||
[Panel.name]: Panel,
|
||||
[Card.name]: Card,
|
||||
[List.name]: List,
|
||||
InfinityScroll
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_list {
|
||||
padding-bottom: 0;
|
||||
|
||||
&--footer_btn {
|
||||
text-align: right;
|
||||
}
|
||||
&--panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--van-card {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&--total {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="order_list">
|
||||
<van-tabs sticky :active="activeIndex" :swipe-threshold="5" @click="handleTabClick">
|
||||
<van-tab v-for="(tab, tabIndex) in tabsItem" :title="tab.name" :key="tab.type">
|
||||
<InfinityScroll
|
||||
class="full-page scroll-wrap"
|
||||
:beforeRequest="beforeRequest"
|
||||
:apiUrl="listApi"
|
||||
@onLoad="onLoad(tabIndex, $event)"
|
||||
>
|
||||
<van-panel
|
||||
v-for="(el, i) in tab.items"
|
||||
class="order_list--panel"
|
||||
:key="i"
|
||||
:title="'订单编号: ' + el.id"
|
||||
:status="getStatusText(el.status)"
|
||||
>
|
||||
<div>
|
||||
<van-card
|
||||
class="order_list--van-card"
|
||||
:key="i"
|
||||
:title="el.orderItem.item_name"
|
||||
:desc="el.orderItem.sku_props_str"
|
||||
:num="10000"
|
||||
:price="(el.orderItem.price / 100).toFixed(2)"
|
||||
:thumb="el.orderItem.pic_url"
|
||||
/>
|
||||
<div
|
||||
class="order_list--total"
|
||||
>合计: {{el.refund_fee | yuan}}(含运费{{el.refund_post_fee | yuan}})</div>
|
||||
</div>
|
||||
<div slot="footer" style="text-align: right;">
|
||||
<van-button
|
||||
size="small"
|
||||
@click="refund_handle(i)"
|
||||
>{{ el.status == 10 ? "撤销申请" : "查看详情"}}</van-button>
|
||||
</div>
|
||||
</van-panel>
|
||||
</InfinityScroll>
|
||||
</van-tab>
|
||||
</van-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { REFUND_LIST } from '@/api/order';
|
||||
|
||||
import { Tab, Tabs, Panel, Card, List } from 'vant';
|
||||
import InfinityScroll from '@/components/infinity-scroll';
|
||||
|
||||
const STATUS_TEXT = {
|
||||
10: '退款中',
|
||||
50: '退款关闭',
|
||||
60: '退款成功'
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'order-list',
|
||||
|
||||
data() {
|
||||
return {
|
||||
listApi: REFUND_LIST,
|
||||
shop_id: 1,
|
||||
activeIndex: 0,
|
||||
items: [],
|
||||
tabsItem: [
|
||||
{
|
||||
name: '全部',
|
||||
status: 0,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '退款中',
|
||||
status: 10,
|
||||
items: []
|
||||
},
|
||||
{
|
||||
name: '退款成功',
|
||||
status: 60,
|
||||
items: []
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
|
||||
methods: {
|
||||
onLoad(i, items) {
|
||||
this.tabsItem[i].items.push(...items);
|
||||
},
|
||||
beforeRequest() {
|
||||
const i = this.activeIndex;
|
||||
const status = this.tabsItem[i].status;
|
||||
const { shop_id } = this;
|
||||
return {
|
||||
params: {
|
||||
status,
|
||||
shop_id
|
||||
}
|
||||
};
|
||||
},
|
||||
refund_handle(i) {
|
||||
const item = this.items[i];
|
||||
if (item.status == 10) {
|
||||
this.$dialog
|
||||
.confirm({
|
||||
message: '撤销后将不能再次发起申请,确定要撤销该申请吗?'
|
||||
})
|
||||
.then(() => {
|
||||
this.$toast('已撤销该退款申请');
|
||||
this.items[i].status = 50;
|
||||
});
|
||||
} else {
|
||||
// 跳转退款详情
|
||||
}
|
||||
},
|
||||
handleTabClick(index) {
|
||||
if (this.activeIndex != index) {
|
||||
this.activeIndex = index;
|
||||
}
|
||||
},
|
||||
getStatusText(status) {
|
||||
return STATUS_TEXT[status] || '';
|
||||
}
|
||||
},
|
||||
components: {
|
||||
[Tab.name]: Tab,
|
||||
[Tabs.name]: Tabs,
|
||||
[Panel.name]: Panel,
|
||||
[Card.name]: Card,
|
||||
[List.name]: List,
|
||||
InfinityScroll
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order_list {
|
||||
padding-bottom: 0;
|
||||
|
||||
&--footer_btn {
|
||||
text-align: right;
|
||||
}
|
||||
&--panel {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
&--van-card {
|
||||
background-color: #fafafa;
|
||||
}
|
||||
|
||||
&--total {
|
||||
text-align: right;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,93 +1,93 @@
|
||||
<template>
|
||||
<div class="user_header" :style="{backgroundImage: `url(${background_image})`}">
|
||||
<van-icon name="set" class="user_set" @click="toSetting"/>
|
||||
<div class="user_avatar">
|
||||
<img :src="avatar" alt="头像" width="55" height="55">
|
||||
</div>
|
||||
<div>{{nickName}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import avatar_default from '../../assets/images/avatar_default.png';
|
||||
import bg_default from '../../assets/images/user_head_bg.png';
|
||||
import { getLocalStorage } from 'core/utils/local-storage';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'user-header',
|
||||
|
||||
props: {
|
||||
isLogin: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
nickName: '昵称',
|
||||
avatar: avatar_default,
|
||||
background_image: bg_default
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.getUserInfo();
|
||||
},
|
||||
|
||||
methods: {
|
||||
getUserInfo() {
|
||||
const infoData = getLocalStorage(
|
||||
'nickName',
|
||||
'background_image',
|
||||
'avatar'
|
||||
);
|
||||
this.avatar = avatar_default;
|
||||
this.nickName = infoData.nickName || '昵称';
|
||||
if (!_.isEmpty(infoData.avatar)) {
|
||||
this.avatar = `http://www.qmenhu.com${infoData.avatar}`;
|
||||
}
|
||||
console.log(this.avatar);
|
||||
console.log('-----------');
|
||||
console.log(infoData);
|
||||
|
||||
this.background_image = infoData.background_image || bg_default;
|
||||
},
|
||||
toSetting() {
|
||||
this.$router.push({ name: 'user-information' });
|
||||
}
|
||||
// toLogin() {
|
||||
// !this.isLogin &&
|
||||
// this.$router.push({ name: 'login', query: { redirect: 'user' } });
|
||||
// }
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user_header {
|
||||
position: relative;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: 130px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
i.user_set {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 24px;
|
||||
}
|
||||
.user_avatar {
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="user_header" :style="{backgroundImage: `url(${background_image})`}">
|
||||
<van-icon name="set" class="user_set" @click="toSetting"/>
|
||||
<div class="user_avatar">
|
||||
<img :src="avatar" alt="头像" width="55" height="55">
|
||||
</div>
|
||||
<div>{{nickName}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import avatar_default from '@/assets/images/avatar_default.png';
|
||||
import bg_default from '@/assets/images/user_head_bg.png';
|
||||
import { getLocalStorage } from '@/utils/local-storage';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'user-header',
|
||||
|
||||
props: {
|
||||
isLogin: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
nickName: '昵称',
|
||||
avatar: avatar_default,
|
||||
background_image: bg_default
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.getUserInfo();
|
||||
},
|
||||
|
||||
methods: {
|
||||
getUserInfo() {
|
||||
const infoData = getLocalStorage(
|
||||
'nickName',
|
||||
'background_image',
|
||||
'avatar'
|
||||
);
|
||||
this.avatar = avatar_default;
|
||||
this.nickName = infoData.nickName || '昵称';
|
||||
if (!_.isEmpty(infoData.avatar)) {
|
||||
this.avatar = `http://www.qmenhu.com${infoData.avatar}`;
|
||||
}
|
||||
console.log(this.avatar);
|
||||
console.log('-----------');
|
||||
console.log(infoData);
|
||||
|
||||
this.background_image = infoData.background_image || bg_default;
|
||||
},
|
||||
toSetting() {
|
||||
this.$router.push({ name: 'user-information' });
|
||||
}
|
||||
// toLogin() {
|
||||
// !this.isLogin &&
|
||||
// this.$router.push({ name: 'login', query: { redirect: 'user' } });
|
||||
// }
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.user_header {
|
||||
position: relative;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
height: 130px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
i.user_set {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
font-size: 24px;
|
||||
}
|
||||
.user_avatar {
|
||||
margin-bottom: 10px;
|
||||
img {
|
||||
border: 0;
|
||||
border-radius: 50%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
<template>
|
||||
<div class="tabbar-user">
|
||||
<user-header :isLogin="isLogin"/>
|
||||
<order-group/>
|
||||
<ecoupon-group/>
|
||||
<user-module/>
|
||||
<van-button size="large" class="tabbar-user__quit" v-if="isLogin" @click="quit">退出当前账户</van-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import userHeader from './tabbar-user-header';
|
||||
import orderGroup from './tabbar-user-order';
|
||||
// import ecouponGroup from './tabbar-user-ecoupon';
|
||||
import userModule from './tabbar-user-module';
|
||||
|
||||
import { removeLocalStorage } from 'core/utils/local-storage';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isLogin: false
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.getLoginStatus();
|
||||
},
|
||||
|
||||
methods: {
|
||||
quit() {
|
||||
removeLocalStorage(
|
||||
'Authorization',
|
||||
'user_id',
|
||||
'avatar',
|
||||
'background_image',
|
||||
'nickName'
|
||||
);
|
||||
this.$router.push({ name: 'login' });
|
||||
},
|
||||
getLoginStatus() {
|
||||
this.isLogin =
|
||||
!!localStorage.getItem('Authorization') &&
|
||||
!!localStorage.getItem('user_id');
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[userHeader.name]: userHeader,
|
||||
[orderGroup.name]: orderGroup,
|
||||
// [ecouponGroup.name]: ecouponGroup,
|
||||
[userModule.name]: userModule
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tabbar-user {
|
||||
> div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
&__quit {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div class="tabbar-user">
|
||||
<user-header :isLogin="isLogin"/>
|
||||
<order-group/>
|
||||
<ecoupon-group/>
|
||||
<user-module/>
|
||||
<van-button size="large" class="tabbar-user__quit" v-if="isLogin" @click="quit">退出当前账户</van-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import userHeader from './tabbar-user-header';
|
||||
import orderGroup from './tabbar-user-order';
|
||||
// import ecouponGroup from './tabbar-user-ecoupon';
|
||||
import userModule from './tabbar-user-module';
|
||||
|
||||
import { removeLocalStorage } from '@/utils/local-storage';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
isLogin: false
|
||||
};
|
||||
},
|
||||
|
||||
activated() {
|
||||
this.getLoginStatus();
|
||||
},
|
||||
|
||||
methods: {
|
||||
quit() {
|
||||
removeLocalStorage(
|
||||
'Authorization',
|
||||
'user_id',
|
||||
'avatar',
|
||||
'background_image',
|
||||
'nickName'
|
||||
);
|
||||
this.$router.push({ name: 'login' });
|
||||
},
|
||||
getLoginStatus() {
|
||||
this.isLogin =
|
||||
!!localStorage.getItem('Authorization') &&
|
||||
!!localStorage.getItem('user_id');
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[userHeader.name]: userHeader,
|
||||
[orderGroup.name]: orderGroup,
|
||||
// [ecouponGroup.name]: ecouponGroup,
|
||||
[userModule.name]: userModule
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
<style scoped lang="scss">
|
||||
.tabbar-user {
|
||||
> div {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
&__quit {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
<script>
|
||||
import { Uploader, Picker, Popup, Button } from 'vant';
|
||||
import { USER_PROFILE } from '@/api/user';
|
||||
import { removeLocalStorage } from 'core/utils/local-storage';
|
||||
import { getLocalStorage } from 'core/utils/local-storage';
|
||||
import { removeLocalStorage } from '@/utils/local-storage';
|
||||
import { getLocalStorage } from '@/utils/local-storage';
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
|
||||
@@ -1,89 +1,89 @@
|
||||
<template>
|
||||
<div>
|
||||
<van-cell-group>
|
||||
<van-field
|
||||
label="原密码"
|
||||
v-model="password"
|
||||
type="password"
|
||||
placeholder="请输入原密码"
|
||||
:error="!!$vuelidation.error('password')"
|
||||
/>
|
||||
|
||||
<van-field
|
||||
label="新密码"
|
||||
v-model="new_password"
|
||||
type="password"
|
||||
placeholder="请输入新密码"
|
||||
:error="!!$vuelidation.error('new_password')"
|
||||
/>
|
||||
|
||||
<van-field
|
||||
label="确认密码"
|
||||
v-model="repeat_password"
|
||||
type="password"
|
||||
placeholder="请再次输入密码"
|
||||
:error="!!$vuelidation.error('repeat_password')"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<div class="bottom_btn">
|
||||
<van-button size="large" type="danger" @click="modifypassword">保存</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { USER_MODIFY_PASSWORD, USER_LOGOUT } from '@/api/user';
|
||||
import { removeLocalStorage } from 'core/utils/local-storage';
|
||||
|
||||
import { Field } from 'vant';
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
password: '',
|
||||
new_password: '',
|
||||
repeat_password: ''
|
||||
}),
|
||||
|
||||
methods: {
|
||||
modifypassword() {
|
||||
if (this.passwordValid()) {
|
||||
this.$reqPut(USER_MODIFY_PASSWORD, {
|
||||
old_password: this.password,
|
||||
new_password: this.new_password
|
||||
})
|
||||
.then(() => this.$dialog.alert({ message: '保存成功, 请重新登录.' }))
|
||||
.then(() => this.$reqGet(USER_LOGOUT))
|
||||
.then(() => {
|
||||
removeLocalStorage(
|
||||
'Authorization',
|
||||
'user_id',
|
||||
'avatar',
|
||||
'background_image',
|
||||
'nickName'
|
||||
);
|
||||
this.$router.replace({ name: 'login' });
|
||||
});
|
||||
}
|
||||
},
|
||||
passwordValid() {
|
||||
if (this.new_password != this.repeat_password) {
|
||||
this.$toast('密码不一致, 请再次确认密码');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[Field.name]: Field
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bottom_btn {
|
||||
padding: 30px 15px 0 15px;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div>
|
||||
<van-cell-group>
|
||||
<van-field
|
||||
label="原密码"
|
||||
v-model="password"
|
||||
type="password"
|
||||
placeholder="请输入原密码"
|
||||
:error="!!$vuelidation.error('password')"
|
||||
/>
|
||||
|
||||
<van-field
|
||||
label="新密码"
|
||||
v-model="new_password"
|
||||
type="password"
|
||||
placeholder="请输入新密码"
|
||||
:error="!!$vuelidation.error('new_password')"
|
||||
/>
|
||||
|
||||
<van-field
|
||||
label="确认密码"
|
||||
v-model="repeat_password"
|
||||
type="password"
|
||||
placeholder="请再次输入密码"
|
||||
:error="!!$vuelidation.error('repeat_password')"
|
||||
/>
|
||||
</van-cell-group>
|
||||
|
||||
<div class="bottom_btn">
|
||||
<van-button size="large" type="danger" @click="modifypassword">保存</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import { USER_MODIFY_PASSWORD, USER_LOGOUT } from '@/api/user';
|
||||
import { removeLocalStorage } from '@/utils/local-storage';
|
||||
|
||||
import { Field } from 'vant';
|
||||
|
||||
export default {
|
||||
data: () => ({
|
||||
password: '',
|
||||
new_password: '',
|
||||
repeat_password: ''
|
||||
}),
|
||||
|
||||
methods: {
|
||||
modifypassword() {
|
||||
if (this.passwordValid()) {
|
||||
this.$reqPut(USER_MODIFY_PASSWORD, {
|
||||
old_password: this.password,
|
||||
new_password: this.new_password
|
||||
})
|
||||
.then(() => this.$dialog.alert({ message: '保存成功, 请重新登录.' }))
|
||||
.then(() => this.$reqGet(USER_LOGOUT))
|
||||
.then(() => {
|
||||
removeLocalStorage(
|
||||
'Authorization',
|
||||
'user_id',
|
||||
'avatar',
|
||||
'background_image',
|
||||
'nickName'
|
||||
);
|
||||
this.$router.replace({ name: 'login' });
|
||||
});
|
||||
}
|
||||
},
|
||||
passwordValid() {
|
||||
if (this.new_password != this.repeat_password) {
|
||||
this.$toast('密码不一致, 请再次确认密码');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
[Field.name]: Field
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.bottom_btn {
|
||||
padding: 30px 15px 0 15px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
export default {
|
||||
install(Vue) {
|
||||
Vue.prototype.$bus = new Vue({
|
||||
data() {
|
||||
return {
|
||||
item_list: []
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.$on('item_list', val => {
|
||||
const isArr = Array.isArray(val);
|
||||
if (isArr) {
|
||||
this.item_list = val;
|
||||
} else {
|
||||
throw Error('item_list必须为数组');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,48 +0,0 @@
|
||||
import asyncLoader from 'core/async-loader';
|
||||
const login = asyncLoader('login/login');
|
||||
const registerGetCode = asyncLoader('login/register-getCode');
|
||||
const registerSubmit = asyncLoader('login/register-submit');
|
||||
const registerStatus = asyncLoader('login/register-status');
|
||||
const forget = asyncLoader('login/forget');
|
||||
const forgetReset = asyncLoader('login/forget-reset');
|
||||
const forgetStatus = asyncLoader('login/forget-status');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: login
|
||||
},
|
||||
{
|
||||
path: '/login/registerGetCode',
|
||||
name: 'registerGetCode',
|
||||
component: registerGetCode
|
||||
},
|
||||
{
|
||||
path: '/login/registerSubmit',
|
||||
name: 'registerSubmit',
|
||||
component: registerSubmit
|
||||
},
|
||||
{
|
||||
path: '/login/registerStatus/:status',
|
||||
name: 'registerStatus',
|
||||
props: true,
|
||||
component: registerStatus
|
||||
},
|
||||
{
|
||||
path: '/login/forget',
|
||||
name: 'forget',
|
||||
component: forget
|
||||
},
|
||||
{
|
||||
path: '/login/forget/reset',
|
||||
name: 'forgetReset',
|
||||
component: forgetReset
|
||||
},
|
||||
{
|
||||
path: '/login/forget/reset/:status',
|
||||
name: 'forgetStatus',
|
||||
props: true,
|
||||
component: forgetStatus
|
||||
}
|
||||
];
|
||||
@@ -1,47 +0,0 @@
|
||||
import asyncLoader from 'core/async-loader';
|
||||
const tab_cart = asyncLoader('order/tabbar-cart');
|
||||
const PlaceOrderEntity = asyncLoader('order/place-order-entity');
|
||||
const orderDetail = asyncLoader('order/orderDetail');
|
||||
const PlaceOrderVirtual = asyncLoader('order/place-order-virtual');
|
||||
const Payment = asyncLoader('order/payment');
|
||||
const PaymentStatus = asyncLoader('order/payment-status');
|
||||
|
||||
const Tabbar = () =>
|
||||
import(/* webpackChunkName: "Tabbar" */ '@/vue/components/Tabbar/');
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/order',
|
||||
name: 'cart',
|
||||
meta: {
|
||||
login: true
|
||||
},
|
||||
components: { default: tab_cart, tabbar: Tabbar }
|
||||
},
|
||||
{
|
||||
path: '/order/placeOrderEntity',
|
||||
name: 'placeOrderEntity',
|
||||
component: PlaceOrderEntity
|
||||
},
|
||||
{
|
||||
path: '/order/orderDetail',
|
||||
name: 'orderDetail',
|
||||
component: orderDetail
|
||||
},
|
||||
{
|
||||
path: '/order/placeOrderVirtual',
|
||||
name: 'placeOrderVirtual',
|
||||
component: PlaceOrderVirtual
|
||||
},
|
||||
{
|
||||
path: '/order/payment',
|
||||
name: 'payment',
|
||||
component: Payment
|
||||
},
|
||||
{
|
||||
path: '/order/payment/:status',
|
||||
name: 'paymentStatus',
|
||||
component: PaymentStatus,
|
||||
props: true
|
||||
}
|
||||
];
|
||||
Reference in New Issue
Block a user