Commit 6cba5813014536e20ad36b59e87802a40b2c29b6

Authored by BigBoss
Exists in master

修改冲突

src/components/CommodityCard/CommodityCard.vue
... ... @@ -77,7 +77,7 @@ image {
77 77 }
78 78 .name {
79 79 width: 92%;
80   - height: 54rpx;
  80 + height: 56rpx;
81 81 padding: 5px 4%;
82 82 display: -webkit-box;
83 83 -webkit-box-orient: vertical;
... ...
src/components/HMFilterDropdown/HMFilterDropdown.vue
... ... @@ -12,7 +12,7 @@
12 12 <view
13 13 class="first-menu"
14 14 :class="{'on':showPage==index || on[index] === 1}"
15   - @tap="togglePage(index)"
  15 + @tap="togglePage(index, false)"
16 16 v-if="!item.isNoPull"
17 17 >
18 18 <text class="name">{{item.name}}</text>
... ... @@ -372,14 +372,14 @@ export default {
372 372 this.$forceUpdate()
373 373 },
374 374 // 菜单开关
375   - togglePage (index) {
  375 + togglePage (index, isRequest = true) {
376 376 if (index === this.showPage) {
377   - this.hidePageLayer(true)
  377 + this.hidePageLayer(true, isRequest)
378 378 this.hideMask()
379 379 this.showPage = -1
380 380 } else {
381 381 if (this.showPage > -1) {
382   - this.hidePageLayer(false)
  382 + this.hidePageLayer(false, isRequest)
383 383 }
384 384 this.showPageLayer(index)
385 385 this.showMask()
... ... @@ -416,14 +416,17 @@ export default {
416 416 })
417 417 },
418 418 // hide菜单页
419   - hidePageLayer (isAnimation) {
  419 + hidePageLayer (isAnimation,isRequset = true) {
420 420 this.triangleDeg[this.showPage] = 0
421 421 const tmpIndex = this.showPage
422 422 if (isAnimation) {
423 423 setTimeout(() => {
424 424 this.pageState.splice(tmpIndex, 1, false)
425   - }, 200)
426   - this.confirm()
  425 + }, 200)
  426 + // debugger
  427 + if(isRequset){
  428 + this.confirm()
  429 + }
427 430 } else {
428 431 this.pageState.splice(tmpIndex, 1, false)
429 432 }
... ... @@ -812,20 +815,21 @@ export default {
812 815 }
813 816 .labels {
814 817 flex-direction: row;
815   - flex-wrap: wrap;
  818 + flex-wrap: wrap;
  819 + justify-content: space-between;
816 820 .on {
817 821 border-color: #ff6b4a;
818 822 background-color: #ff6b4a;
819 823 color: #fff;
820 824 }
821 825 > view {
822   - width: 148rpx;
  826 + width: 220rpx;
823 827 height: 30px;
824 828 border: solid 1rpx #adadad;
825 829 border-radius: 2px;
826   - margin-right: 15px;
  830 + margin-right: 2px;
827 831 margin-top: 8px;
828   - padding: 0 16rpx;
  832 + padding: 0 10rpx;
829 833 box-sizing: border-box;
830 834 font-size: 12px;
831 835 flex-direction: row;
... ...
src/components/sl-filter/filter-view.vue
... ... @@ -0,0 +1,475 @@
  1 +<template>
  2 +
  3 + <view>
  4 + <view style="padding: 0px 0px;">
  5 + <view class="filter-content" v-for="(item, index) in menuList" :key="index" v-if="menuIndex == index">
  6 + <view v-if="item.isSort">
  7 + <view class="filter-content-list">
  8 + <view v-for="(detailItem,idx) in selectDetailList" :key="idx" :class="detailItem.isSelected?'filter-content-list-item-active':'filter-content-list-item-default'"
  9 + :style="{'color': detailItem.isSelected?themeColor:'#666666'}" @tap="sortTap(idx,selectDetailList,item.key)">
  10 + <text>{{detailItem.title}}</text>
  11 + </view>
  12 + </view>
  13 + </view>
  14 + <view v-else>
  15 + <view class="filter-content-title" v-if="item.detailTitle && item.detailTitle.length">
  16 + <text>{{item.detailTitle}}</text>
  17 + </view>
  18 + <view class="filter-content-detail">
  19 + <text v-for="(detailItem,idx) in selectDetailList" :key="idx" class='filter-content-detail-item-default' :style="{'background-color':detailItem.isSelected?themeColor:'#FFFFFF','color':detailItem.isSelected?'#FFFFFF':'#666666'}"
  20 + @tap="itemTap(idx,selectDetailList,item.isMutiple,item.key)">
  21 + {{detailItem.title}}
  22 + </text>
  23 + </view>
  24 + <view class="filter-content-footer">
  25 + <view class="filter-content-footer-item" style="color: #777777; background-color: #FFFFFF;" @tap="resetClick(selectDetailList,item.key)">
  26 + <text>重置</text>
  27 + </view>
  28 + <view class="filter-content-footer-item" :style="{'color': '#FFFFFF', 'background-color': themeColor}" @tap="sureClick">
  29 + <text>确定</text>
  30 + </view>
  31 + </view>
  32 + </view>
  33 + </view>
  34 + </view>
  35 + </view>
  36 +
  37 +</template>
  38 +
  39 +<script>
  40 + export default {
  41 + data() {
  42 + return {
  43 + selectArr: [],
  44 + result: {},
  45 + menuIndex: 0,
  46 + selectDetailList: [],
  47 + independenceObj: {},
  48 + selectedKey: '',
  49 + cacheSelectedObj: {},
  50 + defaultSelectedTitleObj: {}
  51 + };
  52 + },
  53 + props: {
  54 + themeColor: {
  55 + type: String,
  56 + default () {
  57 + return '#D1372C'
  58 + }
  59 + },
  60 + menuList: {
  61 + type: Array,
  62 + default () {
  63 + return []
  64 + }
  65 + },
  66 + independence: {
  67 + type: Boolean,
  68 + default: false
  69 + }
  70 + },
  71 + computed: {
  72 + selectedTitleObj() {
  73 + let obj = {}
  74 + for (let i = 0; i < this.menuList.length; i++) {
  75 + let item = this.menuList[i];
  76 + obj[item.key] = item.title;
  77 + }
  78 + return obj;
  79 + },
  80 + defaultSelectedObj() { // 保存初始状态
  81 + return this.getSelectedObj()
  82 + },
  83 + selectedObj: {
  84 + get() {
  85 + return this.getSelectedObj()
  86 + },
  87 + set(newObj) {
  88 + return newObj;
  89 + }
  90 +
  91 + }
  92 + },
  93 + methods: {
  94 + getSelectedObj() {
  95 + let obj = {}
  96 + for (let i = 0; i < this.menuList.length; i++) {
  97 + let item = this.menuList[i];
  98 + if (!this.independence && item.defaultSelectedIndex != null && item.defaultSelectedIndex.toString().length > 0) { // 处理并列菜单默认值
  99 +
  100 + if (item.isMutiple) {
  101 + obj[item.key] = [];
  102 + item.detailList[0].isSelected = false;
  103 + if (!Array.isArray(item.defaultSelectedIndex)) { // 如果默认值不是数组
  104 + item.defaultSelectedIndex = [item.defaultSelectedIndex];
  105 + }
  106 + for (let j = 0; j < item.defaultSelectedIndex.length; j++) { // 将默认选中的值放入selectedObj
  107 + item.detailList[item.defaultSelectedIndex[j]].isSelected = true;
  108 + obj[item.key].push(item.detailList[item.defaultSelectedIndex[j]].value)
  109 + }
  110 +
  111 + } else {
  112 + obj[item.key] = item.detailList[item.defaultSelectedIndex].value;
  113 + this.selectedTitleObj[item.key] = item.detailList[item.defaultSelectedIndex].title;
  114 + this.defaultSelectedTitleObj[item.key] = item.detailList[item.defaultSelectedIndex].title;
  115 + item.detailList[0].isSelected = false;
  116 + item.detailList[item.defaultSelectedIndex].isSelected = true;
  117 + }
  118 + } else {
  119 + if (item.isMutiple) {
  120 + obj[item.key] = [];
  121 + } else {
  122 + obj[item.key] = '';
  123 + }
  124 + }
  125 + }
  126 + this.result = obj;
  127 + return obj;
  128 + },
  129 + // 重置所有选项,包括默认选项,并更新result
  130 + resetAllSelect(callback) {
  131 + let titles = [];
  132 + for (let i = 0; i < this.menuList.length; i++) {
  133 + this.resetSelected(this.menuList[i].detailList,this.menuList[i].key);
  134 + titles[this.menuList[i].key] = this.menuList[i].title;
  135 + }
  136 + let obj = {
  137 + 'result': this.result,
  138 + 'titles': titles,
  139 + 'isReset': true
  140 + }
  141 + this.$emit("confirm", obj);
  142 + callback(this.result);
  143 + },
  144 + // 重置选项为设置的默认值,并更新result
  145 + resetSelectToDefault(callback) {
  146 + for (let i = 0; i < this.menuList.length; i++) {
  147 + this.selectDetailList = this.menuList[i].detailList;
  148 +
  149 + if (this.menuList[i].defaultSelectedIndex) {
  150 + if (Array.isArray(this.menuList[i].defaultSelectedIndex)) { // 把所有默认的为false的点为true
  151 + for (let j = 0; j < this.menuList[i].defaultSelectedIndex.length; j++) {
  152 + if (this.selectDetailList[this.menuList[i].defaultSelectedIndex[j]].isSelected == false) {
  153 + this.itemTap(this.menuList[i].defaultSelectedIndex[j], this.selectDetailList, this.menuList[i].isMutiple, this
  154 + .menuList[i].key)
  155 + }
  156 + }
  157 + } else {
  158 + this.itemTap(this.menuList[i].defaultSelectedIndex, this.selectDetailList, this.menuList[i].isMutiple, this.menuList[
  159 + i].key)
  160 + }
  161 +
  162 + // 获取非默认项的下标
  163 + let unDefaultSelectedIndexArr = this.getUnDefaultSelectedIndex(this.menuList[i])
  164 + // 把所有不是默认的为true的点为false
  165 + for (let j = 0; j < unDefaultSelectedIndexArr.length; j++) {
  166 + if (this.selectDetailList[unDefaultSelectedIndexArr[j]].isSelected == true) {
  167 + this.itemTap(unDefaultSelectedIndexArr[j], this.selectDetailList, this.menuList[i].isMutiple, this
  168 + .menuList[i].key)
  169 + }
  170 + }
  171 + }
  172 +
  173 +
  174 + }
  175 +
  176 + this.selectedObj = this.defaultSelectedObj;
  177 + this.result = this.defaultSelectedObj;
  178 + let obj = {
  179 + 'result': this.result,
  180 + 'titles': this.defaultSelectedTitleObj,
  181 + 'isReset': true
  182 + }
  183 + this.$emit("confirm", obj);
  184 + callback(this.result)
  185 + },
  186 + getUnDefaultSelectedIndex(menuListItem) { // 获取非默认项
  187 + let tempDefault = menuListItem.defaultSelectedIndex;
  188 + if (!Array.isArray(tempDefault)) {
  189 + tempDefault = [tempDefault];
  190 + }
  191 + // 获取所有项的下标 组成新的数组
  192 + let all = [];
  193 + for (let i = 0; i < menuListItem.detailList.length; i++) {
  194 + all.push(i)
  195 + }
  196 + // 将默认选中的数组与所有项的数组的不同值合并为一个新数组
  197 + var unDefaultSelectedIndex = tempDefault.filter(function(v) {
  198 + return !(all.indexOf(v) > -1)
  199 + }).concat(all.filter(function(v) {
  200 + return !(tempDefault.indexOf(v) > -1)
  201 + }));
  202 + return unDefaultSelectedIndex;
  203 + },
  204 + resetMenuList(val) {
  205 + this.menuList = val;
  206 + this.$emit('update:menuList', val)
  207 + },
  208 + menuTabClick(index) {
  209 + this.menuIndex = index;
  210 + this.selectDetailList = this.menuList[index].detailList;
  211 + this.selectedKey = this.menuList[index].key;
  212 + // 如果是独立菜单
  213 + if (this.independence && !this.menuList[index].isSort) {
  214 + if (JSON.stringify(this.independenceObj) == '{}') {
  215 + this.initIndependenceObj(index);
  216 + } else {
  217 + for (let key in this.independenceObj) {
  218 + if (key != this.selectedKey) {
  219 + this.initIndependenceObj(index);
  220 + this.resetSelected(this.menuList[index].detailList, this.selectedKey);
  221 + }
  222 + }
  223 + }
  224 +
  225 + }
  226 + if (this.independence && this.menuList[index].isSort) {
  227 +
  228 + this.independenceObj = {};
  229 +
  230 +
  231 + }
  232 + if (this.independence) {
  233 + let idx = this.menuList[index].defaultSelectedIndex;
  234 + if (idx != null && idx.toString().length > 0) { // 处理独立菜单默认值
  235 + if (this.menuList[index].isMutiple) {
  236 + for (let i = 0; i < idx.length; i++) {
  237 + if (this.menuList[index].detailList[idx[i]].isSelected == false) {
  238 + this.itemTap(idx[i], this.menuList[index].detailList, true, this.selectedKey);
  239 + }
  240 +
  241 + }
  242 + } else {
  243 + if (this.menuList[index].detailList[idx].isSelected == false) {
  244 +
  245 + this.itemTap(idx, this.menuList[index].detailList, false, this.selectedKey);
  246 +
  247 + }
  248 + }
  249 +
  250 + }
  251 + }
  252 +
  253 +
  254 + // #ifdef H5
  255 + this.selectedObj = this.selectedObj;
  256 + this.$forceUpdate();
  257 + // #endif
  258 + },
  259 + initIndependenceObj(index) {
  260 + this.independenceObj = {};
  261 + if (this.menuList[index].isMutiple) {
  262 + this.independenceObj[this.selectedKey] = [];
  263 + } else {
  264 + this.independenceObj[this.selectedKey] = '';
  265 + }
  266 + },
  267 + itemTap(index, list, isMutiple, key) {
  268 + if (isMutiple == true) {
  269 + list[index].isSelected = !list[index].isSelected;
  270 + if (index == 0) {
  271 + this.resetSelected(list, key)
  272 + if (!this.independence) {
  273 + this.selectedTitleObj[key] = list[index].title;
  274 + }
  275 + } else {
  276 + list[0].isSelected = false
  277 + if (list[index].isSelected) {
  278 + if (this.independence) {
  279 + this.independenceObj[this.selectedKey].push(list[index].value);
  280 + } else {
  281 + this.selectedObj[key].push(list[index].value);
  282 + }
  283 + } else {
  284 + list[index].isSelected = false;
  285 + if (this.independence) {
  286 + var idx = this.independenceObj[this.selectedKey].indexOf(list[index].value);
  287 + this.independenceObj[this.selectedKey].splice(idx, 1);
  288 + } else {
  289 + var idx = this.selectedObj[key].indexOf(list[index].value);
  290 + this.selectedObj[key].splice(idx, 1);
  291 + }
  292 +
  293 + }
  294 + if (this.independence) {
  295 + this.result = this.independenceObj;
  296 + } else {
  297 + this.result = this.selectedObj;
  298 + }
  299 +
  300 + }
  301 + } else {
  302 + if (index == 0) {
  303 + this.resetSelected(list, key)
  304 + if (!this.independence) {
  305 + this.selectedTitleObj[key] = list[index].title;
  306 + }
  307 + } else {
  308 + list[0].isSelected = false
  309 + if (this.independence) {
  310 + this.independenceObj[this.selectedKey] = list[index].value;
  311 + this.result = this.independenceObj;
  312 + } else {
  313 + this.selectedObj[key] = list[index].value;
  314 + this.result = this.selectedObj;
  315 + this.selectedTitleObj[key] = list[index].title;
  316 + }
  317 +
  318 + for (let i = 0; i < list.length; i++) {
  319 + if (index == i) {
  320 + list[i].isSelected = true
  321 + } else {
  322 + list[i].isSelected = false
  323 + }
  324 + }
  325 + }
  326 + }
  327 + // #ifdef H5
  328 + this.$forceUpdate();
  329 + // #endif
  330 + },
  331 + resetSelected(list, key) {
  332 + if (typeof this.result[key] == 'object') {
  333 + this.result[key] = [];
  334 + this.selectedTitleObj[key] = list[0].title;
  335 + } else {
  336 + this.result[key] = '';
  337 + this.selectedTitleObj[key] = list[0].title;
  338 + }
  339 + for (let i = 0; i < list.length; i++) {
  340 + if (i == 0) {
  341 + list[i].isSelected = true;
  342 + } else {
  343 + list[i].isSelected = false;
  344 + }
  345 + }
  346 + // #ifdef H5
  347 + this.$forceUpdate();
  348 + // #endif
  349 + },
  350 + sortTap(index, list, key) {
  351 + if (this.independence) {
  352 + this.independenceObj[this.selectedKey] = list[index].value;
  353 + this.result = this.independenceObj;
  354 + } else {
  355 + this.selectedObj[key] = list[index].value;
  356 + this.result = this.selectedObj;
  357 + this.selectedTitleObj[key] = list[index].title;
  358 + }
  359 +
  360 + for (let i = 0; i < list.length; i++) {
  361 + if (index == i) {
  362 + list[i].isSelected = true;
  363 + } else {
  364 + list[i].isSelected = false;
  365 + }
  366 + }
  367 + let obj = {
  368 + 'result': this.result,
  369 + 'titles': this.selectedTitleObj,
  370 + 'isReset': false
  371 + }
  372 + this.$emit("confirm", obj);
  373 + },
  374 + sureClick() {
  375 + let obj = {
  376 + 'result': this.result,
  377 + 'titles': this.selectedTitleObj,
  378 + 'isReset': false
  379 + }
  380 + this.$emit("confirm", obj);
  381 + },
  382 + resetClick(list, key) {
  383 + this.resetSelected(list, key)
  384 + }
  385 + }
  386 + }
  387 +</script>
  388 +
  389 +<style>
  390 + .filter-content {
  391 + background-color: #F6F7F8;
  392 + }
  393 +
  394 + .filter-content-title {
  395 + border-bottom: #EEEEEE 1px solid;
  396 + padding: 10px 15px;
  397 + font-size: 13px;
  398 + color: #999999;
  399 + }
  400 +
  401 + .filter-content-detail {
  402 + padding: 5px 15px;
  403 + }
  404 +
  405 + .filter-content-detail-item-active {
  406 + background-color: #D1372C;
  407 + color: #FFFFFF;
  408 + padding: 5px 15px;
  409 + border-radius: 20px;
  410 + margin-right: 10px;
  411 + margin-top: 10px;
  412 + display: inline-block;
  413 + font-size: 14px;
  414 + }
  415 +
  416 + .filter-content-detail-item-default {
  417 + background-color: #FFFFFF;
  418 + color: #666666;
  419 + padding: 5px 15px;
  420 + border-radius: 20px;
  421 + margin-right: 10px;
  422 + margin-top: 10px;
  423 + display: inline-block;
  424 + font-size: 14px;
  425 + }
  426 +
  427 + .filter-content-footer {
  428 + display: flex;
  429 + justify-content: space-between;
  430 + width: 100%;
  431 + height: 45px;
  432 + margin-top: 10px;
  433 + }
  434 +
  435 + .filter-content-footer-item {
  436 + width: 50%;
  437 + display: flex;
  438 + justify-content: center;
  439 + align-items: center;
  440 + font-size: 16px;
  441 + }
  442 +
  443 + .filter-content-list {
  444 +
  445 + padding: 5px 15px;
  446 + }
  447 +
  448 + .filter-content-list-item-default {
  449 + color: #666666;
  450 + width: 100%;
  451 + padding: 10px 0px;
  452 + }
  453 +
  454 + .filter-content-list-item-default text {
  455 + width: 90%;
  456 + font-size: 14px;
  457 + display: inline-block;
  458 + }
  459 +
  460 + .filter-content-list-item-active {
  461 + color: #D1372C;
  462 + width: 100%;
  463 + padding: 10px 0px;
  464 + }
  465 +
  466 + .filter-content-list-item-active text {
  467 + font-size: 14px;
  468 + width: 90%;
  469 + display: inline-block;
  470 + }
  471 +
  472 + .filter-content-list-item-active:after {
  473 + content: '✓';
  474 + }
  475 +</style>
... ...
src/components/sl-filter/iconfont/iconfont.css
... ... @@ -0,0 +1,20 @@
  1 +@font-face {
  2 + font-family: 'sl-font';
  3 + src: url('data:font/truetype;charset=utf-8;base64,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') format('truetype');
  4 +}
  5 +
  6 +.sl-font {
  7 + font-family: "sl-font" !important;
  8 + font-size: 16px;
  9 + font-style: normal;
  10 + -webkit-font-smoothing: antialiased;
  11 + -moz-osx-font-smoothing: grayscale;
  12 +}
  13 +
  14 +.sl-down:before {
  15 + content: "\e61a";
  16 +}
  17 +
  18 +.sl-up:before {
  19 + content: "\e61c";
  20 +}
... ...
src/components/sl-filter/popup-layer.vue
... ... @@ -0,0 +1,122 @@
  1 +<template>
  2 + <scroll-view scroll-y v-show="ifshow" @tap="ableClose" @touchmove.stop.prevent class="popup-layer">
  3 + <view ref="popRef" class="popup-content" @tap.stop="stopEvent" :style="_location">
  4 + <slot></slot>
  5 + </view>
  6 + </scroll-view>
  7 +</template>
  8 +
  9 +<script>
  10 + export default {
  11 + name: 'popup-layer',
  12 + props: {
  13 + direction: {
  14 + type: String,
  15 + default: 'top', // 方向 top,bottom,left,right
  16 + },
  17 + autoClose: {
  18 + type: Boolean,
  19 + default: true,
  20 + },
  21 + isTransNav: {
  22 + type: Boolean,
  23 + default: false
  24 + },
  25 + navHeight: {
  26 + type: Number,
  27 + default: 0
  28 + }
  29 + },
  30 + data() {
  31 + return {
  32 + ifshow: false, // 是否展示,
  33 + translateValue: -100, // 位移距离
  34 + timer: null,
  35 + iftoggle: false,
  36 + };
  37 + },
  38 + computed: {
  39 + _translate() {
  40 + if (this.isTransNav) {
  41 + const transformObj = {
  42 + 'top': `transform:translateY(${-this.translateValue}%)`,
  43 + 'bottom': `transform:translateY(calc(${this.translateValue}% + ${this.navHeight}px))`,
  44 + 'left': `transform:translateX(${-this.translateValue}%)`,
  45 + 'right': `transform:translateX(${this.translateValue}%)`
  46 + };
  47 + return transformObj[this.direction]
  48 + } else {
  49 + const transformObj = {
  50 + 'top': `transform:translateY(${-this.translateValue}%)`,
  51 + 'bottom': `transform:translateY(${this.translateValue}%)`,
  52 + 'left': `transform:translateX(${-this.translateValue}%)`,
  53 + 'right': `transform:translateX(${this.translateValue}%)`
  54 + };
  55 + return transformObj[this.direction]
  56 + }
  57 +
  58 + },
  59 + _location() {
  60 + const positionValue = {
  61 + 'top': 'bottom:0px;width:100%;',
  62 + 'bottom': 'top:0px;width:100%;',
  63 + 'left': 'right:0px;height:100%;',
  64 + 'right': 'left:0px;height:100%;',
  65 + };
  66 + return positionValue[this.direction] + this._translate;
  67 + }
  68 + },
  69 + methods: {
  70 + show() {
  71 + let _this = this;
  72 + this.ifshow = true;
  73 + let _open = setTimeout(() => {
  74 + this.translateValue = 0;
  75 + _open = null;
  76 + }, 100)
  77 + let _toggle = setTimeout(() => {
  78 + this.iftoggle = true;
  79 + _toggle = null;
  80 + }, 300);
  81 + },
  82 + close() {
  83 + if (this.timer !== null || !this.iftoggle) {
  84 + return;
  85 + }
  86 + this.translateValue = -100 - this.navHeight;
  87 +
  88 + this.timer = setTimeout(() => {
  89 + this.ifshow = false;
  90 + this.timer = null;
  91 + this.iftoggle = false;
  92 + }, 300);
  93 + this.$emit("close")
  94 + },
  95 + ableClose() {
  96 + if (this.autoClose) {
  97 + this.close();
  98 + }
  99 + },
  100 + stopEvent(event) {},
  101 + }
  102 + }
  103 +</script>
  104 +
  105 +<style>
  106 + .popup-layer {
  107 + position: absolute;
  108 + z-index: 999999;
  109 + background: rgba(0, 0, 0, .3);
  110 + height: calc(100% - 50px);
  111 + width: 100%;
  112 + left: 0px;
  113 + overflow: hidden;
  114 + }
  115 +
  116 + .popup-content {
  117 + position: absolute;
  118 + z-index: 1000000;
  119 + background: #FFFFFF;
  120 + transition: all .3s ease;
  121 + }
  122 +</style>
... ...
src/components/sl-filter/sl-filter.vue
... ... @@ -0,0 +1,317 @@
  1 +<template>
  2 + <view class="content">
  3 + <view :style="{height: tabHeight + 1 +'px'}">
  4 + <view :class="topFixed?'select-tab-fixed-top':'select-tab'" :style="{height: tabHeight+'px'}">
  5 + <view class="select-tab-item" :style="{width: itemWidth}" v-for="(item,index) in titleList" :key="index" @tap="showMenuClick(index)">
  6 + <text :style="{color:color}">{{item.title}}</text>
  7 + <text class="arrows sl-font" :class="statusList[index].isActive?up:down"></text>
  8 + </view>
  9 + </view>
  10 + </view>
  11 + <popup-layer ref="popupRef" :direction="'bottom'" @close="close" :isTransNav="isTransNav" :navHeight="navHeight"
  12 + :tabHeight="tabHeight">
  13 + <sl-filter-view :ref="'slFilterView'" :independence="independence" :themeColor="themeColor" :menuList.sync="menuListTemp"
  14 + ref="slFilterView" @confirm="filterResult"></sl-filter-view>
  15 + </popup-layer>
  16 + </view>
  17 +
  18 +</template>
  19 +
  20 +<script>
  21 + import popupLayer from '@/components/sl-filter/popup-layer.vue';
  22 + import slFilterView from '@/components/sl-filter/filter-view.vue';
  23 + export default {
  24 + components: {
  25 + popupLayer,
  26 + slFilterView
  27 + },
  28 + props: {
  29 + menuList: {
  30 + type: Array,
  31 + default () {
  32 + return []
  33 + }
  34 + },
  35 + themeColor: {
  36 + type: String,
  37 + default () {
  38 + return '#000000'
  39 + }
  40 + },
  41 + color: {
  42 + type: String,
  43 + default () {
  44 + return '#666666'
  45 + }
  46 + },
  47 + independence: {
  48 + type: Boolean,
  49 + default: false
  50 + },
  51 + isTransNav: {
  52 + type: Boolean,
  53 + default: false
  54 + },
  55 + navHeight: {
  56 + type: Number,
  57 + default: 0
  58 + },
  59 + topFixed: {
  60 + type: Boolean,
  61 + default: false
  62 + }
  63 + },
  64 +
  65 + computed: {
  66 + itemWidth() {
  67 + return 'calc(100%/2)'
  68 + },
  69 + menuListTemp: {
  70 + get() {
  71 + return this.getMenuListTemp();
  72 + },
  73 + set(newObj) {
  74 + return newObj;
  75 + }
  76 + }
  77 + },
  78 + // #ifndef H5
  79 + onReady: function() {
  80 + let arr = [];
  81 + let titleArr = [];
  82 + let r = {};
  83 + for (let i = 0; i < this.menuList.length; i++) {
  84 + arr.push({
  85 + 'isActive': false
  86 + });
  87 + // titleArr.push({
  88 + // 'title': this.menuList[i].title,
  89 + // 'key': this.menuList[i].key
  90 + // })
  91 +
  92 + r[this.menuList[i].key] = this.menuList[i].title;
  93 +
  94 + if (this.menuList[i].reflexTitle && this.menuList[i].defaultSelectedIndex > -1) {
  95 + titleArr.push({
  96 + 'title': this.menuList[i].detailList[this.menuList[i].defaultSelectedIndex].title,
  97 + 'key': this.menuList[i].key
  98 + })
  99 + } else {
  100 + titleArr.push({
  101 + 'title': this.menuList[i].title,
  102 + 'key': this.menuList[i].key
  103 + })
  104 + }
  105 +
  106 + }
  107 + this.statusList = arr;
  108 + this.titleList = titleArr;
  109 + this.tempTitleObj = r;
  110 + },
  111 + // #endif
  112 +
  113 + // #ifdef H5
  114 + created: function() {
  115 + let arr = [];
  116 + let titleArr = [];
  117 + let r = {};
  118 + for (let i = 0; i < this.menuList.length; i++) {
  119 + arr.push({
  120 + 'isActive': false
  121 + });
  122 + // titleArr.push({
  123 + // 'title': this.menuList[i].title,
  124 + // 'key': this.menuList[i].key
  125 + // });
  126 + r[this.menuList[i].key] = this.menuList[i].title;
  127 +
  128 + if (this.menuList[i].reflexTitle && this.menuList[i].defaultSelectedIndex > -1) {
  129 + titleArr.push({
  130 + 'title': this.menuList[i].detailList[this.menuList[i].defaultSelectedIndex].title,
  131 + 'key': this.menuList[i].key
  132 + })
  133 + } else {
  134 + titleArr.push({
  135 + 'title': this.menuList[i].title,
  136 + 'key': this.menuList[i].key
  137 + })
  138 + }
  139 +
  140 + }
  141 + this.statusList = arr;
  142 + this.titleList = titleArr;
  143 + this.tempTitleObj = r;
  144 + },
  145 + // #endif
  146 + data() {
  147 + return {
  148 + down: 'sl-down',
  149 + up: 'sl-up',
  150 + tabHeight: 50,
  151 + statusList: [],
  152 + selectedIndex: '',
  153 + titleList: [],
  154 + tempTitleObj: {}
  155 + };
  156 + },
  157 + methods: {
  158 + getMenuListTemp() {
  159 + let arr = this.menuList;
  160 + for (let i = 0; i < arr.length; i++) {
  161 + let item = arr[i];
  162 + for (let j = 0; j < item.detailList.length; j++) {
  163 + let d_item = item.detailList[j];
  164 + if (j == 0) {
  165 + d_item.isSelected = true
  166 + } else {
  167 + d_item.isSelected = false
  168 + }
  169 + }
  170 + }
  171 + return arr;
  172 + },
  173 + // 重置所有选项,包括默认选项,并更新result
  174 + resetAllSelect(callback) {
  175 + this.$refs.slFilterView.resetAllSelect(function(e){
  176 + callback(e);
  177 + });
  178 + },
  179 + // 重置选项为设置的默认值,并更新result
  180 + resetSelectToDefault(callback) {
  181 + this.$refs.slFilterView.resetSelectToDefault(function(e){
  182 + callback(e);
  183 + });
  184 + },
  185 + resetMenuList(val) {
  186 + this.menuList = val;
  187 + this.$emit('update:menuList', val)
  188 + this.$forceUpdate();
  189 + this.$refs.slFilterView.resetMenuList(val)
  190 + },
  191 + showMenuClick(index) {
  192 + this.selectedIndex = index;
  193 + if (this.statusList[index].isActive == true) {
  194 + this.$refs.popupRef.close();
  195 + this.statusList[index].isActive = false
  196 + } else {
  197 + this.menuTabClick(index);
  198 + this.$refs.popupRef.show()
  199 + }
  200 + },
  201 + menuTabClick(index) {
  202 + this.$refs.slFilterView.menuTabClick(index);
  203 + for (let i = 0; i < this.statusList.length; i++) {
  204 + if (index == i) {
  205 + this.statusList[i].isActive = true;
  206 + } else {
  207 + this.statusList[i].isActive = false;
  208 + }
  209 + }
  210 + },
  211 + filterResult(obj) {
  212 + let val = obj.result;
  213 + let titlesObj = obj.titles;
  214 + // 处理选项映射到菜单title
  215 + if (this.independence) {
  216 + if (!this.menuList[this.selectedIndex].isMutiple || this.menuList[this.selectedIndex].isSort) {
  217 + let tempTitle = '';
  218 + for (let i = 0; i < this.menuList[this.selectedIndex].detailList.length; i++) {
  219 + let item = this.menuList[this.selectedIndex].detailList[i];
  220 + if (item.value == val[this.menuList[this.selectedIndex].key]) {
  221 + tempTitle = item.title;
  222 + }
  223 + }
  224 + if (this.menuList[this.selectedIndex].reflexTitle) {
  225 + this.titleList[this.selectedIndex].title = tempTitle;
  226 + }
  227 + }
  228 + } else {
  229 + for (let key in titlesObj) {
  230 + if (!Array.isArray(titlesObj[key])) {
  231 + this.tempTitleObj[key] = titlesObj[key];
  232 + }
  233 +
  234 + }
  235 + for (let key in this.tempTitleObj) {
  236 + for (let i = 0; i < this.titleList.length; i++) {
  237 + if (this.titleList[i].key == key) {
  238 + this.titleList[i].title = this.tempTitleObj[key];
  239 + }
  240 + }
  241 + }
  242 + }
  243 +
  244 + this.$refs.popupRef.close()
  245 + if (obj.isReset) {
  246 +
  247 + } else{
  248 + this.$emit("result", val)
  249 + }
  250 +
  251 +
  252 + },
  253 + close() {
  254 + for (let i = 0; i < this.statusList.length; i++) {
  255 + this.statusList[i].isActive = false;
  256 + }
  257 + }
  258 + }
  259 + }
  260 +</script>
  261 +
  262 +<style lang="scss">
  263 + @import 'iconfont/iconfont.css';
  264 + // .content{
  265 + // flex-shrink: 0;
  266 + // width: 100%;
  267 + // height: 44px;
  268 + // position: fixed;
  269 + // z-index: 997;
  270 + // flex-wrap: nowrap;
  271 + // display: flex;
  272 + // flex-direction: row;
  273 + // // top: var(--window-top);
  274 + // left: 0;
  275 + // view {
  276 + // display: flex;
  277 + // flex-wrap: nowrap;
  278 + // }
  279 + // }
  280 + .select-tab {
  281 + border-bottom: #F7F7F7 1px solid;
  282 + background-color: #FFFFFF;
  283 + display: flex;
  284 + width: 100%;
  285 + }
  286 +
  287 + .select-tab-fixed-top {
  288 + border-bottom: #F7F7F7 1px solid;
  289 + background-color: #FFFFFF;
  290 + display: flex;
  291 + width: 100%;
  292 + position: fixed;
  293 + /* #ifdef H5 */
  294 + top: 44px;
  295 + /* #endif */
  296 + /* #ifndef H5 */
  297 + top: 0;
  298 + /* #endif */
  299 + }
  300 +
  301 + .arrows {
  302 + margin-left: 5px;
  303 + }
  304 +
  305 + .select-tab .select-tab-item,
  306 + .select-tab-fixed-top .select-tab-item {
  307 + display: flex;
  308 + justify-content: center;
  309 + align-items: center;
  310 + }
  311 +
  312 + .select-tab .select-tab-item text,
  313 + .select-tab-fixed-top .select-tab-item text {
  314 + color: #666666;
  315 + font-size: 14px;
  316 + }
  317 +</style>
... ...
... ... @@ -37,6 +37,12 @@
37 37 }
38 38 },
39 39 {
  40 + "path": "pages/details/details",
  41 + "style": {
  42 + "navigationBarTitleText": "产品详情"
  43 + }
  44 + },
  45 + {
40 46 "path": "pages/myOrderPaying/myOrderPaying",
41 47 "style": {
42 48 "navigationBarTitleText": "我的订单"
... ... @@ -192,7 +198,7 @@
192 198 },
193 199 {
194 200 "name": "产品详情",
195   - "path": "pages/frameDetail/frameDetail",
  201 + "path": "pages/details/details",
196 202 "query": ""
197 203 },
198 204 {
... ...
src/pages/details/components/AfterSails.vue
... ... @@ -0,0 +1,104 @@
  1 +<template>
  2 + <!-- 售后保障 -->
  3 + <view class="customerService">
  4 + <view class="serviceItem">
  5 + <view class="title">
  6 + <view style="width: 6rpx;height: 6rpx;border-radius: 3rpx;background-color: #FF6B4A;margin-right: 12rpx;"></view>
  7 + <text class="titleText">卖家服务</text>
  8 + </view>
  9 + <view class="itemContent">平台卖家服务,为您在平台获得最优的购买体验</view>
  10 + </view>
  11 + <view class="serviceItem">
  12 + <view class="title">
  13 + <view style="width: 6rpx;height: 6rpx;border-radius: 3rpx;background-color: #FF6B4A;margin-right: 12rpx;"></view>
  14 + <text class="titleText">平台承诺</text>
  15 + </view>
  16 + <view class="itemContent">平台卖家服务,为您在平台获得最优的购买体验阿斯蒂芬的发射点发射点发生的房贷首付的发护法国会国家和国际会更加和</view>
  17 + </view>
  18 + <view class="serviceItem">
  19 + <view class="title">
  20 + <view style="width: 6rpx;height: 6rpx;border-radius: 3rpx;background-color: #FF6B4A;margin-right: 12rpx;"></view>
  21 + <text class="titleText">正品保证</text>
  22 + </view>
  23 + <view class="itemContent">向您保证所售商品均为正品行货</view>
  24 + </view>
  25 + <view class="serviceItem2">
  26 + <view class="title">
  27 + <text class="titleText">权利申明</text>
  28 + </view>
  29 + <view class="itemContent">任何个人或单位如果同时符合以下两个条件:1. 权利人发现网络用户利用网络服务侵害其合法权益;2. 百度的搜索引擎系统以自动检索方式而链接到第三方网站的内容侵犯了上述权利人的合法权益。请上述个人或单位务必以书面的通讯方式向百度提交权利通知。</view>
  30 + </view>
  31 + <view class="serviceItem2">
  32 + <view class="title">
  33 + <text class="titleText">价格保证</text>
  34 + </view>
  35 + <view class="itemContent">
  36 + <view class="itemContent-child">
  37 + <text class="contentTitle">平台价:</text>
  38 + <text>任何个人或单位如果同时符合以下两个条件:1. 权利人发现网络用户利用网络服务侵害其合法权益;2. 百度的搜索引擎系统以自动检索方式而链接到第三方网站的内容侵犯了上述权利人的合法权益。请上述个人或单位务必以书面的通讯方式向百度提交权利通知</text>
  39 + </view>
  40 + <view class="itemContent-child">
  41 + <text class="contentTitle">划线价:</text>
  42 + <text>任何个人或单位如果同时符合以下两个条件:1. 权利人发现网络用户利用网络服务侵害其合法权益;2. 百度的搜索引擎系统以自动检索方式而链接到第三方网站的内容侵犯了上述权利人的合法权益。请上述个人或单位务必以书面的通讯方式向百度提交权利通知</text>
  43 + </view>
  44 + <view class="itemContent-child">
  45 + <text class="contentTitle">平折扣:</text>
  46 + <text>任何个人或单位如果同时符合以下两个条件:1. 权利人发现网络用户利用网络服务侵害其合法权益;2. 百度的搜索引擎系统以自动检索方式而链接到第三方网站的内容侵犯了上述权利人的合法权益。请上述个人或单位务必以书面的通讯方式向百度提交权利通知</text>
  47 + </view>
  48 + <view class="itemContent-child">
  49 + <text class="contentTitle">异常问题:</text>
  50 + <text>任何个人或单位如果同时符合以下两个条件:1. 权利人发现网络用户利用网络服务侵害其合法权益;2. 百度的搜索引擎系统以自动检索方式而链接到第三方网站的内容侵犯了上述权利人的合法权益。请上述个人或单位务必以书面的通讯方式向百度提交权利通知</text>
  51 + </view>
  52 + </view>
  53 + </view>
  54 + </view>
  55 +</template>
  56 +
  57 +<script>
  58 +export default {
  59 +
  60 +}
  61 +</script>
  62 +
  63 +<style lang="scss">
  64 +.customerService {
  65 + margin-bottom: 90rpx;
  66 + .serviceItem {
  67 + margin-bottom: 32rpx;
  68 + .title {
  69 + display: flex;
  70 + flex-direction: row;
  71 + align-items: center;
  72 + .titleText {
  73 + font-family: PingFangSC-Medium;
  74 + font-size: 14px;
  75 + color: #333333;
  76 + margin-bottom: 12rpx;
  77 + }
  78 + }
  79 + .itemContent {
  80 + font-size: 14px;
  81 + color: #999999;
  82 + margin-left: 18rpx;
  83 + }
  84 + }
  85 + .serviceItem2 {
  86 + margin-left: 18rpx;
  87 + margin-bottom: 32rpx;
  88 + .titleText {
  89 + font-size: 14px;
  90 + color: #ff6b4a;
  91 + }
  92 + .itemContent {
  93 + font-size: 14px;
  94 + color: #999999;
  95 + .itemContent-child {
  96 + margin-bottom: 40rpx;
  97 + .contentTitle {
  98 + border-bottom: 1px solid #ff6b4a;
  99 + }
  100 + }
  101 + }
  102 + }
  103 +}
  104 +</style>
... ...
src/pages/details/details.vue
... ... @@ -0,0 +1,234 @@
  1 +<template>
  2 + <view class="container">
  3 + <view class="basic_info">
  4 + <!-- 轮播图 -->
  5 + <swiper
  6 + class="swiperImage"
  7 + :indicator-dots="true"
  8 + :autoplay="true"
  9 + :interval="4000"
  10 + :duration="500"
  11 + >
  12 + <swiper-item
  13 + v-for="(item, index) in carousel"
  14 + :key="index"
  15 + >
  16 + <image
  17 + :src="item"
  18 + mode="scaleToFill"
  19 + ></image>
  20 + </swiper-item>
  21 + </swiper>
  22 + <!-- 产品价格及购买人数 -->
  23 + <view class="info_pay">
  24 + <view>¥{{goodsInfo.price || '暂无'}}<span
  25 + v-if="goodsInfo.discountPrice"
  26 + class="info_pay_discount"
  27 + >¥{{goodsInfo.discountPrice}}</span></view>
  28 + <span class="info_pay_number">{{goodsInfo.tradeNumber || '暂无'}}人购买过</span>
  29 + </view>
  30 + <!-- 产品名称 -->
  31 + <view class="info_name">
  32 + <text class="info_name_name">{{goodsInfo.name || '暂无'}}</text>
  33 + <view class="info_name_share">
  34 + <image src="/static/img/detail/share-icon.png"></image>
  35 + <text>分享</text>
  36 + </view>
  37 + </view>
  38 + <!-- 产品售后信息 -->
  39 + <view class="info_after">
  40 + <span>支持7天无理由退货</span>
  41 + <span>顺丰发货</span>
  42 + <span>30天质量保证</span>
  43 + </view>
  44 + </view>
  45 + <view class="detail_info">
  46 + <!-- 详细信息菜单 -->
  47 + <view class="screen_bar">
  48 + <view
  49 + v-for="item in screenItems"
  50 + :key="item.current"
  51 + @click="tabChange(item.current)"
  52 + >
  53 + <view
  54 + class="screen_item"
  55 + v-bind:class="{ item_active: item_current === item.current }"
  56 + >{{ item.text || '暂无' }}</view>
  57 + </view>
  58 + </view>
  59 + <!-- 售后保障 -->
  60 + <view
  61 + class="screen_item"
  62 + v-if="item_current === 2"
  63 + >
  64 + <AfterSails />
  65 + </view>
  66 + </view>
  67 + </view>
  68 +</template>
  69 +
  70 +<script>
  71 +import store from '@/store'
  72 +import AfterSails from './components/AfterSails'
  73 +// import BottomSheet from '@/components/BottomSheet.vue'
  74 +
  75 +export default {
  76 + components: {
  77 + AfterSails,
  78 + },
  79 + data () {
  80 + return {
  81 + pid: 7, // 产品ID
  82 + skId: undefined, // skuId
  83 + // 详细信息菜单
  84 + item_current: 0,
  85 + screenItems: [
  86 + { current: 0, text: '商品介绍' },
  87 + { current: 1, text: '规格参数' },
  88 + { current: 2, text: '售后保障' },
  89 + ],
  90 + }
  91 + },
  92 + onLoad({ pid = this.pid, sk_id: skId }) {
  93 + this.pid = pid
  94 + this.skId = skId
  95 +
  96 + // 获取产品详情
  97 + this.getDetails({ pid, skId })
  98 + },
  99 + computed: {
  100 + // 获取轮播图数据
  101 + carousel() {
  102 + return this.$store.state.details.carousel
  103 + },
  104 + // 商品基本信息
  105 + goodsInfo() {
  106 + return this.$store.state.details.goodsInfo
  107 + },
  108 + },
  109 + methods: {
  110 + // 获取产品详情
  111 + getDetails({ pid, skId }) {
  112 + store.dispatch('details/details', {
  113 + pid,
  114 + sk_id: skId,
  115 + })
  116 + },
  117 + // 切换详细信息菜单
  118 + tabChange (e) {
  119 + if (this.current !== e) {
  120 + this.item_current = e
  121 + }
  122 + },
  123 + },
  124 +}
  125 +</script>
  126 +
  127 +<style lang="scss">
  128 +.container {
  129 + background-color: #f8f8f8;
  130 + font-family: "PingFangSC-Regular";
  131 + // 板块样式
  132 + > view {
  133 + background: #ffffff;
  134 + margin-bottom: 10px;
  135 + padding: 8px 20px 8px 20px;
  136 + box-sizing: border-box;
  137 + }
  138 + // 基础信息板块
  139 + .basic_info {
  140 + // 轮播图
  141 + .swiperImage {
  142 + width: 684rpx;
  143 + height: 480rpx;
  144 + image {
  145 + max-width: 100%;
  146 + max-height: 100%;
  147 + border-radius: 16rpx;
  148 + }
  149 + }
  150 + // 产品价格及购买人数
  151 + .info_pay {
  152 + color: #eb5d3b;
  153 + font-size: 18px;
  154 + margin-top: 5px;
  155 + font-family: "PingFangSC-Semibold";
  156 + display: flex;
  157 + justify-content: space-between;
  158 + .info_pay_discount {
  159 + text-decoration: line-through;
  160 + margin-left: 8rpx;
  161 + color: #999;
  162 + font-size: 14px;
  163 + }
  164 + .info_pay_number {
  165 + color: #999;
  166 + font-size: 14px;
  167 + }
  168 + }
  169 + // 产品名称
  170 + .info_name {
  171 + margin-top: 5px;
  172 + display: flex;
  173 + justify-content: space-between;
  174 + .info_name_name {
  175 + margin-right: 10px;
  176 + font-size: 16px;
  177 + font-family: "PingFangSC-Semibold";
  178 + max-width: 592rpx;
  179 + }
  180 + .info_name_share {
  181 + display: flex;
  182 + flex-direction: column;
  183 + justify-content: space-between;
  184 + align-items: center;
  185 + margin-top: 14rpx;
  186 + > image {
  187 + height: 40rpx;
  188 + width: 40rpx;
  189 + }
  190 + > text {
  191 + font-family: PingFangSC-Regular;
  192 + font-size: 12px;
  193 + color: #999;
  194 + letter-spacing: -0.23px;
  195 + }
  196 + }
  197 + }
  198 + // 售后服务
  199 + .info_after {
  200 + font-size: 10px;
  201 + color: #999;
  202 + margin-top: 20rpx;
  203 + > span {
  204 + height: 14px;
  205 + margin-right: 10px;
  206 + }
  207 + }
  208 + }
  209 + // 详细信息
  210 + .detail_info {
  211 + .screen_bar {
  212 + width: 670rpx;
  213 + margin-top: 20rpx;
  214 + margin-bottom: 24rpx;
  215 + display: flex;
  216 + flex-direction: row;
  217 + justify-content: space-between;
  218 + align-items: center;
  219 + font-size: 14px;
  220 + color: #333333;
  221 + transition: all 0.2s;
  222 + }
  223 + .item_active {
  224 + border-bottom: 4rpx solid #ff6b4a;
  225 + }
  226 + .screen_item {
  227 + font-size: 32rpx;
  228 + color: #333333;
  229 + display: flex;
  230 + transition: all 0.2s;
  231 + }
  232 + }
  233 +}
  234 +</style>
... ...
src/pages/frameDetail/components/BottomSheet.vue
... ... @@ -0,0 +1,1232 @@
  1 +<template>
  2 + <view class="content">
  3 + <view
  4 + class="sheet"
  5 + :class="{sheetShow:isShowBottom,sheeHide:!isShowBottom}"
  6 + @touchmove.stop.prevent="moveHandle"
  7 + @click="closeSheet()"
  8 + >
  9 + <scroll-view
  10 + scroll-y="true"
  11 + class="sheetView"
  12 + :class="{sheetView_active:isShowBottom}"
  13 + @click.stop="stopEvent()"
  14 + >
  15 + <view class="content">
  16 + <view class="goodInfo">
  17 + <view class="imageWrap">
  18 + <image
  19 + :src="goodInfo.img_index_url"
  20 + mode="aspectFill"
  21 + style="width: 188rpx;height: 168rpx;"
  22 + ></image>
  23 + </view>∂
  24 + <view class="infoRight">
  25 + <text class="goodName">{{goodInfo.p_name}}</text>
  26 + <text class="remarks">支持7天无理由退货 顺丰发货</text>
  27 + <view class="priceBox">
  28 + <view class="price">¥{{goodInfo.priceArea.Min_Price || '暂无'}}</view>
  29 + <text>(限购{{maxCount}}副)</text>
  30 + <view class="counter">
  31 + <view
  32 + class="btn"
  33 + disabled="this.addDisabled"
  34 + type="default"
  35 + @click="counter(false)"
  36 + >-</view>
  37 + <text>{{count}}</text>
  38 + <view
  39 + class="btn"
  40 + disabled="this.desDisabled"
  41 + type="default"
  42 + @click="counter(true)"
  43 + >+</view>
  44 + </view>
  45 + </view>
  46 + </view>
  47 + </view>
  48 + <view class="peopleChoose">
  49 + <view class="title">选择使用人</view>
  50 + <view class="loveList">
  51 + <view
  52 + class="peopleName"
  53 + v-for="(item,index) in loveList"
  54 + :key='index'
  55 + :class="{ active2: loveCurrent === index }"
  56 + @click="onClickLoveItem(index,item.name)"
  57 + >
  58 + {{item.name}}
  59 + </view>
  60 + </view>
  61 + </view>
  62 + <view class="goods-data">
  63 + <view class="opCollapse">
  64 + <view class="body">
  65 + <template v-if="opIsOpen">
  66 + <view class="goods-form">
  67 + <view class="p1">
  68 + <image
  69 + class="image2"
  70 + src="../../../static/img/myOpticsData/dataWrite.png"
  71 + mode="aspectFit"
  72 + ></image>
  73 + 填写验光数据
  74 + </view>
  75 + <text class="p2">没有验光数据?请到线下眼镜店验光哦~</text>
  76 + <view class="picker">
  77 + <view class="picker-choice">
  78 + <view class="choice-left">
  79 + <text class="pd">验光单取名:</text>
  80 + </view>
  81 + <input
  82 + type="text"
  83 + @blur="handleInput"
  84 + class="input"
  85 + placeholder="请输入名称"
  86 + maxlength="20"
  87 + :value="name"
  88 + />
  89 + </view>
  90 + </view>
  91 + <view class="picker">
  92 + <view class="picker-choice">
  93 + <view class="choice-left">
  94 + <text class="p11">{{pickerInfoList[0].nameC}}</text>
  95 + <text class="p12">{{pickerInfoList[0].nameE}}</text>
  96 + </view>
  97 + <text class="p13">左&nbsp;&nbsp;&nbsp;(OD)</text>
  98 + <!-- <text class="p14">{{pickerInfoList[0].nameArray1[pickerInfoList[0].nameIndex1]}}</text> -->
  99 + <picker
  100 + @change="bindPickerChange01"
  101 + :value="pickerInfoList[0].nameIndex1"
  102 + :range="pickerInfoList[0].nameArray1"
  103 + >
  104 + <view class="p14">
  105 + {{pickerInfoList[0].nameArray1[pickerInfoList[0].nameIndex1]}}
  106 + <image src="../../../static/detail-tabicon.png"></image>
  107 + </view>
  108 + <!-- <image src="../../../static/detail-tabicon.png" ></image> -->
  109 + </picker>
  110 + <text class="p13">右&nbsp;&nbsp;&nbsp;(OS)</text>
  111 + <!-- <text class="p14">{{pickerInfoList[0].nameArray2[pickerInfoList[0].nameIndex2]}}</text> -->
  112 + <picker
  113 + @change="bindPickerChange02"
  114 + :value="pickerInfoList[0].nameIndex2"
  115 + :range="pickerInfoList[0].nameArray2"
  116 + >
  117 + <view class="p14">
  118 + {{pickerInfoList[0].nameArray2[pickerInfoList[0].nameIndex2]}}
  119 + <image src="../../../static/detail-tabicon.png"></image>
  120 + </view>
  121 + <!-- <image src="../../../static/detail-tabicon.png" ></image> -->
  122 + </picker>
  123 + </view>
  124 + </view>
  125 + <view class="picker">
  126 + <view class="picker-choice">
  127 + <view class="choice-left">
  128 + <text class="p11">{{pickerInfoList[1].nameC}}</text>
  129 + <text class="p12">{{pickerInfoList[1].nameE}}</text>
  130 + </view>
  131 + <text class="p13">左&nbsp;&nbsp;&nbsp;(OD)</text>
  132 + <!-- <text class="p14">{{pickerInfoList[1].nameArray1[pickerInfoList[1].nameIndex1]}}</text> -->
  133 + <picker
  134 + @change="bindPickerChange11"
  135 + :value="pickerInfoList[1].nameIndex1"
  136 + :range="pickerInfoList[1].nameArray1"
  137 + >
  138 + <view class="p14">
  139 + {{pickerInfoList[1].nameArray1[pickerInfoList[1].nameIndex1]}}
  140 + <image src="../../../static/detail-tabicon.png"></image>
  141 + </view>
  142 + <!-- <image src="../../../static/detail-tabicon.png" ></image> -->
  143 + </picker>
  144 + <text class="p13">右&nbsp;&nbsp;&nbsp;(OS)</text>
  145 + <!-- <text class="p14">{{pickerInfoList[1].nameArray2[pickerInfoList[1].nameIndex2]}}</text> -->
  146 + <picker
  147 + @change="bindPickerChange12"
  148 + :value="pickerInfoList[1].nameIndex2"
  149 + :range="pickerInfoList[1].nameArray2"
  150 + >
  151 + <view class="p14">
  152 + {{pickerInfoList[1].nameArray2[pickerInfoList[1].nameIndex2]}}
  153 + <image src="../../../static/detail-tabicon.png"></image>
  154 + </view>
  155 + <!-- <image src="../../../static/detail-tabicon.png" ></image> -->
  156 + </picker>
  157 + </view>
  158 + </view>
  159 + <view class="picker">
  160 + <view class="picker-choice">
  161 + <view class="choice-left">
  162 + <text class="p11">{{pickerInfoList[2].nameC}}</text>
  163 + <text class="p12">{{pickerInfoList[2].nameE}}</text>
  164 + </view>
  165 + <text class="p13">左&nbsp;&nbsp;&nbsp;(OD)</text>
  166 + <picker
  167 + @change="bindPickerChange21"
  168 + :value="pickerInfoList[2].nameIndex1"
  169 + :range="pickerInfoList[2].nameArray1"
  170 + >
  171 + <view class="p14">
  172 + {{pickerInfoList[2].nameArray1[pickerInfoList[2].nameIndex1]}}
  173 + <image src="../../../static/detail-tabicon.png"></image>
  174 + </view>
  175 + </picker>
  176 + <text class="p13">右&nbsp;&nbsp;&nbsp;(OS)</text>
  177 + <!-- <text class="p14">{{pickerInfoList[2].nameArray2[pickerInfoList[2].nameIndex2]}}</text> -->
  178 + <picker
  179 + @change="bindPickerChange22"
  180 + :value="pickerInfoList[2].nameIndex2"
  181 + :range="pickerInfoList[2].nameArray2"
  182 + >
  183 + <view class="p14">
  184 + {{pickerInfoList[2].nameArray2[pickerInfoList[2].nameIndex2]}}
  185 + <image src="../../../static/detail-tabicon.png"></image>
  186 + </view>
  187 + <!-- <image src="../../../static/detail-tabicon.png" ></image> -->
  188 + </picker>
  189 + </view>
  190 + </view>
  191 + <view class="picker">
  192 + <view class="picker-choice">
  193 + <view class="choice-left">
  194 + <text class="pd">瞳距:</text>
  195 + </view>
  196 + <input
  197 + type="digit"
  198 + @change="handleInputPd"
  199 + class="input"
  200 + placeholder="请输入瞳距,单位cm"
  201 + maxlength="20"
  202 + :value="pd"
  203 + />
  204 + </view>
  205 + </view>
  206 + <view class="picker">
  207 + <view class="picker-choice">
  208 + <view class="choice-left">
  209 + <text class="p11">{{pickerInfoList[3].nameC}}</text>
  210 + </view>
  211 + <text class="p13-date">年&nbsp;&nbsp;&nbsp;(Y)</text>
  212 + <picker
  213 + @change="bindPickerChange41"
  214 + :value="pickerInfoList[3].nameIndex1"
  215 + :range="pickerInfoList[3].nameArray1"
  216 + >
  217 + <view
  218 + class="p14"
  219 + style="width: 30px;"
  220 + >
  221 + {{pickerInfoList[3].nameArray1[pickerInfoList[3].nameIndex1]}}
  222 + <image src="../../../static/detail-tabicon.png"></image>
  223 + </view>
  224 + </picker>
  225 + <text class="p13-date">月&nbsp;&nbsp;&nbsp;(M)</text>
  226 + <picker
  227 + @change="bindPickerChange42"
  228 + :value="pickerInfoList[3].nameIndex2"
  229 + :range="pickerInfoList[3].nameArray2"
  230 + >
  231 + <view
  232 + class="p14"
  233 + style="width: 30px;"
  234 + >
  235 + {{pickerInfoList[3].nameArray2[pickerInfoList[3].nameIndex2]}}
  236 + <image src="../../../static/detail-tabicon.png"></image>
  237 + </view>
  238 + </picker>
  239 + <text class="p13-date">日&nbsp;&nbsp;&nbsp;(D)</text>
  240 + <picker
  241 + @change="bindPickerChange43"
  242 + :value="pickerInfoList[3].nameIndex3"
  243 + :range="pickerInfoList[3].nameArray3"
  244 + >
  245 + <view
  246 + class="p14"
  247 + style="width: 30px;"
  248 + >
  249 + {{pickerInfoList[3].nameArray3[pickerInfoList[3].nameIndex3]}}
  250 + <image src="../../../static/detail-tabicon.png"></image>
  251 + </view>
  252 + </picker>
  253 + </view>
  254 + </view>
  255 + <view class="confirm">
  256 + <image
  257 + class="image1"
  258 + :src="confirm ? tabicon[0] : tabicon[1]"
  259 + @tap="changeConfirm"
  260 + ></image>
  261 + <text>确认以上输入信息来源于我的验光数据!</text>
  262 + </view>
  263 + </view>
  264 + </template>
  265 + <template v-else>
  266 + <view
  267 + v-for="item in pickerInfoList"
  268 + :key="item.key"
  269 + class="bodyBox"
  270 + >
  271 + <template v-if="item.nameC==='验光日期'">
  272 + <text class="names">{{item.nameC}}</text>
  273 + <text style="margin-right: 5px;"