Authored by TaoHuang

Merge remote-tracking branch 'origin/master'

... ... @@ -18,26 +18,32 @@ export default {
},
methods: {
...mapActions(['postComment']),
openComentInput() {
const hint = this.user ? `回复${this.user}:` : '';
async openComentInput() {
const user = await this.$sdk.getUser();
if (this.$yoho.isYohoBuy) {
this.$yoho.getInput({hint}, (content) => {
this.comment(content);
}, (e) => {
console.error(e);
});
if (user && user.uid) {
const hint = this.user ? `回复${this.user}:` : '评论:';
if (this.$yoho.isYohoBuy) {
this.$yoho.getInput({hint}, (content) => {
this.comment(content);
}, (e) => {
console.error(e);
});
} else {
this.$createDialog({
type: 'prompt',
title: '测试-输入',
prompt: {
placeholder: hint
},
onConfirm: (e, promptValue) => {
this.comment(promptValue);
}
}).show();
}
} else {
this.$createDialog({
type: 'prompt',
title: '测试-输入',
prompt: {
placeholder: hint
},
onConfirm: (e, promptValue) => {
this.comment(promptValue);
}
}).show();
this.$sdk.goLogin();
}
},
async comment(content) {
... ...
export default {
name: 'AuthComponent',
props: {
tag: String,
auth: {
type: Boolean,
default: true
}
},
methods: {
async onClick() {
if (!this.auth) {
return this.$emit('click');
}
const user = await this.$sdk.getUser();
if (user && user.uid) {
this.$emit('click', {uid: user.uid});
} else {
this.$emit('cancel');
this.$sdk.goLogin();
}
}
},
render(h) {
return h(this.tag || 'div', {
on: {
click: this.onClick.bind(this)
}
}, this.$slots.default);
}
};
... ...
... ... @@ -2,10 +2,12 @@ import Layout from './layout';
import LayoutHeader from './layout-header';
import LayoutRecycleList from './layout-recycle-list';
import RecycleList from './recycle-list';
import AuthComponent from './auth-component';
export default [
Layout,
LayoutHeader,
LayoutRecycleList,
RecycleList,
AuthComponent,
];
... ...
... ... @@ -10,10 +10,10 @@
<p class="price">¥{{product.salesPrice}}</p>
</div>
</div>
<div
<AuthComponent
class="btn-fav hover-opacity"
@click.stop="onFav"
:class="favClass">{{favText}}</div>
@click="onFav"
:class="favClass">{{favText}}</AuthComponent>
</div>
</template>
... ... @@ -50,10 +50,6 @@ export default {
methods: {
...mapActions(['postProductFav']),
async onFav() {
if (!this.auth()) {
return;
}
if (this.posting) {
return;
}
... ...
<template>
<div class="btn-follow hover-opacity" :class="followClass" @click="onFollow">{{followText}}</div>
<AuthComponent class="btn-follow hover-opacity" :class="followClass" @click="onFollow">{{followText}}</AuthComponent>
</template>
<script>
... ... @@ -41,10 +41,6 @@ export default {
methods: {
...mapActions(['followUser']),
async onFollow() {
if (!this.auth()) {
return;
}
if (this.loading) {
return;
}
... ...
<template>
<div class="icon-btn" @click="onClick" :style="btnStyle">
<AuthComponent :auth="isAuth" class="icon-btn" @click="onClick" :style="btnStyle">
<i class="iconfont" :class="iconClass" :style="iconStyle"></i>
<p v-if="viewText" class="icon-btn-text" :style="textStyle">
<span class="view-text">{{viewText}}</span>
<span class="placeholder-text">{{placText}}</span>
</p>
</div>
</AuthComponent>
</template>
<script>
import {forEach, get, fill} from 'lodash';
import {createNamespacedHelpers} from 'vuex';
const {mapActions} = createNamespacedHelpers('user');
const classMap = {
fav: {
default: 'icon-zan',
selected: 'icon-zan-fill'
},
star: {
default: 'icon-star',
selected: 'icon-star-fill'
},
share: {
default: 'icon-share'
import {forEach, fill} from 'lodash';
import {createNamespacedHelpers} from 'vuex';
const {mapActions} = createNamespacedHelpers('user');
const classMap = {
fav: {
default: 'icon-zan',
selected: 'icon-zan-fill'
},
star: {
default: 'icon-star',
selected: 'icon-star-fill'
},
share: {
default: 'icon-share'
},
msg: {
default: 'icon-msg'
}
};
const defaultOption = {
canSelect: true, // 是否支持选中
selected: false, // 初始选中状态(不受是否支持选中控制)
color: '#444', // btn字体颜色
selectedColor: '#d90025', // btn选中状态字体颜色(不设置默认与非选中一致)
iconFontSize: 48, // icon字号(单位px)
textSelectedColor: '#444', // text选中状态字体颜色(不设置默认与selectedColor一致)
textFontSize: 20, // text字号(单位px)
textAlign: 'top', // text位置, 默认normal(支持normal, top, bottom)
textZoom: 0.9, // text缩放
textAutoChange: true, // text自动增减,只支持number类型(受是否支持选中控制)
emitName: '' // 点击触发事件名称
};
export default {
name: 'WidgetIconBtn',
props: {
type: {
type: String,
default: 'fav'
},
msg: {
default: 'icon-msg'
}
};
const defaultOption = {
canSelect: true, // 是否支持选中
selected: false, // 初始选中状态(不受是否支持选中控制)
color: '#444', // btn字体颜色
selectedColor: '#d90025', // btn选中状态字体颜色(不设置默认与非选中一致)
iconFontSize: 48, // icon字号(单位px)
textSelectedColor: '#444', // text选中状态字体颜色(不设置默认与selectedColor一致)
textFontSize: 20, // text字号(单位px)
textAlign: 'top', // text位置, 默认normal(支持normal, top, bottom)
textZoom: 0.9, // text缩放
textAutoChange: true, // text自动增减,只支持number类型(受是否支持选中控制)
emitName: '' // 点击触发事件名称
};
export default {
name: 'WidgetIconBtn',
props: {
type: {
type: String,
default: 'fav'
},
text: {
type: [String, Number],
default() {
return '';
}
},
articleId: Number,
commentId: Number,
option: {
type: Object,
default() {
return defaultOption;
}
text: {
type: [String, Number],
default() {
return '';
}
},
data() {
return {
viewOption: {},
btnSelected: false,
actionClass: '',
editText: null
articleId: Number,
commentId: Number,
option: {
type: Object,
default() {
return defaultOption;
}
}
},
data() {
return {
viewOption: {},
btnSelected: false,
actionClass: '',
editText: null
};
},
created() {
forEach(defaultOption, (value, key) => {
this.viewOption[key] = this.option.hasOwnProperty(key) ? this.option[key] : defaultOption[key];
});
this.viewOption = {...this.viewOption};
},
computed: {
syncFnName() {
if (this.articleId) {
if (this.type === 'fav') {
return 'praiseArticle';
} else if (this.type === 'star') {
return 'followArticle';
}
} else if (this.commentId && this.type === 'fav') {
return 'praiseComment';
}
},
created() {
forEach(defaultOption, (value, key) => {
this.viewOption[key] = this.option.hasOwnProperty(key) ? this.option[key] : defaultOption[key];
});
this.viewOption = {...this.viewOption};
isAuth() {
return !!this.syncFnName;
},
computed: {
btnStyle() {
let color = this.viewOption.color || defaultOption.color;
btnStyle() {
let color = this.viewOption.color || defaultOption.color;
return `color: ${this.btnSelected ? (this.viewOption.selectedColor || color) : color};`;
},
iconClass() {
if (this.actionClass) {
return this.actionClass;
}
if (!this._icon) {
this._type = classMap[this.type] ? this.type : 'fav'
this._icon = classMap[this._type];
}
return `color: ${this.btnSelected ? (this.viewOption.selectedColor || color) : color};`;
},
iconClass() {
if (this.actionClass) {
return this.actionClass;
}
if (classMap[this.type]) {
const currentClass = classMap[this.type];
if (this.viewOption.selected) {
this.btnSelected = true;
return this._icon.selected || this._icon.default;
return currentClass.selected || currentClass.default;
}
return this._icon.default;
},
iconStyle() {
return `font-size: ${this.pxToRem(this.viewOption.iconFontSize)};`;
},
textStyle() {
let style = `font-size: ${this.pxToRem(this.viewOption.textFontSize)};`;
let textAlign = this.viewOption.textAlign;
if (['top', 'bottom'].indexOf(textAlign) >= 0) {
style += ` vertical-align: ${textAlign};`;
}
return currentClass.default;
}
},
iconStyle() {
return `font-size: ${this.pxToRem(this.viewOption.iconFontSize)};`;
},
textStyle() {
let style = `font-size: ${this.pxToRem(this.viewOption.textFontSize)};`;
let textZoom = this.viewOption.textZoom;
let textAlign = this.viewOption.textAlign;
if (Number(textZoom) !== NaN) {
style += ` transform: scale(${textZoom}, ${textZoom});`
}
if (['top', 'bottom'].indexOf(textAlign) >= 0) {
style += ` vertical-align: ${textAlign};`;
}
if (this.viewOption.textSelectedColor) {
style += ` color: ${this.viewOption.textSelectedColor};`
}
let textZoom = this.viewOption.textZoom;
return style;
},
viewText() {
return `${(this.editText === null ? this.text : this.editText)}`;
},
placText() {
if (!isNaN(Number(this.text)) && this.viewText.length) {
return fill(Array(this.viewText.length), 0).join('');
} else {
return `${this.text}`;
}
if (Number(textZoom) !== NaN) {
style += ` transform: scale(${textZoom}, ${textZoom});`
}
},
methods: {
...mapActions(['followArticle', 'praiseArticle', 'praiseComment']),
pxToRem(px) {
const rootValue = 40;
if (typeof px !== 'number') {
px = parseInt(`0${px}`);
}
if (px > 2) {
return (px / rootValue).toFixed(2) + 'rem';
} else {
return px + 'px';
}
},
changeBtnStatus() {
this.btnSelected = !this.btnSelected;
if (this.viewOption.textSelectedColor) {
style += ` color: ${this.viewOption.textSelectedColor};`
}
if (this.viewOption.textAutoChange) {
let _text = this.editText || this.text;
return style;
},
viewText() {
return `${(this.editText === null ? this.text : this.editText)}`;
},
placText() {
if (!isNaN(Number(this.text)) && this.viewText.length) {
return fill(Array(this.viewText.length), 0).join('');
} else {
return `${this.text}`;
}
}
},
methods: {
...mapActions(['followArticle', 'praiseArticle', 'praiseComment']),
pxToRem(px) {
const rootValue = 40;
if (typeof px !== 'number') {
px = parseInt(`0${px}`, 10);
}
if (!isNaN(Number(this.viewText))) {
this.editText = Number(this.viewText) + (this.btnSelected ? 1 : -1);
}
}
if (px > 2) {
return (px / rootValue).toFixed(2) + 'rem';
} else {
return px + 'px';
}
},
changeBtnStatus() {
this.btnSelected = !this.btnSelected;
if (this._icon.selected) {
this.actionClass = this.btnSelected ? this._icon.selected : this._icon.default;
}
},
syncService(type, data) {
if (typeof this[type] === 'function') {
return this[type](data);
} else {
return Promise.resolve({code: 404});
}
},
onClick(evt) {
if (this.syncing) {
return;
if (this.viewOption.textAutoChange) {
if (!isNaN(Number(this.viewText))) {
this.editText = Number(this.viewText) + (this.btnSelected ? 1 : -1);
}
}
if (this.viewOption.canSelect) {
this.changeBtnStatus();
let syncFnName = '';
if (classMap[this.type]) {
this.actionClass = this.btnSelected ? classMap[this.type].selected : classMap[this.type].default;
}
},
syncService(type, data) {
if (typeof this[type] === 'function') {
return this[type](data);
} else {
return Promise.resolve({code: 404});
}
},
onClick(evt) {
if (this.syncing) {
return;
}
if (this.articleId) {
if (this._type === 'fav') {
syncFnName = 'praiseArticle';
} else if (this._type === 'star') {
syncFnName = 'followArticle';
}
} else if (this.commentId && this._type === 'fav') {
syncFnName = 'praiseComment';
if (this.viewOption.canSelect) {
this.changeBtnStatus();
const backFn = (res) => {
this.syncing = false;
if (res.code !== 200) {
this.changeBtnStatus();
this.$createToast && this.$createToast({
txt: res.message || '服务器开小差了',
type: 'warn',
time: 1000
}).show();
}
};
if (syncFnName) {
if (!this.auth()) {
return this.changeBtnStatus();
}
const backFn = (res) => {
this.syncing = false;
if (res.code !== 200) {
this.changeBtnStatus();
if (res.code === 401) {
// TODO go_login
} else {
this.$createToast && this.$createToast({
txt: res.message || '服务器开小差了',
type: 'warn',
time: 1000
}).show();
}
}
};
this.syncing = true;
this.syncing = true;
this.syncService(syncFnName, {
articleId: this.articleId,
commentId: this.commentId,
status: this.btnSelected
}).then(backFn).catch(backFn);
}
}
this.viewOption.emitName && this.$emit(this.viewOption.emitName, evt);
this.syncService(this.syncFnName, {
articleId: this.articleId,
commentId: this.commentId,
status: this.btnSelected
}).then(backFn).catch(backFn);
}
},
};
this.viewOption.emitName && this.$emit(this.viewOption.emitName, evt);
}
},
};
</script>
<style type="scss">
... ...
... ... @@ -10,6 +10,7 @@ import {get} from 'lodash';
import Lazy from 'vue-lazyload';
import yoho from 'common/yoho';
import sdk from 'common/sdk';
import InitClient from 'utils/init-client';
import 'statics/scss/common.scss';
import 'statics/scss/grass-prompt.scss';
import 'statics/font/iconfont.css';
... ... @@ -24,6 +25,7 @@ if (window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__);
}
window._router = get(store, 'state.yoho.context.route');
Vue.prop('yoho', yoho);
... ... @@ -44,6 +46,8 @@ Vue.prop('api', createApi(context, store));
Vue.use(Lazy, {error: ''});
InitClient(store);
const trackPage = (path) => {
if (window._hmt) {
try {
... ...
... ... @@ -27,16 +27,6 @@ const clientTitleMixin = {
if (title) {
document.title = title;
}
},
methods: {
auth() {
if (!this.$store.state.yoho.context.isLogin) {
this.$yoho.goLogin();
return false;
} else {
return true;
}
}
}
};
... ...
... ... @@ -6,7 +6,6 @@ import storeArticle from './article';
import storeUser from './user';
import storeComment from './comment';
import storeProduct from './product';
import plugin from './plugin';
Vue.use(Vuex);
... ... @@ -21,7 +20,6 @@ export function createStore(context) {
product: storeProduct()
},
strict: process.env.NODE_ENV !== 'production',
plugins: [plugin]
});
const api = createApi(context, store);
... ...
import Vue from 'vue';
export default (store) => {
setTimeout(() => {
if (process.env.VUE_ENV !== 'server') {
window.onresize = () => {
const {clientWidth, clientHeight} = document.body;
store.commit('SET_WINDOW_SIZE', {clientWidth, clientHeight});
};
const {clientWidth, clientHeight} = document.body;
store.commit('SET_WINDOW_SIZE', {clientWidth, clientHeight});
let supportsPassive = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get() {
supportsPassive = true;
return true;
}
});
window.addEventListener('test', null, opts);
} catch (e) {} //eslint-disable-line
store.commit('SET_SUPPORT_PASSIVE', {supportsPassive});
Vue.$sdk.getUser().then(user => {
console.log(user)
})
}
}, 0);
export default () => {
};
... ...
... ... @@ -33,7 +33,9 @@ export default function() {
state.context.title = context.title;
state.context.route = context.route;
state.context.path = context.path;
state.context.isLogin = context.user.uid > 1;
},
[Types.SET_LOGIN_INFO](state, {uid}) {
state.context.isLogin = uid > 1;
},
[Types.SET_TITLE](state, {title}) {
state.context.title = title;
... ... @@ -55,8 +57,9 @@ export default function() {
[Types.SET_NEED_LOGIN](state, {needLogin}) {
state.context.needLogin = needLogin;
},
[Types.SET_WINDOW_SIZE](state, data) {
state.window = Object.assign(state.window, data);
[Types.SET_WINDOW_SIZE](state, {clientWidth, clientHeight}) {
state.window.clientWidth = clientWidth;
state.window.clientHeight = clientHeight;
},
[Types.SET_SUPPORT_PASSIVE](state, {supportsPassive}) {
state.window.supportsPassive = supportsPassive;
... ...
... ... @@ -3,5 +3,6 @@ export const SET_TITLE = 'SET_TITLE';
export const ROUTE_CHANGE = 'ROUTE_CHANGE';
export const REPORT_YAS = 'REPORT_YAS';
export const SET_NEED_LOGIN = 'SET_NEED_LOGIN';
export const SET_LOGIN_INFO = 'SET_LOGIN_INFO';
export const SET_WINDOW_SIZE = 'SET_WINDOW_SIZE';
export const SET_SUPPORT_PASSIVE = 'SET_SUPPORT_PASSIVE';
... ...
import Vue from 'vue';
export default store => {
window.onresize = () => {
const {clientWidth, clientHeight} = document.body;
store.commit('SET_WINDOW_SIZE', {clientWidth, clientHeight});
};
const {clientWidth, clientHeight} = document.body;
store.commit('SET_WINDOW_SIZE', {clientWidth, clientHeight});
let supportsPassive = false;
try {
const opts = Object.defineProperty({}, 'passive', {
get() {
supportsPassive = true;
return true;
}
});
window.addEventListener('test', null, opts);
} catch (e) {} //eslint-disable-line
store.commit('SET_SUPPORT_PASSIVE', {supportsPassive});
Vue.$sdk.getUser().then(user => {
if (user && user.uid) {
store.commit('SET_LOGIN_INFO', user);
}
});
};
... ...