Authored by bevishuang

Merge branch 'develop' of http://git.yoho.cn/fe/xianyu-ufo-app-web into develop

1 <template> 1 <template>
2 <LayoutApp :title="title" :show-back="true"> 2 <LayoutApp :title="title" :show-back="true">
3 - <div class="pane-body">  
4 - <FormItem>  
5 - <CInput  
6 - label="收货人"  
7 - place-holder="请写姓名"  
8 - v-model="model.consignee"  
9 - :textValue="model.consignee"  
10 - type="text"  
11 - ></CInput>  
12 - </FormItem>  
13 - <FormItem>  
14 - <CInput label="手机号" place-holder="请填写手机号" v-model="model.mobile" :textValue="model.mobile"></CInput>  
15 - </FormItem>  
16 -  
17 - <template> 3 + <Scroll ref="scroll" :options="scrollOpts">
  4 + <div class="pane-body">
18 <FormItem> 5 <FormItem>
19 - <div class="wrapper-area">  
20 - <label class="input-label">所在区域</label>  
21 - <div class="wrapper-arrow" @click="chooseArea">  
22 - <template v-if="model.area">  
23 - <label class="text-label">{{ model.area }}</label>  
24 - </template>  
25 - <template v-else>  
26 - <label class="choose-area">请选择</label>  
27 - </template>  
28 - <div class="arrow"></div> 6 + <CInput
  7 + label="收货人"
  8 + place-holder="请写姓名"
  9 + v-model="model.consignee"
  10 + :textValue="model.consignee"
  11 + type="text"
  12 + ></CInput>
  13 + </FormItem>
  14 + <FormItem>
  15 + <CInput
  16 + label="手机号"
  17 + place-holder="请填写手机号"
  18 + v-model="model.mobile"
  19 + :textValue="model.mobile"
  20 + ></CInput>
  21 + </FormItem>
  22 +
  23 + <template>
  24 + <FormItem>
  25 + <div class="wrapper-area">
  26 + <label class="input-label">所在区域</label>
  27 + <div class="wrapper-arrow" @click="chooseArea">
  28 + <template v-if="model.area">
  29 + <label class="text-label">{{ model.area }}</label>
  30 + </template>
  31 + <template v-else>
  32 + <label class="choose-area">请选择</label>
  33 + </template>
  34 + <div class="arrow"></div>
  35 + </div>
29 </div> 36 </div>
30 - </div> 37 + </FormItem>
  38 + </template>
  39 +
  40 + <FormItem>
  41 + <CInput
  42 + label="详细地址"
  43 + place-holder="请输入详细地址"
  44 + v-model="model.address"
  45 + :textValue="model.address"
  46 + ></CInput>
31 </FormItem> 47 </FormItem>
32 - </template>  
33 -  
34 - <FormItem>  
35 - <CInput  
36 - label="详细地址"  
37 - place-holder="请输入详细地址"  
38 - v-model="model.address"  
39 - :textValue="model.address"  
40 - ></CInput>  
41 - </FormItem>  
42 - <!-- 订单修改地址隐藏 -->  
43 - <div v-if="!orderCode" class="wrapper-tag">  
44 - <p class="tag-text">设置标签:</p>  
45 - <RadioGroup class="wrapper-radio">  
46 - <div v-for="(tag, index) in addressTags" :key="index">  
47 - <Radio  
48 - class="tag-radio"  
49 - :label="{ text: `${tag.name}`, value: `${tag.code}` }"  
50 - v-model="model.tag_code"  
51 - checked="tag.code === model.tag_code"  
52 - ></Radio>  
53 - </div>  
54 - </RadioGroup>  
55 - </div>  
56 - <!-- 订单修改地址隐藏 -->  
57 - <div v-if="!orderCode" class="wrapper-del">  
58 - <Radio  
59 - class="radio"  
60 - :label="{ text: '设为默认地址', value: true }"  
61 - style="flex: 0 1 100%;"  
62 - checked="model.is_default"  
63 - v-model="model.is_default"  
64 - ></Radio>  
65 - <div v-if="isUpdate" class="del-address" @click="delAddress">删除地址</div> 48 + <!-- 订单修改地址隐藏 -->
  49 + <div v-if="!orderCode" class="wrapper-tag">
  50 + <p class="tag-text">设置标签:</p>
  51 + <RadioGroup class="wrapper-radio">
  52 + <div v-for="(tag, index) in addressTags" :key="index">
  53 + <Radio
  54 + class="tag-radio"
  55 + :label="{ text: `${tag.name}`, value: `${tag.code}` }"
  56 + v-model="model.tag_code"
  57 + checked="tag.code === model.tag_code"
  58 + ></Radio>
  59 + </div>
  60 + </RadioGroup>
  61 + </div>
  62 + <!-- 订单修改地址隐藏 -->
  63 + <div v-if="!orderCode" class="wrapper-del">
  64 + <Radio
  65 + class="radio"
  66 + :label="{ text: '设为默认地址', value: true }"
  67 + style="flex: 0 1 100%;"
  68 + checked="model.is_default"
  69 + v-model="model.is_default"
  70 + ></Radio>
  71 + <div v-if="isUpdate" class="del-address" @click="delAddress">删除地址</div>
  72 + </div>
66 </div> 73 </div>
67 -  
68 <div :class="submitClass" @touchend="onSubmit">确 认</div> 74 <div :class="submitClass" @touchend="onSubmit">确 认</div>
69 - </div>  
70 - 75 + </Scroll>
71 <AddressAct 76 <AddressAct
  77 + class="address-act"
72 ref="addressAct" 78 ref="addressAct"
73 v-show="isShowProvince" 79 v-show="isShowProvince"
74 @popHidden="popHidden" 80 @popHidden="popHidden"
@@ -84,6 +90,7 @@ import FormItem from "./components/form-item"; @@ -84,6 +90,7 @@ import FormItem from "./components/form-item";
84 import Radio from "./components/radio"; 90 import Radio from "./components/radio";
85 import AddressAct from "./components/address-act"; 91 import AddressAct from "./components/address-act";
86 import RadioGroup from "./components/radio-group"; 92 import RadioGroup from "./components/radio-group";
  93 +import { Scroll } from "cube-ui";
87 94
88 import { createNamespacedHelpers } from "vuex"; 95 import { createNamespacedHelpers } from "vuex";
89 const { mapState, mapMutations, mapActions } = createNamespacedHelpers( 96 const { mapState, mapMutations, mapActions } = createNamespacedHelpers(
@@ -98,10 +105,14 @@ export default { @@ -98,10 +105,14 @@ export default {
98 FormItem, 105 FormItem,
99 Radio, 106 Radio,
100 AddressAct, 107 AddressAct,
101 - RadioGroup 108 + RadioGroup,
  109 + Scroll
102 }, 110 },
103 data() { 111 data() {
104 return { 112 return {
  113 + scrollOpts: {
  114 + bounce: false
  115 + },
105 isShowProvince: false, 116 isShowProvince: false,
106 isUpdate: false, 117 isUpdate: false,
107 updateMobileNum: "", 118 updateMobileNum: "",
@@ -332,9 +343,27 @@ export default { @@ -332,9 +343,27 @@ export default {
332 </script> 343 </script>
333 344
334 <style lang="scss" scoped> 345 <style lang="scss" scoped>
  346 +/deep/ {
  347 + .cube-scroll-content {
  348 + min-height: 100%;
  349 + }
  350 +
  351 + .cube-scroll-list-wrapper {
  352 + overflow: auto;
  353 + }
  354 +
  355 + .cube-loading-spinners {
  356 + margin: auto;
  357 + }
  358 +}
  359 +
  360 +.address-act {
  361 + z-index: 99;
  362 +}
  363 +
335 .pane-body { 364 .pane-body {
336 height: 100%; 365 height: 100%;
337 - overflow-y: hidden; 366 + overflow-y: auto;
338 padding-top: 12px; 367 padding-top: 12px;
339 padding-left: 40px; 368 padding-left: 40px;
340 padding-right: 40px; 369 padding-right: 40px;
@@ -154,8 +154,8 @@ export default { @@ -154,8 +154,8 @@ export default {
154 refreshProductList(index) { 154 refreshProductList(index) {
155 let str = get(get(this.navList, `[${index}].url`, '').split('?'), '[1]', ''); 155 let str = get(get(this.navList, `[${index}].url`, '').split('?'), '[1]', '');
156 156
157 - this.params = Object.assign({}, queryString.parse(str), this.listBaseParams);  
158 - this.fetchList(this.params); 157 + this.searchParams = Object.assign({}, queryString.parse(str), this.listBaseParams);
  158 + this.fetchList(this.searchParams);
159 }, 159 },
160 160
161 async onPullingUp() { 161 async onPullingUp() {
@@ -178,7 +178,7 @@ export default { @@ -178,7 +178,7 @@ export default {
178 return; 178 return;
179 } 179 }
180 if (typeof params === 'object' && Object.keys(params)) { 180 if (typeof params === 'object' && Object.keys(params)) {
181 - searchParams = Object.assign({...searchParams}, params); 181 + searchParams ={...params};
182 this.searchParams = searchParams; 182 this.searchParams = searchParams;
183 } 183 }
184 184
@@ -214,8 +214,10 @@ export default { @@ -214,8 +214,10 @@ export default {
214 }, 214 },
215 215
216 onPullingDown() { 216 onPullingDown() {
217 - this.params.isReset = true;  
218 - this.fetchList(this.params); 217 + let params = this.searchParams;
  218 +
  219 + params.isReset = true;
  220 + this.fetchList(params);
219 }, 221 },
220 }, 222 },
221 components: { 223 components: {
@@ -26,8 +26,10 @@ export default { @@ -26,8 +26,10 @@ export default {
26 }, 26 },
27 methods: { 27 methods: {
28 jump(item) { 28 jump(item) {
29 - const { type, description } = item; 29 + console.log(item);
  30 + let { type, description } = item;
30 this.$router.push({name:'newsDetail',query: {type,description}}) 31 this.$router.push({name:'newsDetail',query: {type,description}})
  32 + this.$emit('clearStore',1);
31 } 33 }
32 } 34 }
33 }; 35 };
@@ -2,7 +2,7 @@ export default [ @@ -2,7 +2,7 @@ export default [
2 { 2 {
3 name: 'news', 3 name: 'news',
4 path: '/xianyu/news', 4 path: '/xianyu/news',
5 - component: () => import(/* webpackChunkName: "news" */ './news') 5 + component: () => import(/* webpackChunkName: "news" */ './news'),
6 }, 6 },
7 { 7 {
8 name: 'newsDetail', 8 name: 'newsDetail',
@@ -7,7 +7,9 @@ @@ -7,7 +7,9 @@
7 @pulling-up="onPullingUp" 7 @pulling-up="onPullingUp"
8 :data="newsList.list"> 8 :data="newsList.list">
9 <div class="news-content"> 9 <div class="news-content">
10 - <Tab v-if="newsList.tabList.length > 0" :list="newsList.tabList"></Tab> 10 + <Tab
  11 + v-if="newsList.tabList.length > 0" :list="newsList.tabList"
  12 + @clearStore="clearStoreData"></Tab>
11 <List v-if="newsList.list.length > 0" :list="newsList && newsList.list || []"></List> 13 <List v-if="newsList.list.length > 0" :list="newsList && newsList.list || []"></List>
12 <UfoNoItem v-else :tip="`暂无数据`"></UfoNoItem> 14 <UfoNoItem v-else :tip="`暂无数据`"></UfoNoItem>
13 </div> 15 </div>
@@ -30,9 +32,6 @@ export default { @@ -30,9 +32,6 @@ export default {
30 data() { 32 data() {
31 return { 33 return {
32 options: { 34 options: {
33 - // bounce: {  
34 - // top: false  
35 - // },  
36 pullUpLoad: true 35 pullUpLoad: true
37 }, 36 },
38 msg: '消息', 37 msg: '消息',
@@ -62,6 +61,10 @@ export default { @@ -62,6 +61,10 @@ export default {
62 }; 61 };
63 await this.fetchNewsList(params); 62 await this.fetchNewsList(params);
64 this.$refs.scroll.forceUpdate(); 63 this.$refs.scroll.forceUpdate();
  64 + },
  65 +
  66 + clearStoreData(index) {
  67 + console.log(index);
65 } 68 }
66 }, 69 },
67 watch:{ 70 watch:{
@@ -28,9 +28,6 @@ export default { @@ -28,9 +28,6 @@ export default {
28 data() { 28 data() {
29 return { 29 return {
30 options: { 30 options: {
31 - // bounce: {  
32 - // top: false  
33 - // },  
34 pullUpLoad: true 31 pullUpLoad: true
35 }, 32 },
36 title: '', 33 title: '',
@@ -41,6 +38,7 @@ export default { @@ -41,6 +38,7 @@ export default {
41 ...mapState(['newsList','newsDeatilList']), 38 ...mapState(['newsList','newsDeatilList']),
42 }, 39 },
43 activated() { 40 activated() {
  41 + console.log('111');
44 let params = { 42 let params = {
45 type: this.type, 43 type: this.type,
46 isPage: true 44 isPage: true
@@ -51,9 +49,6 @@ export default { @@ -51,9 +49,6 @@ export default {
51 this.title = this.$route.query.description; 49 this.title = this.$route.query.description;
52 this.type = this.$route.query.type; 50 this.type = this.$route.query.type;
53 }, 51 },
54 - activated() {  
55 -  
56 - },  
57 methods: { 52 methods: {
58 ...mapActions(['fetchNewsList']), 53 ...mapActions(['fetchNewsList']),
59 async onPullingUp() { 54 async onPullingUp() {
@@ -61,7 +61,7 @@ export default { @@ -61,7 +61,7 @@ export default {
61 const regexp = /#\*(.*?)\*#/; 61 const regexp = /#\*(.*?)\*#/;
62 return confirmDesc.split(regexp); 62 return confirmDesc.split(regexp);
63 } else { 63 } else {
64 - return [confirmDesc]; 64 + return confirmDesc ? [confirmDesc] : [];
65 } 65 }
66 } 66 }
67 } 67 }
@@ -58,6 +58,7 @@ export default { @@ -58,6 +58,7 @@ export default {
58 display: block; 58 display: block;
59 background-size: contain; 59 background-size: contain;
60 margin-right: 40px; 60 margin-right: 40px;
  61 + background-image: url("~statics/image/order/addr-icon@3x.png");
61 } 62 }
62 63
63 .back-address-icon { 64 .back-address-icon {
@@ -100,7 +100,7 @@ export default { @@ -100,7 +100,7 @@ export default {
100 this.$createOrderPayType({ 100 this.$createOrderPayType({
101 orderCode, 101 orderCode,
102 price: parseFloat(bidDepositInfo.depositAmount), 102 price: parseFloat(bidDepositInfo.depositAmount),
103 - desc: '保证金', 103 + desc: '支付定金',
104 extra: JSON.stringify({ 104 extra: JSON.stringify({
105 forward: { 105 forward: {
106 name: 'OrderList', 106 name: 'OrderList',
@@ -103,7 +103,7 @@ export default { @@ -103,7 +103,7 @@ export default {
103 this.$createOrderPayType({ 103 this.$createOrderPayType({
104 orderCode, 104 orderCode,
105 price: parseFloat(bidDepositInfo.depositAmount), 105 price: parseFloat(bidDepositInfo.depositAmount),
106 - desc: '保证金', 106 + desc: '支付定金',
107 extra: JSON.stringify({ 107 extra: JSON.stringify({
108 forward: { 108 forward: {
109 name: 'OrderList', 109 name: 'OrderList',
@@ -5,6 +5,7 @@ const uuid = require('uuid'); @@ -5,6 +5,7 @@ const uuid = require('uuid');
5 const passport = require('passport'); 5 const passport = require('passport');
6 const TaobaoStrategy = require('./passport-taobao'); 6 const TaobaoStrategy = require('./passport-taobao');
7 const authcode = require('../../utils/authcode'); 7 const authcode = require('../../utils/authcode');
  8 +const redis = require('../../utils/redis');
8 const aes = require('./aes'); 9 const aes = require('./aes');
9 10
10 const log = global.yoho.logger; 11 const log = global.yoho.logger;
@@ -15,6 +16,7 @@ const loginPage = '//m.yohobuy.com/signin.html'; @@ -15,6 +16,7 @@ const loginPage = '//m.yohobuy.com/signin.html';
15 const homePage = `${config.siteUrl}/xianyu/channel`; 16 const homePage = `${config.siteUrl}/xianyu/channel`;
16 17
17 const URL_BIND_KEY = 'bind_code'; 18 const URL_BIND_KEY = 'bind_code';
  19 +const MAX_MSG_SEND_TIMES = 20;
18 20
19 // taobao 登录 21 // taobao 登录
20 passport.use('taobao', new TaobaoStrategy({ 22 passport.use('taobao', new TaobaoStrategy({
@@ -43,7 +45,7 @@ class passportModel extends global.yoho.BaseModel { @@ -43,7 +45,7 @@ class passportModel extends global.yoho.BaseModel {
43 constructor(ctx) { 45 constructor(ctx) {
44 super(ctx); 46 super(ctx);
45 } 47 }
46 - signinByOpenID({ nickname, openId, sourceType, businessLine}) { 48 + signinByOpenID({ nickname, openId, sourceType, sourceTypeSecond, businessLine}) {
47 let param = { 49 let param = {
48 nickname: nickname || '', 50 nickname: nickname || '',
49 openId: openId, 51 openId: openId,
@@ -55,6 +57,10 @@ class passportModel extends global.yoho.BaseModel { @@ -55,6 +57,10 @@ class passportModel extends global.yoho.BaseModel {
55 param.business_line = businessLine; 57 param.business_line = businessLine;
56 } 58 }
57 59
  60 + if (sourceTypeSecond) {
  61 + param.source_type_second = sourceTypeSecond;
  62 + }
  63 +
58 return this.get({ data: param }); 64 return this.get({ data: param });
59 } 65 }
60 syncUserSession({uid, sessionKey, req, res}) { 66 syncUserSession({uid, sessionKey, req, res}) {
@@ -119,25 +125,33 @@ class passportModel extends global.yoho.BaseModel { @@ -119,25 +125,33 @@ class passportModel extends global.yoho.BaseModel {
119 log.info(`[sync profile error] uid: ${uid} | err: ${JSON.stringify(e)}`); 125 log.info(`[sync profile error] uid: ${uid} | err: ${JSON.stringify(e)}`);
120 }); 126 });
121 } 127 }
122 - sendTaobaoBindCode(mobile) {  
123 - return this.post({  
124 - data: {  
125 - method: 'app.bind.sendCodeByTB',  
126 - source_type: 'taobao',  
127 - mobile  
128 - }  
129 - }); 128 + sendTaobaoBindCode(mobile, sourceTypeSecond) {
  129 + let data = {
  130 + method: 'app.bind.sendCodeByTB',
  131 + source_type: 'taobao',
  132 + mobile
  133 + };
  134 +
  135 + if (sourceTypeSecond) {
  136 + data.source_type_second = sourceTypeSecond;
  137 + }
  138 +
  139 + return this.post({ data });
130 } 140 }
131 - bindTaobaoAccountByCode({ mobile, code, openId }) {  
132 - return this.post({  
133 - data: {  
134 - method: 'app.bind.bindTBByCode',  
135 - source_type: 'taobao',  
136 - mobile,  
137 - code,  
138 - open_id: openId  
139 - }  
140 - }); 141 + bindTaobaoAccountByCode({ mobile, code, openId, sourceTypeSecond }) {
  142 + let data = {
  143 + method: 'app.bind.bindTBByCode',
  144 + source_type: 'taobao',
  145 + mobile,
  146 + code,
  147 + open_id: openId
  148 + };
  149 +
  150 + if (sourceTypeSecond) {
  151 + data.source_type_second = sourceTypeSecond;
  152 + }
  153 +
  154 + return this.post({ data });
141 } 155 }
142 }; 156 };
143 157
@@ -161,7 +175,8 @@ const login = { @@ -161,7 +175,8 @@ const login = {
161 175
162 return model.signinByOpenID({ 176 return model.signinByOpenID({
163 openId: user.open_uid, 177 openId: user.open_uid,
164 - sourceType: 'taobao' 178 + sourceType: 'taobao',
  179 + sourceTypeSecond: req.yoho.isAliApp ? 'xianyu' : ''
165 }).then(result => { 180 }).then(result => {
166 let redirectUrl = loginPage; 181 let redirectUrl = loginPage;
167 182
@@ -213,12 +228,27 @@ const bind = { @@ -213,12 +228,27 @@ const bind = {
213 228
214 return bindInfo; 229 return bindInfo;
215 }, 230 },
216 - sendSms(req, res, next) { 231 + async sendSms(req, res, next) {
217 let { mobile, bindCode } = req.body || {}; 232 let { mobile, bindCode } = req.body || {};
218 let info = bind.getBindThirdInfo(bindCode); 233 let info = bind.getBindThirdInfo(bindCode);
219 234
220 if (info.type === 'taobao') { 235 if (info.type === 'taobao') {
221 - req.ctx(passportModel).sendTaobaoBindCode(mobile).then(res.json).catch(next); 236 + const timeKey = `${config.app}:bindsms:taobao:${info.openId}`;
  237 + let sendTimes = await redis.getAsync(timeKey);
  238 +
  239 + sendTimes = (sendTimes || 0) + 1;
  240 +
  241 + if (sendTimes > MAX_MSG_SEND_TIMES) {
  242 + log.info(`[SMS delivery times exceeded] type: taobao | openId: ${info.openId} | mobile: ${mobile} | ua: ${req.get('user-agent')}`);
  243 +
  244 + return res.json({
  245 + code: 403,
  246 + message: '操作频繁,请稍后重试'
  247 + });
  248 + }
  249 +
  250 + redis.setex(timeKey, 60 * 60 * 2, sendTimes);
  251 + req.ctx(passportModel).sendTaobaoBindCode(mobile, req.yoho.isAliApp ? 'xianyu' : '').then(res.json).catch(next);
222 } else { 252 } else {
223 res.json({ 253 res.json({
224 code: 200, 254 code: 200,
@@ -236,7 +266,8 @@ const bind = { @@ -236,7 +266,8 @@ const bind = {
236 model.bindTaobaoAccountByCode({ 266 model.bindTaobaoAccountByCode({
237 mobile, 267 mobile,
238 code, 268 code,
239 - openId: info.openId 269 + openId: info.openId,
  270 + sourceTypeSecond: req.yoho.isAliApp ? 'xianyu' : ''
240 }).then(result => { 271 }).then(result => {
241 if (_.get(result, 'data.is_bind') === 'Y') { 272 if (_.get(result, 'data.is_bind') === 'Y') {
242 model.syncUserSession({ 273 model.syncUserSession({
1 { 1 {
2 "name": "xianyu-ufo-app-web", 2 "name": "xianyu-ufo-app-web",
3 - "version": "0.0.2-beta-15", 3 + "version": "0.0.2-beta-17",
4 "private": true, 4 "private": true,
5 "description": "Xianyu Project With Express", 5 "description": "Xianyu Project With Express",
6 "repository": { 6 "repository": {