Authored by yyq

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

1 import Vue from 'vue'; 1 import Vue from 'vue';
2 -import { ROUTE_CHANGE } from 'store/yoho/types';  
3 -import { createApp } from './app';  
4 -import { createApi } from 'create-api';  
5 -import { Style, Toast, Dialog, DatePicker, ImagePreview } from 'cube-ui'; //eslint-disable-line  
6 -import { get } from 'lodash'; 2 +import {
  3 + ROUTE_CHANGE
  4 +} from 'store/yoho/types';
  5 +import {
  6 + createApp
  7 +} from './app';
  8 +import {
  9 + createApi
  10 +} from 'create-api';
  11 +import {
  12 + Style,
  13 + Toast,
  14 + Dialog,
  15 + DatePicker,
  16 + ImagePreview
  17 +} from 'cube-ui'; //eslint-disable-line
  18 +import {
  19 + get
  20 +} from 'lodash';
7 import Lazy from 'vue-lazyload'; 21 import Lazy from 'vue-lazyload';
8 import cookie from 'yoho-cookie'; 22 import cookie from 'yoho-cookie';
9 import yoho from 'common/yoho'; 23 import yoho from 'common/yoho';
@@ -13,10 +27,13 @@ import OrderCouponList from 'components/order-coupon-list'; @@ -13,10 +27,13 @@ import OrderCouponList from 'components/order-coupon-list';
13 import OrderPromotionList from 'components/order-promotion-list'; 27 import OrderPromotionList from 'components/order-promotion-list';
14 import Bind from 'components/bind'; 28 import Bind from 'components/bind';
15 import ConfirmDialog from 'components/confirm-dialog'; 29 import ConfirmDialog from 'components/confirm-dialog';
  30 +import 'video.js/dist/video-js.css';
16 31
17 import sdk from 'yoho-activity-sdk'; 32 import sdk from 'yoho-activity-sdk';
18 33
19 -import { initClient } from 'utils/init-client'; 34 +import {
  35 + initClient
  36 +} from 'utils/init-client';
20 import 'statics/scss/common.scss'; 37 import 'statics/scss/common.scss';
21 import 'statics/font/iconfont.css'; 38 import 'statics/font/iconfont.css';
22 import 'statics/font/ufofont.css'; 39 import 'statics/font/ufofont.css';
@@ -25,7 +42,11 @@ const $app = document.getElementById('app'); @@ -25,7 +42,11 @@ const $app = document.getElementById('app');
25 42
26 const isDegrade = Boolean(!($app && $app.attributes['data-server-rendered'])); 43 const isDegrade = Boolean(!($app && $app.attributes['data-server-rendered']));
27 const context = get(window, '__INITIAL_STATE__.yoho.context'); 44 const context = get(window, '__INITIAL_STATE__.yoho.context');
28 -const { app, router, store } = createApp(context); 45 +const {
  46 + app,
  47 + router,
  48 + store
  49 +} = createApp(context);
29 const api = createApi(); 50 const api = createApi();
30 51
31 if (window.__INITIAL_STATE__) { 52 if (window.__INITIAL_STATE__) {
@@ -42,7 +63,9 @@ Vue.use(DatePicker); @@ -42,7 +63,9 @@ Vue.use(DatePicker);
42 Vue.use(Dialog); 63 Vue.use(Dialog);
43 Vue.use(ImagePreview); 64 Vue.use(ImagePreview);
44 Vue.prop('api', api); 65 Vue.prop('api', api);
45 -Vue.use(Lazy, { error: '' }); 66 +Vue.use(Lazy, {
  67 + error: ''
  68 +});
46 Vue.use(OrderPayType); 69 Vue.use(OrderPayType);
47 Vue.use(OrderCouponList); 70 Vue.use(OrderCouponList);
48 Vue.use(OrderPromotionList); 71 Vue.use(OrderPromotionList);
@@ -53,7 +76,10 @@ initClient(store); @@ -53,7 +76,10 @@ initClient(store);
53 76
54 xianyu.$router = router; 77 xianyu.$router = router;
55 yoho.auth = async (args) => { 78 yoho.auth = async (args) => {
56 - let { refer, loginUrl } = args || {}; 79 + let {
  80 + refer,
  81 + loginUrl
  82 + } = args || {};
57 let user = await sdk.getUser(true); 83 let user = await sdk.getUser(true);
58 84
59 if (user && user.uid) { 85 if (user && user.uid) {
@@ -96,7 +122,12 @@ yoho.authRealName = async () => { @@ -96,7 +122,12 @@ yoho.authRealName = async () => {
96 122
97 const fetchAsycData = (matched, r) => { 123 const fetchAsycData = (matched, r) => {
98 const asyncDataPromises = matched 124 const asyncDataPromises = matched
99 - .map(({ asyncData }) => asyncData && asyncData({ store, router: r })) 125 + .map(({
  126 + asyncData
  127 + }) => asyncData && asyncData({
  128 + store,
  129 + router: r
  130 + }))
100 .filter(p => p); 131 .filter(p => p);
101 132
102 return Promise.all(asyncDataPromises); 133 return Promise.all(asyncDataPromises);
@@ -139,7 +170,10 @@ router.onReady(() => { @@ -139,7 +170,10 @@ router.onReady(() => {
139 trackPage(to.fullPath); 170 trackPage(to.fullPath);
140 const matched = router.getMatchedComponents(to); 171 const matched = router.getMatchedComponents(to);
141 172
142 - store.commit(ROUTE_CHANGE, { to, from }); 173 + store.commit(ROUTE_CHANGE, {
  174 + to,
  175 + from
  176 + });
143 177
144 store.dispatch('reportYas', { 178 store.dispatch('reportYas', {
145 params: { 179 params: {
@@ -155,12 +189,16 @@ router.onReady(() => { @@ -155,12 +189,16 @@ router.onReady(() => {
155 fetchAsycData(matched, to) 189 fetchAsycData(matched, to)
156 .then(next) 190 .then(next)
157 .catch(e => { 191 .catch(e => {
158 - store.dispatch('reportError', { error: e }); 192 + store.dispatch('reportError', {
  193 + error: e
  194 + });
159 console.error(e); 195 console.error(e);
160 return next(); 196 return next();
161 }); 197 });
162 } catch (e) { 198 } catch (e) {
163 - store.dispatch('reportError', { error: e }); 199 + store.dispatch('reportError', {
  200 + error: e
  201 + });
164 return next(); 202 return next();
165 } 203 }
166 }); 204 });
@@ -168,6 +206,10 @@ router.onReady(() => { @@ -168,6 +206,10 @@ router.onReady(() => {
168 }); 206 });
169 207
170 router.onError(e => { 208 router.onError(e => {
171 - store.dispatch('reportError', { error: e });  
172 - router.push({ name: 'error.500' }); 209 + store.dispatch('reportError', {
  210 + error: e
  211 + });
  212 + router.push({
  213 + name: 'error.500'
  214 + });
173 }); 215 });
@@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
25 </div> 25 </div>
26 <div class="list-wrap" :style="{minHeight: total + 'px'}"> 26 <div class="list-wrap" :style="{minHeight: total + 'px'}">
27 <ProductList :list="productList.list" v-if="productList.list.length > 0"></ProductList> 27 <ProductList :list="productList.list" v-if="productList.list.length > 0"></ProductList>
28 - <UfoNoItem :tip="`暂无数据`" v-else style="margin-top: 60px;"></UfoNoItem> 28 + <UfoNoItem :tip="`暂无数据`" v-else></UfoNoItem>
29 </div> 29 </div>
30 </div> 30 </div>
31 </Scroll> 31 </Scroll>
@@ -54,13 +54,12 @@ export default { @@ -54,13 +54,12 @@ export default {
54 data() { 54 data() {
55 return { 55 return {
56 options: { 56 options: {
  57 + scrollbar: true,
57 pullUpLoad: true, 58 pullUpLoad: true,
58 // pullDownRefresh: true, 59 // pullDownRefresh: true,
59 pullDownRefresh: { 60 pullDownRefresh: {
60 txt: '刷新成功', 61 txt: '刷新成功',
61 - visible: true,  
62 } 62 }
63 -  
64 }, 63 },
65 scrollEvents: ['scroll'], 64 scrollEvents: ['scroll'],
66 scrollY: 0, 65 scrollY: 0,
@@ -157,11 +156,10 @@ export default { @@ -157,11 +156,10 @@ export default {
157 }, 156 },
158 157
159 async onPullingUp() { 158 async onPullingUp() {
160 - if (this.productList.endReached) {  
161 - this.$refs.scroll.forceUpdate();  
162 - return;  
163 - }  
164 - console.log('111') 159 + // if (this.productList.endReached) {
  160 + // this.$refs.scroll.forceUpdate();
  161 + // return;
  162 + // }
165 await this.fetchList(); 163 await this.fetchList();
166 this.$refs.scroll.forceUpdate(); 164 this.$refs.scroll.forceUpdate();
167 165
@@ -255,8 +253,8 @@ export default { @@ -255,8 +253,8 @@ export default {
255 content: ""; 253 content: "";
256 position: absolute; 254 position: absolute;
257 width: 100%; 255 width: 100%;
258 - height: 0;  
259 - box-shadow: 0 0 120px 100px #fefefe; 256 + height: 100px;
  257 + box-shadow: 0 0 120px 100px #f2f2f2 !important;
260 } 258 }
261 259
262 &.fixed-nav { 260 &.fixed-nav {
@@ -309,15 +307,16 @@ export default { @@ -309,15 +307,16 @@ export default {
309 } 307 }
310 308
311 .list-wrap { 309 .list-wrap {
312 - background: #fefefe;  
313 - overflow: hidden; 310 + background: #f2f2f2;
314 311
315 /deep/ .item { 312 /deep/ .item {
316 position: relative; 313 position: relative;
317 z-index: 1; 314 z-index: 1;
318 } 315 }
319 } 316 }
320 -.cube-scroll-wrapper {  
321 - background: #fefefe; 317 +.yohoufo-channel-page {
  318 + /deep/ .cube-pullup-wrapper {
  319 + background: #f2f2f2;
  320 + }
322 } 321 }
323 </style> 322 </style>
1 <template> 1 <template>
2 <div class="container" v-show="showType"> 2 <div class="container" v-show="showType">
3 - <div class="header">  
4 - <div class="back" @click="back()"></div> 3 + <div class="title">筛选
  4 + <div class="cancel" @click="back()">取消</div>
5 </div> 5 </div>
6 - <div class="title">筛选</div>  
7 <div class="content-search"> 6 <div class="content-search">
8 <div class="item" v-if="filterData && filterData.length" v-for="(filter,row) in filterData"> 7 <div class="item" v-if="filterData && filterData.length" v-for="(filter,row) in filterData">
9 <div class="item-title">{{filter.filterName}}</div> 8 <div class="item-title">{{filter.filterName}}</div>
@@ -210,8 +209,15 @@ export default { @@ -210,8 +209,15 @@ export default {
210 color: #000; 209 color: #000;
211 height: 82px; 210 height: 82px;
212 line-height: 82px; 211 line-height: 82px;
213 - margin-bottom: 50px;  
214 - margin-left: 40px; 212 + margin: 40px;
  213 + flex-direction: row;
  214 + display: flex;
  215 + justify-content: space-between;
  216 +
  217 + .cancel {
  218 + font-size: 38px;
  219 + color: #888;
  220 + }
215 } 221 }
216 222
217 .content-search { 223 .content-search {
@@ -36,7 +36,7 @@ import Filtrate from './filtrate'; @@ -36,7 +36,7 @@ import Filtrate from './filtrate';
36 import EmptyList from '../../components/ufo-no-item'; 36 import EmptyList from '../../components/ufo-no-item';
37 37
38 import {Scroll} from 'cube-ui'; 38 import {Scroll} from 'cube-ui';
39 -import {createNamespacedHelpers} from 'vuex'; 39 +import {mapState, createNamespacedHelpers} from 'vuex';
40 40
41 const {mapActions} = createNamespacedHelpers('list'); 41 const {mapActions} = createNamespacedHelpers('list');
42 42
@@ -93,6 +93,10 @@ export default { @@ -93,6 +93,10 @@ export default {
93 }; 93 };
94 }, 94 },
95 activated: function() { 95 activated: function() {
  96 + if (this.yoho.direction === 'forword') {
  97 + this.$refs.filtrate.hide();
  98 + Object.assign(this.$data, this.$options.data());
  99 + }
96 this.changeArrow(); 100 this.changeArrow();
97 let params = this.$route.query; 101 let params = this.$route.query;
98 102
@@ -112,8 +116,13 @@ export default { @@ -112,8 +116,13 @@ export default {
112 !params.order && (params.order = 'sale_desc'); 116 !params.order && (params.order = 'sale_desc');
113 this.fetchList({...params, isReset: true}); 117 this.fetchList({...params, isReset: true});
114 }, 118 },
  119 +
  120 + computed: {
  121 + ...mapState(['yoho'])
  122 + },
  123 +
115 methods: { 124 methods: {
116 - ...mapActions(['fetchProductList']), 125 + ...mapActions(['fetchProductList', 'getDirection']),
117 126
118 // 上拉加载 127 // 上拉加载
119 async onPullingUp() { 128 async onPullingUp() {
@@ -195,7 +204,7 @@ export default { @@ -195,7 +204,7 @@ export default {
195 this.selectedType = type; 204 this.selectedType = type;
196 if (type === 1) { 205 if (type === 1) {
197 this.priceDesc = !this.priceDesc; 206 this.priceDesc = !this.priceDesc;
198 - params.order = !this.priceDesc ? 'p_desc' : 'p_asc'; 207 + params.order = this.priceDesc ? 'p_desc' : 'p_asc';
199 } else if (type === 2) { 208 } else if (type === 2) {
200 this.priceDesc = true; 209 this.priceDesc = true;
201 params.order = 'sale_desc'; 210 params.order = 'sale_desc';
@@ -546,7 +546,7 @@ export default { @@ -546,7 +546,7 @@ export default {
546 546
547 .feeTotalRight { 547 .feeTotalRight {
548 font-family: PingFangSC-Regular; 548 font-family: PingFangSC-Regular;
549 - font-size: 14px; 549 + font-size: 14*2px;
550 color: #D0021B; 550 color: #D0021B;
551 letter-spacing: 0; 551 letter-spacing: 0;
552 text-align: right; 552 text-align: right;
@@ -10,13 +10,6 @@ @@ -10,13 +10,6 @@
10 <i class="cubeic-arrow" ></i> 10 <i class="cubeic-arrow" ></i>
11 </div> 11 </div>
12 </div> 12 </div>
13 - <!--<Select-->  
14 - <!--v-model="chooseday"-->  
15 - <!--:title="title"-->  
16 - <!--:options="options"-->  
17 - <!--@change="change"-->  
18 - <!--class="customSelect"-->  
19 - <!--/>-->  
20 </div> 13 </div>
21 14
22 </template> 15 </template>
@@ -88,20 +81,16 @@ export default { @@ -88,20 +81,16 @@ export default {
88 </script> 81 </script>
89 82
90 <style lang="scss" scoped> 83 <style lang="scss" scoped>
91 -  
92 .customSelectWrapper { 84 .customSelectWrapper {
93 -  
94 position: relative; 85 position: relative;
95 -  
96 height: 60px; 86 height: 60px;
97 padding-top: 10px; 87 padding-top: 10px;
98 } 88 }
99 89
100 .customSelectTextWrapper { 90 .customSelectTextWrapper {
101 -  
102 position: absolute; 91 position: absolute;
103 width: 100%; 92 width: 100%;
104 - height: 100%; 93 + height: 60px;
105 display: flex; 94 display: flex;
106 flex-direction: row; 95 flex-direction: row;
107 justify-content: space-between; 96 justify-content: space-between;
@@ -110,7 +99,7 @@ export default { @@ -110,7 +99,7 @@ export default {
110 99
111 .leftText { 100 .leftText {
112 font-family: PingFang-SC-Regular; 101 font-family: PingFang-SC-Regular;
113 - font-size: 14px; 102 + font-size: 14*2px;
114 color: #000000; 103 color: #000000;
115 letter-spacing: 0; 104 letter-spacing: 0;
116 } 105 }
@@ -121,7 +110,7 @@ export default { @@ -121,7 +110,7 @@ export default {
121 110
122 .rightText { 111 .rightText {
123 font-family: PingFang-SC-Regular; 112 font-family: PingFang-SC-Regular;
124 - font-size: 14px; 113 + font-size: 14*2px;
125 color: #000000; 114 color: #000000;
126 letter-spacing: 0; 115 letter-spacing: 0;
127 } 116 }
1 <template> 1 <template>
2 - <div class="change-bid-price-wrapper"></div> 2 + <div class="change-bid-price-wrapper">
  3 + <p class="price-item">
  4 + <span>我的求购价:</span>
  5 + <span>¥{{ goodsInfo.goodPrice }}</span>
  6 + </p>
  7 + <p class="price-item">
  8 + <span>当前最高求购价:</span>
  9 + <span>¥{{ goodsInfo.goodPrice }}</span>
  10 + </p>
  11 + <p class="price-item">
  12 + <span>最低现货价:</span>
  13 + <span>¥{{ goodsInfo.leastPrice }}</span>
  14 + </p>
  15 + <p v-for="(priceInfo, i) in computePriceList" :key="i">
  16 + <span>{{ priceInfo.promotion }}:</span>
  17 + <span>{{ priceInfo.promotionAmount }}</span>
  18 + </p>
  19 + <p class="a-tip">Tip: 调整求购价成功后,当前的求购将被关闭</p>
  20 + </div>
3 </template> 21 </template>
4 22
5 <script> 23 <script>
6 -export default {}; 24 +import { createNamespacedHelpers } from "vuex";
  25 +const { mapActions } = createNamespacedHelpers("order/orderList");
  26 +export default {
  27 + props: {
  28 + computePriceInfo: {
  29 + type: Object,
  30 + default: () => ({})
  31 + },
  32 + goodsInfo: {
  33 + type: Object,
  34 + default: () => ({})
  35 + }
  36 + },
  37 + computed: {
  38 + computePriceList() {
  39 + return this.computePriceInfo.promotionFormulaList.filter(
  40 + ({ promotion }) => promotion === "运费" || promotion === "实付金额"
  41 + );
  42 + }
  43 + },
  44 + methods: {
  45 + ...mapActions(["computeChangePrice", "changePrice"])
  46 + }
  47 +};
7 </script> 48 </script>
8 49
9 -<style scoped> 50 +<style lang="scss" scoped>
10 .change-bid-price-wrapper { 51 .change-bid-price-wrapper {
  52 + font-size: 12px;
  53 + color: #000;
  54 + padding: 0 38px;
  55 + letter-spacing: 0;
  56 +
  57 + .tip {
  58 + color: #999;
  59 + }
11 } 60 }
12 </style> 61 </style>
1 <template> 1 <template>
2 - <div class="actions-wrapper">  
3 - <Button  
4 - v-for="action in actionList"  
5 - :key="action.code"  
6 - @click="() => onActionHandler(action)" 2 + <div class="pane-body">
  3 + <div
  4 + class="video-wrapper"
  5 + v-if="appraiseVideoUrl"
  6 + @click="() => onVideoHandler({videoUrl:appraiseVideoUrl, orderCode: order.orderCode})"
7 > 7 >
8 - {{ action.text }}  
9 - </Button> 8 + <div class="play-btn"></div>
  9 + <div class="play-txt">鉴定视频</div>
  10 + </div>
  11 + <div class="after-video" v-else></div>
  12 + <div class="actions-wrapper">
  13 + <Button
  14 + v-for="action in actionList"
  15 + :key="action.code"
  16 + @click="() => onActionHandler(action)"
  17 + >{{ action.text }}</Button>
  18 + </div>
10 </div> 19 </div>
11 </template> 20 </template>
12 21
@@ -27,6 +36,9 @@ export default { @@ -27,6 +36,9 @@ export default {
27 computed: { 36 computed: {
28 actionList: function() { 37 actionList: function() {
29 return this.order.buttons; 38 return this.order.buttons;
  39 + },
  40 + appraiseVideoUrl: function() {
  41 + return this.order.appraiseVideoUrl;
30 } 42 }
31 }, 43 },
32 methods: { 44 methods: {
@@ -125,6 +137,9 @@ export default { @@ -125,6 +137,9 @@ export default {
125 default: 137 default:
126 this.$emit("on-action", action); 138 this.$emit("on-action", action);
127 } 139 }
  140 + },
  141 + onVideoHandler(params) {
  142 + this.$emit("on-video", params);
128 } 143 }
129 } 144 }
130 }; 145 };
@@ -146,6 +161,33 @@ export default { @@ -146,6 +161,33 @@ export default {
146 </style> 161 </style>
147 162
148 <style lang="scss" scoped> 163 <style lang="scss" scoped>
  164 +.pane-body {
  165 + display: flex;
  166 + justify-content: space-between;
  167 +}
  168 +
  169 +.video-wrapper {
  170 + display: flex;
  171 + align-items: center;
  172 +
  173 + .play-btn {
  174 + width: 28.4px;
  175 + height: 28.4px;
  176 + background: url("~statics/image/order/play@3x.png");
  177 + background-size: cover;
  178 + }
  179 + .play-txt {
  180 + margin-left: 6.8px;
  181 + color: #000;
  182 + font-size: 24px;
  183 + line-height: 1.4;
  184 + }
  185 +}
  186 +
  187 +.after-video {
  188 + background-color: transparent;
  189 +}
  190 +
149 .actions-wrapper { 191 .actions-wrapper {
150 display: flex; 192 display: flex;
151 justify-content: flex-end; 193 justify-content: flex-end;
  1 +<template>
  2 + <div class="video-player">
  3 + <video
  4 + v-if="showVideo"
  5 + ref="videoPlayer"
  6 + class="video-js vjs-matrix vjs-yoho"
  7 + controls
  8 + :poster="coverImg"
  9 + preload="auto"
  10 + muted="muted"
  11 + autoplay="none"
  12 + playsinline
  13 + x5-playsinline
  14 + webkit-playsinline="true"
  15 + >
  16 + <source :src="source" :type="sourceType" />
  17 + <p class="vjs-no-js">
  18 + To view this video please enable JavaScript, and consider upgrading to a
  19 + web browser
  20 + </p>
  21 + <div class="vjs-yoho-voice"></div>
  22 + </video>
  23 + </div>
  24 +</template>
  25 +
  26 +<script>
  27 +import { get } from "lodash";
  28 +import videojs from "video.js";
  29 +import { getArticleImageSize, processImage } from "utils/image-handler";
  30 +
  31 +export default {
  32 + name: "VideoPlayer",
  33 + props: {
  34 + source: String,
  35 + cover: String,
  36 + width: [Number, String],
  37 + height: [Number, String],
  38 + options: {
  39 + type: Object,
  40 + default() {
  41 + return {
  42 + muted: true,
  43 + controls: true,
  44 + aspectRatio: "1:1"
  45 + };
  46 + }
  47 + }
  48 + },
  49 + data() {
  50 + return {
  51 + showVideo: false,
  52 + player: null
  53 + };
  54 + },
  55 + computed: {
  56 + coverImg() {
  57 + if (this.cover) {
  58 + if (this.width && this.height) {
  59 + let imgSize = getArticleImageSize({
  60 + width: this.width,
  61 + height: this.height,
  62 + minScale: 0,
  63 + maxWidth: 500
  64 + });
  65 +
  66 + return processImage(
  67 + this.cover,
  68 + 2,
  69 + imgSize.width,
  70 + imgSize.height,
  71 + get(this.yoho, "window.supportWebp")
  72 + );
  73 + } else {
  74 + return this.cover.split("?")[0];
  75 + }
  76 + } else {
  77 + return "";
  78 + }
  79 + },
  80 + sourceType() {
  81 + let type = "video/mp4";
  82 +
  83 + if (this.source) {
  84 + let source = this.source.split("?")[0];
  85 +
  86 + source = source.split(".");
  87 +
  88 + switch (source[source.length - 1]) {
  89 + case "opus":
  90 + case "ogv":
  91 + type = "video/ogg";
  92 + break;
  93 + case "mkv":
  94 + type = "video/x-matroska";
  95 + break;
  96 + case "m3u8":
  97 + type = "application/x-mpegURL";
  98 + break;
  99 + case "m4a":
  100 + type = "audio/mp4";
  101 + break;
  102 + case "mp3":
  103 + type = "audio/mpeg";
  104 + break;
  105 + case "aac":
  106 + type = "audio/aac";
  107 + break;
  108 + case "oga":
  109 + type = "audio/ogg";
  110 + break;
  111 + default:
  112 + break;
  113 + }
  114 + }
  115 +
  116 + return type;
  117 + }
  118 + },
  119 + watch: {
  120 + source() {
  121 + this.showPlayer();
  122 + }
  123 + },
  124 + mounted() {
  125 + this.showPlayer();
  126 + },
  127 + beforeDestroy() {
  128 + if (this.player) {
  129 + this.player.dispose();
  130 + }
  131 + },
  132 + methods: {
  133 + parentHandleclick() {
  134 + this.player.play();
  135 + const timeId = setTimeout(() => {
  136 + this.player.requestFullscreen();
  137 + clearTimeout(timeId);
  138 + });
  139 + },
  140 + showPlayer() {
  141 + if (this.showVideo || !this.source) {
  142 + return;
  143 + }
  144 +
  145 + this.showVideo = true;
  146 + this.$nextTick(() => {
  147 + this.initPlayer();
  148 + });
  149 + },
  150 + initPlayer() {
  151 + const noVioceClass = "vjs-yoho-novoice";
  152 +
  153 + this.player = videojs(this.$refs.videoPlayer, this.options);
  154 +
  155 + this.voiceBtn = this.player.addChild("button");
  156 + this.voiceBtn.addClass("vjs-yoho-voice");
  157 + this.voiceBtn.addClass(noVioceClass);
  158 + this.backBtn = this.player.addChild("button");
  159 + this.backBtn.addClass("vjs-yoho-back");
  160 + this.voiceBtn.on("touchend", () => {
  161 + this.player.muted(!this.voiceBtn.hasClass(noVioceClass));
  162 + });
  163 + this.backBtn.on("touchend", () => {
  164 + this.player.exitFullscreen();
  165 + });
  166 +
  167 + this.player.on("play", () => {
  168 + this.player._yohoPlayTime = this.getTime();
  169 + });
  170 + this.player.on("pause", () => {
  171 + this.player._yohoPauseTime = this.getTime();
  172 + });
  173 + this.player.on("ended", () => {
  174 + this.player._yohoEndedTime = this.getTime();
  175 + });
  176 +
  177 + this.player.on("fullscreenchange", () => {
  178 + this.player._yohoPlayTime = this.getTime();
  179 + });
  180 +
  181 + this.player.on("volumechange", () => {
  182 + const soundOff = this.player.muted() || this.player.volume() === 0;
  183 +
  184 + if (soundOff) {
  185 + this.voiceBtn.addClass(noVioceClass);
  186 + } else {
  187 + this.voiceBtn.removeClass(noVioceClass);
  188 + }
  189 + });
  190 +
  191 + // setTimeout(() => {
  192 + // this.$yoho.getNetStatus({}, res => {
  193 + // if (res && +res.wifi === 1) {
  194 + // this.player.autoplay("muted");
  195 + // }
  196 + // });
  197 + // }, 1000);
  198 + },
  199 + getTime() {
  200 + return new Date().getTime();
  201 + }
  202 + }
  203 +};
  204 +</script>
  205 +
  206 +<style lang="scss" scoped>
  207 +.video-js {
  208 + width: 100%;
  209 + height: auto;
  210 +
  211 + video {
  212 + width: 100%;
  213 + }
  214 +
  215 + &.vjs-yoho /deep/ {
  216 + position: relative;
  217 + background-color: #222;
  218 +
  219 + .vjs-resize-manager {
  220 + z-index: 0;
  221 + visibility: hidden;
  222 + }
  223 +
  224 + .vjs-poster {
  225 + background-color: #222;
  226 + }
  227 +
  228 + .vjs-yoho-voice {
  229 + width: 60px;
  230 + height: 60px;
  231 + position: absolute;
  232 + top: 20px;
  233 + right: 28px;
  234 + opacity: 0;
  235 + visibility: hidden;
  236 + background: url("~statics/image/components/video-voice-icon.png");
  237 + background-size: cover;
  238 + background-repeat: no-repeat;
  239 +
  240 + &.vjs-yoho-novoice {
  241 + background-position: bottom left;
  242 + }
  243 + }
  244 +
  245 + &.vjs-has-started .vjs-yoho-voice {
  246 + visibility: visible;
  247 + opacity: 1;
  248 + transition: visibility 1s, opacity 1s;
  249 + }
  250 +
  251 + &.vjs-has-started.vjs-user-inactive.vjs-playing .vjs-yoho-voice {
  252 + visibility: visible;
  253 + opacity: 0;
  254 + }
  255 +
  256 + .vjs-big-play-button {
  257 + width: 126px;
  258 + height: 126px;
  259 + line-height: 126px;
  260 + font-size: 60px;
  261 + border: none;
  262 + left: 50%;
  263 + top: 50%;
  264 + margin: -63px auto auto -63px;
  265 +
  266 + /*background: url("~statics/image/components/video-play-btn.png");*/
  267 + background: url("data:image/png;base64,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");
  268 + background-size: contain;
  269 + background-repeat: no-repeat;
  270 +
  271 + > * {
  272 + display: none;
  273 + }
  274 + }
  275 +
  276 + @keyframes roundframe {
  277 + 0% {
  278 + -webkit-transform: rotate(0deg);
  279 + }
  280 + 25% {
  281 + -webkit-transform: rotate(90deg);
  282 + }
  283 + 50% {
  284 + -webkit-transform: rotate(180deg);
  285 + }
  286 + 75% {
  287 + -webkit-transform: rotate(270deg);
  288 + }
  289 + 100% {
  290 + -webkit-transform: rotate(360deg);
  291 + }
  292 + }
  293 +
  294 + .vjs-loading-spinner {
  295 + width: 110px;
  296 + height: 110px;
  297 + margin-top: -55px;
  298 + margin-left: -55px;
  299 + border: none;
  300 + background: url("~statics/image/components/video-loading-icon.png");
  301 + background-size: contain;
  302 + background-repeat: no-repeat;
  303 + background-position: center center;
  304 + visibility: visible;
  305 + animation: roundframe 1.3s linear infinite;
  306 +
  307 + &:before,
  308 + &:after,
  309 + > * {
  310 + display: none;
  311 + }
  312 + }
  313 +
  314 + .vjs-control-bar {
  315 + height: 80px;
  316 + background: none;
  317 + padding-bottom: 20px;
  318 +
  319 + .vjs-control {
  320 + width: 80px;
  321 + }
  322 +
  323 + .vjs-play-control {
  324 + width: 60px;
  325 + height: 60px;
  326 + margin-left: 20px;
  327 + background: url("~statics/image/components/video-play-icon.png");
  328 + background-size: cover;
  329 +
  330 + &.vjs-playing {
  331 + background-position: bottom left;
  332 + }
  333 +
  334 + > * {
  335 + display: none;
  336 + }
  337 + }
  338 +
  339 + .vjs-volume-panel {
  340 + display: none;
  341 + }
  342 +
  343 + .vjs-duration,
  344 + .vjs-current-time {
  345 + display: block;
  346 + order: 3;
  347 +
  348 + > span {
  349 + font-size: 22px;
  350 + font-weight: 300;
  351 + }
  352 + }
  353 +
  354 + .vjs-time-control {
  355 + line-height: 60px;
  356 + }
  357 +
  358 + .vjs-current-time {
  359 + order: 1;
  360 + }
  361 +
  362 + .vjs-remaining-time {
  363 + display: none;
  364 + }
  365 +
  366 + .vjs-progress-control {
  367 + order: 2;
  368 +
  369 + .vjs-progress-holder {
  370 + margin: 0;
  371 + }
  372 +
  373 + .vjs-progress-holder,
  374 + .vjs-load-progress,
  375 + .vjs-play-progress {
  376 + height: 1px;
  377 + }
  378 +
  379 + .vjs-play-progress:before {
  380 + font-size: 10px;
  381 + top: 0;
  382 + transform: translateY(-44%);
  383 + }
  384 + }
  385 +
  386 + .vjs-fullscreen-control {
  387 + order: 4;
  388 + width: 60px;
  389 + height: 60px;
  390 + margin-right: 20px;
  391 + background: url("~statics/image/components/video-fullscreen-icon.png");
  392 + background-size: cover;
  393 +
  394 + > * {
  395 + display: none;
  396 + }
  397 + }
  398 +
  399 + .vjs-icon-placeholder:before {
  400 + font-size: 38px;
  401 + line-height: 60px;
  402 + }
  403 + }
  404 +
  405 + &.vjs-fullscreen .vjs-fullscreen-control {
  406 + background-position: bottom left;
  407 + }
  408 +
  409 + &.vjs-fullscreen .vjs-yoho-back {
  410 + width: 40px;
  411 + height: 42px;
  412 + background: url("~statics/image/components/video-back-icon.png");
  413 + background-size: contain;
  414 + background-repeat: no-repeat;
  415 + position: absolute;
  416 + top: 20px;
  417 + left: 32px;
  418 + }
  419 + }
  420 +}
  421 +</style>
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 import { orderActionsMap, ownType } from 'constants/order-constants'; 3 import { orderActionsMap, ownType } from 'constants/order-constants';
4 import { createNamespacedHelpers } from 'vuex'; 4 import { createNamespacedHelpers } from 'vuex';
5 import DialogConfirmInfo from '../../components/dialog-confirm-info'; 5 import DialogConfirmInfo from '../../components/dialog-confirm-info';
  6 +import DialogChangeBidPrice from '../../components/dialog-change-bid-price';
6 7
7 const { mapActions, mapMutations } = createNamespacedHelpers('order/orderList'); 8 const { mapActions, mapMutations } = createNamespacedHelpers('order/orderList');
8 const { mapMutations: inSaleMapMutations } = createNamespacedHelpers( 9 const { mapMutations: inSaleMapMutations } = createNamespacedHelpers(
@@ -11,14 +12,25 @@ const { mapMutations: inSaleMapMutations } = createNamespacedHelpers( @@ -11,14 +12,25 @@ const { mapMutations: inSaleMapMutations } = createNamespacedHelpers(
11 12
12 export default { 13 export default {
13 methods: { 14 methods: {
14 - ...mapActions(['cancelTradeConfirmInfo', 'cancelTrade', 'deleteOrder']), 15 + ...mapActions([
  16 + 'cancelTradeConfirmInfo',
  17 + 'cancelTrade',
  18 + 'deleteOrder',
  19 + 'computeChangePrice',
  20 + 'changePrice',
  21 + ]),
15 ...mapMutations(['filterOrderList', 'resetData']), 22 ...mapMutations(['filterOrderList', 'resetData']),
16 ...inSaleMapMutations(['filterInSaleOrderList']), 23 ...inSaleMapMutations(['filterInSaleOrderList']),
17 24
18 // 订单列表 25 // 订单列表
19 async onAction({ action, order }) { 26 async onAction({ action, order }) {
20 const { owner = ownType.SELL } = this.$route.params; 27 const { owner = ownType.SELL } = this.$route.params;
21 - const { orderCode, realPrice = '', bidDepositInfo = {} } = order; 28 + const {
  29 + orderCode,
  30 + realPrice = '',
  31 + bidDepositInfo = {},
  32 + goodsInfo = {},
  33 + } = order;
22 34
23 switch (action.name) { 35 switch (action.name) {
24 case orderActionsMap.DEL_ORDER.name: 36 case orderActionsMap.DEL_ORDER.name:
@@ -140,7 +152,27 @@ export default { @@ -140,7 +152,27 @@ export default {
140 } 152 }
141 153
142 case orderActionsMap.CHANGE_BID_PRICE.name: { 154 case orderActionsMap.CHANGE_BID_PRICE.name: {
143 - this.$createDialog({ type: 'prompt' }).show(); 155 + const { goodPrice } = goodsInfo;
  156 + const computePriceInfo = await this.computeChangePrice({
  157 + orderCode,
  158 + price: goodPrice,
  159 + });
  160 +
  161 + this.$createDialog(
  162 + {
  163 + type: 'prompt',
  164 + confirmBtn: { text: '调整求购价' },
  165 + cancelBtn: { active: true },
  166 + },
  167 + createElement => {
  168 + return [
  169 + createElement(DialogChangeBidPrice, {
  170 + props: { computePriceInfo, goodsInfo },
  171 + slot: 'content',
  172 + }),
  173 + ];
  174 + },
  175 + ).show();
144 break; 176 break;
145 } 177 }
146 case orderActionsMap.NOT_SOLD.name: { 178 case orderActionsMap.NOT_SOLD.name: {
@@ -20,17 +20,21 @@ @@ -20,17 +20,21 @@
20 class="actions" 20 class="actions"
21 :order="order" 21 :order="order"
22 @on-action="action => onAction({ action, order })" 22 @on-action="action => onAction({ action, order })"
  23 + @on-video="params => onVideoHandle(params)"
23 /> 24 />
24 </div> 25 </div>
  26 + <div ref="videoWrapper">
  27 + <VideoPlayer
  28 + :ref="order.orderCode"
  29 + class="play-video"
  30 + :source="order.appraiseVideoUrl"
  31 + ></VideoPlayer>
  32 + </div>
25 </li> 33 </li>
26 </ul> 34 </ul>
27 </scroll> 35 </scroll>
28 36
29 - <empty-list  
30 - class="empty-wrapper"  
31 - tip="这里什么都没有..."  
32 - v-show="isShowEmpty"  
33 - /> 37 + <empty-list class="empty-wrapper" tip="这里什么都没有..." v-show="isShowEmpty" />
34 </div> 38 </div>
35 </layout-app> 39 </layout-app>
36 </template> 40 </template>
@@ -42,6 +46,7 @@ import { createNamespacedHelpers } from "vuex"; @@ -42,6 +46,7 @@ import { createNamespacedHelpers } from "vuex";
42 import OrderItem from "./components/order-item"; 46 import OrderItem from "./components/order-item";
43 import StatusNav from "./components/status-nav"; 47 import StatusNav from "./components/status-nav";
44 import OrderItemHeader from "./components/order-item-header"; 48 import OrderItemHeader from "./components/order-item-header";
  49 +import VideoPlayer from "./components/video-player";
45 50
46 import EmptyList from "components//ufo-no-item"; 51 import EmptyList from "components//ufo-no-item";
47 52
@@ -64,7 +69,8 @@ export default { @@ -64,7 +69,8 @@ export default {
64 OrderItemHeader, 69 OrderItemHeader,
65 EmptyList, 70 EmptyList,
66 OrderActions, 71 OrderActions,
67 - CountDown 72 + CountDown,
  73 + VideoPlayer
68 }, 74 },
69 computed: { 75 computed: {
70 ...mapState(["orderList", "pullUpLoad", "isShowEmpty"]), 76 ...mapState(["orderList", "pullUpLoad", "isShowEmpty"]),
@@ -87,6 +93,24 @@ export default { @@ -87,6 +93,24 @@ export default {
87 ...mapActions(["fetchOrderList", "confirmReceipt"]), 93 ...mapActions(["fetchOrderList", "confirmReceipt"]),
88 fetchData() { 94 fetchData() {
89 this.fetchOrderList(this.$route.params); 95 this.fetchOrderList(this.$route.params);
  96 + },
  97 + onVideoHandle({ videoUrl, orderCode }) {
  98 + if (!videoUrl) {
  99 + return;
  100 + }
  101 + const $video = this.$refs[`${orderCode}`][0];
  102 + if ($video) {
  103 + $video.parentHandleclick();
  104 + }
  105 + }
  106 + },
  107 +
  108 + mounted() {
  109 + if (this.$yoho.isAndroid) {
  110 + this.$refs.videoWrapper.forEach($vnode => {
  111 + $vnode.style.position = "absolute";
  112 + $vnode.style.top = "-1000px";
  113 + });
90 } 114 }
91 } 115 }
92 }; 116 };
@@ -121,10 +145,16 @@ export default { @@ -121,10 +145,16 @@ export default {
121 border-bottom: 1px solid #eee; 145 border-bottom: 1px solid #eee;
122 } 146 }
123 147
  148 + .play-video {
  149 + display: inline-block;
  150 + height: 10px;
  151 + opacity: 0;
  152 + }
  153 +
124 & :last-child { 154 & :last-child {
125 border-bottom: 0; 155 border-bottom: 0;
126 } 156 }
127 } 157 }
128 } 158 }
129 } 159 }
130 -</style>  
  160 +</style>
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 28
29 <script> 29 <script>
30 import { Scroll } from 'cube-ui'; 30 import { Scroll } from 'cube-ui';
31 -import { sortBy } from 'lodash'; 31 +import { orderBy } from 'lodash';
32 32
33 export default { 33 export default {
34 name: 'size-list', 34 name: 'size-list',
@@ -73,13 +73,40 @@ export default { @@ -73,13 +73,40 @@ export default {
73 return this.list || []; 73 return this.list || [];
74 } 74 }
75 75
76 - if (!this.simplePrice) {  
77 - const list = sortBy(this.list, 'order_by').reverse(); 76 + let list;
78 77
79 - return list.map(this.priceMap); 78 + if (!this.simplePrice) {
  79 + list = this.list.map(this.priceMap);
  80 + } else {
  81 + list = this.list.map(this.simplePriceMap);
80 } 82 }
81 83
82 - return this.list.map(this.simplePriceMap); 84 + /**
  85 + * 根据 name 及 subName 从小到大排列
  86 + * @type {Array}
  87 + */
  88 + const sorted = orderBy(list, [o => parseFloat(o.name), o => {
  89 + if (o.subName == null) {
  90 + return 0;
  91 + }
  92 +
  93 + let subName = o.subName.split('/');
  94 +
  95 + if (subName.length === 2) {
  96 + if (subName[1] === '0') {
  97 + subName = subName[0];
  98 + } else {
  99 + subName = parseFloat(subName[0]) / parseFloat(subName[1]);
  100 + }
  101 + }
  102 + subName = parseFloat(subName);
  103 + if (isNaN(subName)) {
  104 + return 0;
  105 + }
  106 + return subName;
  107 + }]);
  108 +
  109 + return sorted;
83 }, 110 },
84 }, 111 },
85 methods: { 112 methods: {
@@ -95,10 +122,10 @@ export default { @@ -95,10 +122,10 @@ export default {
95 const name = info.size_name.split(/\s+/); 122 const name = info.size_name.split(/\s+/);
96 123
97 // 区分交易(buy|sell),变现 124 // 区分交易(buy|sell),变现
98 - const isTradable = info.storage_num > 0 && price !== '-'; 125 + const isTradable = this.config.type === 'buy' && info.storage_num > 0 && price !== '-';
99 126
100 // 出售: 只要上架,都可出售 127 // 出售: 只要上架,都可出售
101 - const isMarketable = this.config.type === 'sell' || info.bid_moster_price > 0; 128 + const isMarketable = this.config.type === 'sell';
102 129
103 return { 130 return {
104 size_id: info.size_id, 131 size_id: info.size_id,
@@ -29,7 +29,7 @@ @@ -29,7 +29,7 @@
29 <transition name="slide-up"> 29 <transition name="slide-up">
30 30
31 <div class="footer" v-if="isAvailable"> 31 <div class="footer" v-if="isAvailable">
32 - <cube-button v-if="config.type === 'sell'" @click="convertToCash" :class="{active: isMarketable}">变现<span> <i>¥</i>{{cashPrice}}</span></cube-button> 32 + <cube-button v-if="isQiugouEnabled && isMarketable" @click="convertToCash" :class="{active: isMarketable}">变现<span> <i>¥</i>{{cashPrice}}</span></cube-button>
33 <cube-button @click="select" :class="{active: isTradable}">{{config.title}}</cube-button> 33 <cube-button @click="select" :class="{active: isTradable}">{{config.title}}</cube-button>
34 </div> 34 </div>
35 </transition> 35 </transition>
@@ -41,7 +41,7 @@ @@ -41,7 +41,7 @@
41 <script> 41 <script>
42 import { Scroll, Button } from 'cube-ui'; 42 import { Scroll, Button } from 'cube-ui';
43 import { get } from 'lodash'; 43 import { get } from 'lodash';
44 -import { createNamespacedHelpers, mapActions } from 'vuex'; 44 +import { createNamespacedHelpers, mapActions, mapGetters } from 'vuex';
45 45
46 import ActionSheet from './action-sheet'; 46 import ActionSheet from './action-sheet';
47 import SizeList from './size-list'; 47 import SizeList from './size-list';
@@ -83,6 +83,7 @@ export default { @@ -83,6 +83,7 @@ export default {
83 }, 83 },
84 computed: { 84 computed: {
85 ...mapState(['selectedProductInfo']), 85 ...mapState(['selectedProductInfo']),
  86 + ...mapGetters(['isQiugouEnabled']),
86 selectedSize() { 87 selectedSize() {
87 if (this.selectedProductInfo.productId === this.product.product_id) { 88 if (this.selectedProductInfo.productId === this.product.product_id) {
88 return this.selectedProductInfo.size; 89 return this.selectedProductInfo.size;
@@ -114,7 +115,8 @@ export default { @@ -114,7 +115,8 @@ export default {
114 isTradable() { 115 isTradable() {
115 return this.isAvailable && ( 116 return this.isAvailable && (
116 (this.config.type === 'buy' && this.selectedSize.storage_num > 0 && this.selectedSize.least_price !== '-') || 117 (this.config.type === 'buy' && this.selectedSize.storage_num > 0 && this.selectedSize.least_price !== '-') ||
117 - (this.config.type === 'sell')); 118 + this.isMarketable
  119 + );
118 }, 120 },
119 121
120 /** 122 /**
@@ -133,7 +135,7 @@ export default { @@ -133,7 +135,7 @@ export default {
133 * 通过bid_moster_price或bid_skup判断 135 * 通过bid_moster_price或bid_skup判断
134 */ 136 */
135 isMarketable() { 137 isMarketable() {
136 - return this.cashPrice > 0; 138 + return this.config.type === 'sell' && this.cashPrice > 0;
137 } 139 }
138 }, 140 },
139 mounted() { 141 mounted() {
@@ -183,12 +183,10 @@ export default { @@ -183,12 +183,10 @@ export default {
183 } 183 }
184 }, 184 },
185 activated() { 185 activated() {
186 - if (this.productId !== this.productDetail.product_id) {  
187 - this.loadData(this.productId);  
188 - } 186 + this.loadData(this.productId);
189 }, 187 },
190 methods: { 188 methods: {
191 - ...mapActions(['fetchProductInfo', 'fetchTop3', 'fetchFav', 'toggleFav', 'updateTradeInfo', 'getSelectedTradeProduct', 'payment']), 189 + ...mapActions(['fetchProductInfo', 'fetchTop3', 'fetchFav', 'toggleFav', 'updateTradeInfo', 'getSelectedTradeProduct', 'payment', 'resetSelectedSize']),
192 refresh() { 190 refresh() {
193 this.$refs.slide.refresh(); 191 this.$refs.slide.refresh();
194 }, 192 },
@@ -295,6 +293,7 @@ export default { @@ -295,6 +293,7 @@ export default {
295 return; 293 return;
296 } 294 }
297 295
  296 + this.resetSelectedSize();
298 this.selectSizeConfig = { 297 this.selectSizeConfig = {
299 dest: 'OrderBuyConfirm', 298 dest: 'OrderBuyConfirm',
300 type: 'buy', 299 type: 'buy',
@@ -313,6 +312,7 @@ export default { @@ -313,6 +312,7 @@ export default {
313 return; 312 return;
314 } 313 }
315 314
  315 + this.resetSelectedSize();
316 this.selectSizeConfig = { 316 this.selectSizeConfig = {
317 dest: 'OrderSellConfirm', 317 dest: 'OrderSellConfirm',
318 type: 'sell', 318 type: 'sell',
@@ -61,12 +61,7 @@ export default function() { @@ -61,12 +61,7 @@ export default function() {
61 let result = await this.$api.get('/api/ufo/list/searchSuggest', {query}); 61 let result = await this.$api.get('/api/ufo/list/searchSuggest', {query});
62 62
63 commit('setSearchSuggest', {searchSuggestList: result.data}); 63 commit('setSearchSuggest', {searchSuggestList: result.data});
64 -  
65 }, 64 },
66 -  
67 - initData: function({commit}) {  
68 - commit('initData');  
69 - }  
70 } 65 }
71 }; 66 };
72 } 67 }
@@ -157,6 +157,29 @@ export default function() { @@ -157,6 +157,29 @@ export default function() {
157 157
158 return res.code === 200 ? res.data : null; 158 return res.code === 200 ? res.data : null;
159 }, 159 },
  160 +
  161 + // 买家调价计算
  162 + async computeChangePrice(_, { orderCode, price }) {
  163 + const res = await this.$api.get(
  164 + '/api/order/buyerask/computechangeprice',
  165 + {
  166 + orderCode: `${orderCode}`,
  167 + price: +price,
  168 + },
  169 + );
  170 +
  171 + return res.code === 200 ? res.data : null;
  172 + },
  173 +
  174 + // 买家调价
  175 + async changePrice(_, { orderCode, price }) {
  176 + const res = await this.$api.post('/api/order/buyerask/changeprice', {
  177 + orderCode: `${orderCode}`,
  178 + price: +price,
  179 + });
  180 +
  181 + return res.code === 200 ? res.data : null;
  182 + },
160 }, 183 },
161 getters: {}, 184 getters: {},
162 }; 185 };
@@ -100,6 +100,9 @@ export default { @@ -100,6 +100,9 @@ export default {
100 100
101 return state.selectedProductInfo; 101 return state.selectedProductInfo;
102 }, 102 },
  103 + resetSelectedSize({commit}) {
  104 + commit(Types.RESET_SELECTED_PRODUCT_SIZE);
  105 + },
103 async requestSize({ state }, { sizeIds }) { 106 async requestSize({ state }, { sizeIds }) {
104 const selectedProduct = state.selectedProductInfo; 107 const selectedProduct = state.selectedProductInfo;
105 108
1 import actions from './actions'; 1 import actions from './actions';
2 import mutations from './mutations'; 2 import mutations from './mutations';
3 3
  4 +export function defaultSelectedSize() {
  5 + return {
  6 + productId: null,
  7 + product: {},
  8 + sizeId: null,
  9 + storageId: null,
  10 + size: {},
  11 + };
  12 +}
  13 +
4 export function defaultProduct() { 14 export function defaultProduct() {
5 return { 15 return {
6 brand_name: '', 16 brand_name: '',
@@ -51,13 +61,7 @@ export function defaultState() { @@ -51,13 +61,7 @@ export function defaultState() {
51 * storageId: 库存id 61 * storageId: 库存id
52 * size: 尺寸信息 62 * size: 尺寸信息
53 */ 63 */
54 - selectedProductInfo: {  
55 - productId: null,  
56 - product: {},  
57 - sizeId: null,  
58 - storageId: null,  
59 - size: {},  
60 - }, 64 + selectedProductInfo: defaultSelectedSize(),
61 }; 65 };
62 } 66 }
63 67
1 import * as Types from './types'; 1 import * as Types from './types';
2 import { find } from 'lodash'; 2 import { find } from 'lodash';
3 3
4 -import { defaultProduct } from './index'; 4 +import { defaultProduct, defaultSelectedSize } from './index';
5 5
6 function ensureProduct(state, productId) { 6 function ensureProduct(state, productId) {
7 if (state.products[productId] === undefined) { 7 if (state.products[productId] === undefined) {
@@ -55,4 +55,7 @@ export default { @@ -55,4 +55,7 @@ export default {
55 } 55 }
56 state.selectedProductInfo.size = sizeInfo; 56 state.selectedProductInfo.size = sizeInfo;
57 }, 57 },
  58 + [Types.RESET_SELECTED_PRODUCT_SIZE](state) {
  59 + Object.assign(state.selectedProductInfo, defaultSelectedSize());
  60 + },
58 }; 61 };
@@ -2,4 +2,5 @@ export const UPDATE_PRODUCT_DETAIL = 'UPDATE_PRODUCT_DETAIL'; @@ -2,4 +2,5 @@ export const UPDATE_PRODUCT_DETAIL = 'UPDATE_PRODUCT_DETAIL';
2 export const ENSURE_PRODUCT_DETAIL = 'ENSURE_PRODUCT_DETAIL'; 2 export const ENSURE_PRODUCT_DETAIL = 'ENSURE_PRODUCT_DETAIL';
3 export const UPDATE_PRODUCT_FAV = 'UPDATE_PRODUCT_FAV'; 3 export const UPDATE_PRODUCT_FAV = 'UPDATE_PRODUCT_FAV';
4 export const UPDATE_SELECTED_PRODUCT_SIZE = 'UPDATE_SELECTED_PRODUCT_SIZE'; 4 export const UPDATE_SELECTED_PRODUCT_SIZE = 'UPDATE_SELECTED_PRODUCT_SIZE';
  5 +export const RESET_SELECTED_PRODUCT_SIZE = 'RESET_SELECTED_PRODUCT_SIZE';
5 export const UPDATE_PRODUCT_TOP3 = 'UPDATE_PRODUCT_TOP3'; 6 export const UPDATE_PRODUCT_TOP3 = 'UPDATE_PRODUCT_TOP3';
  1 +/* eslint-disable lines-around-comment */
  2 +/* eslint-disable spaced-comment */
1 3
2 // 查询订单数量 4 // 查询订单数量
3 const ORDER_COUNT = 'ufo.order.getAllCnt'; 5 const ORDER_COUNT = 'ufo.order.getAllCnt';
@@ -21,7 +23,6 @@ const SELLER_ASK_PRE_COMPUTE = 'ufo.seller.bid.compute'; @@ -21,7 +23,6 @@ const SELLER_ASK_PRE_COMPUTE = 'ufo.seller.bid.compute';
21 //变现 23 //变现
22 const SELLER_ASK_PUBLISH = 'ufo.seller.bid.publish'; 24 const SELLER_ASK_PUBLISH = 'ufo.seller.bid.publish';
23 25
24 -  
25 module.exports = { 26 module.exports = {
26 ORDER_COUNT, 27 ORDER_COUNT,
27 BUYER_ASK_CONFIG, 28 BUYER_ASK_CONFIG,
@@ -13,7 +13,7 @@ module.exports = { @@ -13,7 +13,7 @@ module.exports = {
13 auth: true, 13 auth: true,
14 path: 'shopping/bid', 14 path: 'shopping/bid',
15 api: API.BUYER_ASK_CONFIG, 15 api: API.BUYER_ASK_CONFIG,
16 - params: {} 16 + params: {},
17 }, 17 },
18 '/api/order/buyeraskcompute': { 18 '/api/order/buyeraskcompute': {
19 ufo: true, 19 ufo: true,
@@ -21,9 +21,9 @@ module.exports = { @@ -21,9 +21,9 @@ module.exports = {
21 path: 'shopping/bid', 21 path: 'shopping/bid',
22 api: API.BUYER_ASK_COMPUTE, 22 api: API.BUYER_ASK_COMPUTE,
23 params: { 23 params: {
24 - price: {type: Number, required: true},  
25 - storage_id: {type: Number, required: true},  
26 - } 24 + price: { type: Number, required: true },
  25 + storage_id: { type: Number, required: true },
  26 + },
27 }, 27 },
28 '/api/order/buyeraskprepublish': { 28 '/api/order/buyeraskprepublish': {
29 ufo: true, 29 ufo: true,
@@ -31,10 +31,10 @@ module.exports = { @@ -31,10 +31,10 @@ module.exports = {
31 path: 'shopping/bid', 31 path: 'shopping/bid',
32 api: API.BUYER_ASK_TIPS, 32 api: API.BUYER_ASK_TIPS,
33 params: { 33 params: {
34 - price: {type: Number, required: true},  
35 - storage_id: {type: Number, required: true},  
36 - address_id: {type: String, required: true},  
37 - } 34 + price: { type: Number, required: true },
  35 + storage_id: { type: Number, required: true },
  36 + address_id: { type: String, required: true },
  37 + },
38 }, 38 },
39 39
40 '/api/order/buyeraskpublish': { 40 '/api/order/buyeraskpublish': {
@@ -43,11 +43,11 @@ module.exports = { @@ -43,11 +43,11 @@ module.exports = {
43 path: 'shopping/bid', 43 path: 'shopping/bid',
44 api: API.BUYER_ASK_PUBLISH, 44 api: API.BUYER_ASK_PUBLISH,
45 params: { 45 params: {
46 - price: {type: Number, required: true},  
47 - storage_id: {type: Number, required: true},  
48 - address_id: {type: String, required: true},  
49 - time_limit_id: {type: Number, required: true}, // 有效期  
50 - } 46 + price: { type: Number, required: true },
  47 + storage_id: { type: Number, required: true },
  48 + address_id: { type: String, required: true },
  49 + time_limit_id: { type: Number, required: true }, // 有效期
  50 + },
51 }, 51 },
52 52
53 '/api/order/buyerask/computechangeprice': { 53 '/api/order/buyerask/computechangeprice': {
@@ -56,9 +56,9 @@ module.exports = { @@ -56,9 +56,9 @@ module.exports = {
56 path: 'shopping/bid', 56 path: 'shopping/bid',
57 api: API.BUYER_ASK_COMPUTE_CHANGE_PRICE, 57 api: API.BUYER_ASK_COMPUTE_CHANGE_PRICE,
58 params: { 58 params: {
59 - price: {type: Number, required: true},  
60 - orderCode: {type: String, required: true},  
61 - } 59 + price: { type: Number, required: true },
  60 + orderCode: { type: String, required: true },
  61 + },
62 }, 62 },
63 '/api/order/buyerask/prechangeprice': { 63 '/api/order/buyerask/prechangeprice': {
64 ufo: true, 64 ufo: true,
@@ -66,9 +66,9 @@ module.exports = { @@ -66,9 +66,9 @@ module.exports = {
66 path: 'shopping/bid', 66 path: 'shopping/bid',
67 api: API.BUYER_ASK_PRE_CHANGE_PRICE, 67 api: API.BUYER_ASK_PRE_CHANGE_PRICE,
68 params: { 68 params: {
69 - price: {type: Number, required: true},  
70 - orderCode: {type: String, required: true},  
71 - } 69 + price: { type: Number, required: true },
  70 + orderCode: { type: String, required: true },
  71 + },
72 }, 72 },
73 73
74 '/api/order/buyerask/changeprice': { 74 '/api/order/buyerask/changeprice': {
@@ -77,9 +77,8 @@ module.exports = { @@ -77,9 +77,8 @@ module.exports = {
77 path: 'shopping/bid', 77 path: 'shopping/bid',
78 api: API.BUYER_ASK_CHANGE_PRICE, 78 api: API.BUYER_ASK_CHANGE_PRICE,
79 params: { 79 params: {
80 - price: {type: Number, required: true},  
81 - orderCode: {type: String, required: true},  
82 - }  
83 - }  
84 - 80 + price: { type: Number, required: true },
  81 + orderCode: { type: String, required: true },
  82 + },
  83 + },
85 }; 84 };
@@ -226,7 +226,6 @@ module.exports = { @@ -226,7 +226,6 @@ module.exports = {
226 auth: true, 226 auth: true,
227 ufo: true, 227 ufo: true,
228 api: 'ufo.sellerOrder.computePublishPrd', 228 api: 'ufo.sellerOrder.computePublishPrd',
229 -  
230 }, 229 },
231 230
232 '/api/order/ordercount': { 231 '/api/order/ordercount': {
@@ -235,7 +234,7 @@ module.exports = { @@ -235,7 +234,7 @@ module.exports = {
235 api: API.ORDER_COUNT, 234 api: API.ORDER_COUNT,
236 params: { 235 params: {
237 tabType: { type: String, require: true }, // 订单来源 236 tabType: { type: String, require: true }, // 订单来源
238 - } 237 + },
239 }, 238 },
240 239
241 // 判断用户状态 240 // 判断用户状态
@@ -310,7 +309,7 @@ module.exports = { @@ -310,7 +309,7 @@ module.exports = {
310 auth: true, 309 auth: true,
311 path: 'payment', 310 path: 'payment',
312 api: 'ufo.order.pay', 311 api: 'ufo.order.pay',
313 - params: {} 312 + params: {},
314 }, 313 },
315 314
316 // 定单商品详情 315 // 定单商品详情
@@ -318,14 +317,14 @@ module.exports = { @@ -318,14 +317,14 @@ module.exports = {
318 ufo: true, 317 ufo: true,
319 auth: true, 318 auth: true,
320 api: 'ufo.order.goodsDetail', 319 api: 'ufo.order.goodsDetail',
321 - params: {} 320 + params: {},
322 }, 321 },
323 322
324 '/api/order/status': { 323 '/api/order/status': {
325 ufo: true, 324 ufo: true,
326 auth: true, 325 auth: true,
327 api: 'ufo.order.payDetail', 326 api: 'ufo.order.payDetail',
328 - params: {} 327 + params: {},
329 }, 328 },
330 329
331 // 订单物流信息 330 // 订单物流信息
@@ -372,22 +371,24 @@ module.exports = { @@ -372,22 +371,24 @@ module.exports = {
372 depotNum: { type: Number, require: true }, // 鉴定中心id 371 depotNum: { type: Number, require: true }, // 鉴定中心id
373 }, 372 },
374 }, 373 },
375 - //瑕疵接受 374 +
  375 + // 瑕疵接受
376 '/api/order/flawaccept': { 376 '/api/order/flawaccept': {
377 ufo: true, 377 ufo: true,
378 auth: true, 378 auth: true,
379 api: 'ufo.buyer.miniFaultAccept', 379 api: 'ufo.buyer.miniFaultAccept',
380 params: { 380 params: {
381 orderCode: { type: String, require: true }, // 订单编号 381 orderCode: { type: String, require: true }, // 订单编号
382 - } 382 + },
383 }, 383 },
384 - //瑕疵拒绝 384 +
  385 + // 瑕疵拒绝
385 '/api/order/flawreject': { 386 '/api/order/flawreject': {
386 ufo: true, 387 ufo: true,
387 auth: true, 388 auth: true,
388 api: 'ufo.buyer.miniFaultReject', 389 api: 'ufo.buyer.miniFaultReject',
389 params: { 390 params: {
390 orderCode: { type: String, require: true }, // 订单编号 391 orderCode: { type: String, require: true }, // 订单编号
391 - }  
392 - } 392 + },
  393 + },
393 }; 394 };
1 { 1 {
2 "name": "xianyu-ufo-app-web", 2 "name": "xianyu-ufo-app-web",
3 - "version": "0.0.2-beta-19", 3 + "version": "0.0.2-beta-20",
4 "private": true, 4 "private": true,
5 "description": "Xianyu Project With Express", 5 "description": "Xianyu Project With Express",
6 "repository": { 6 "repository": {
@@ -85,7 +85,8 @@ @@ -85,7 +85,8 @@
85 "yoho-node-lib": "=0.6.41", 85 "yoho-node-lib": "=0.6.41",
86 "yoho-qs": "^1.0.1", 86 "yoho-qs": "^1.0.1",
87 "yoho-store": "^1.3.20", 87 "yoho-store": "^1.3.20",
88 - "yoho-zookeeper": "^1.0.11" 88 + "yoho-zookeeper": "^1.0.11",
  89 + "video.js": "^7.5.5"
89 }, 90 },
90 "devDependencies": { 91 "devDependencies": {
91 "@babel/core": "^7.2.0", 92 "@babel/core": "^7.2.0",